Skip to content

Custom Skins

Brennan Hatton edited this page Jun 7, 2026 · 1 revision

Custom Skins (Datapack)

PlayerMob loads its real-player skins from datapack JSON, using the same mechanism vanilla uses for loot tables and recipes. You can add skins with a datapack — no Java, no rebuild, no resource pack.


Quick start

  1. In a datapack, create a JSON file under:
    data/<your_namespace>/playermob_skins/<any_name>.json
    
  2. Give it a display name, a Mojang texture URL, and (optionally) a model:
    {
      "displayName": "Steve The Builder",
      "textureUrl": "http://textures.minecraft.net/texture/fd82a31be355fae3842af8a66a208df602230a0fc748c7453e491e08377eb4c2",
      "model": "wide"
    }
  3. Load the datapack and run /reload. New PlayerMobs can now roll your skin.

That's it. Each JSON file is one skin entry; drop in as many as you like. The file name only matters for log lines — it's the JSON contents that count.


Field reference

Field Required Type Notes
displayName non-blank string Informational only — never rendered in-game. Use it to document which player/skin this is.
textureUrl non-blank string A Mojang skin texture URL, http://textures.minecraft.net/texture/<hash>. See below.
model "wide" or "slim" Defaults to "wide". See the wide/slim caveat below.

A blank or malformed entry is skipped with a WARN log line — it does not break the reload, so one bad file won't wipe out the rest of the pack.


How skin selection works

Every PlayerMob rolls its look once, at spawn. There are two skin systems:

  1. Bundled vanilla skins — the 9 default Minecraft player skins (PlayerMobEntity.SKIN_COUNT = 9). Every mob always rolls one of these as its base (and as a safe fallback for old clients).
  2. Datapack URL skins — the entries you add here, pooled in PlayerMobSkinRegistry.

With probability ~30 % (URL_SKIN_CHANCE = 0.30f) a freshly-spawned mob overrides its bundled skin with a random URL skin from the registry; the other ~70 % keep a vanilla default. So most mobs read as "a player" at a glance, with recognisable custom skins as the occasional standout.

If the registry is empty, the 30 % roll is skipped entirely and every mob uses a bundled vanilla skin. Adding skins only ever adds to the 30 % pool.

PlayerMob ships its own built-in pack (a few dozen Mojang-staff and notable-community skins in the playermob namespace, under data/playermob/playermob_skins/). Your datapack entries are merged in alongside them. Because entries are keyed by file path, you can also override a built-in skin by shipping a file at the same data/playermob/playermob_skins/<name>.json path.


Getting a texture URL

The textureUrl is the pre-resolved, content-hashed URL Mojang's CDN serves a skin PNG from — e.g.:

http://textures.minecraft.net/texture/fd82a31be355fae3842af8a66a208df602230a0fc748c7453e491e08377eb4c2

These URLs are immutable (the hash is the content), which is exactly why PlayerMob stores the URL rather than a username: it never has to hit Mojang's rate-limited session API at runtime. You can obtain one by:

  • Decoding the base64 textures property from a player's profile (https://sessionserver.mojang.com/session/minecraft/profile/<uuid>?unsigned=false), or
  • Using any "Minecraft skin URL" lookup tool / site, or
  • Pointing it at any publicly-hosted 64×64 skin PNG that Mojang's texture server serves (custom skins work, not just real players').

Snapshot semantics. The URL is a snapshot. If the real player later changes their skin, your entry keeps showing the old one until you update the URL. For most packs that's fine.


The wide / slim caveat

The model field is parsed and stored, but v0.15.0 always renders with the wide (PlayerModel) arms. A "slim" entry is accepted by the loader and remembered, but renders with slightly-thick (wide) arms today. True slim-model swapping is a planned follow-up. Author slim entries if you want them future-proofed — just know they look wide for now.


Troubleshooting

Symptom Cause / fix
No custom skins ever appear Only ~30 % of mobs use a URL skin — spawn a handful. Confirm the datapack is enabled and you ran /reload.
One entry never appears Check the server log for a [playermob] skipping invalid skin … WARN — usually a blank/missing displayName or textureUrl.
Skin shows as the default Steve/Alex The texture URL didn't resolve (bad hash, or not a Mojang-served texture).
[playermob] loaded N skin(s) count looks low That log line (emitted on every reload) is the count actually accepted — compare it to how many files you shipped.

Under the hood

Want to pin a specific skin on a specific mob instead of relying on the random roll? Use the SkinTextureUrl NBT field — see Spawning and NBT.

Clone this wiki locally