-
Notifications
You must be signed in to change notification settings - Fork 0
Custom Skins
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.
- In a datapack, create a JSON file under:
data/<your_namespace>/playermob_skins/<any_name>.json - 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" } - 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 | 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.
Every PlayerMob rolls its look once, at spawn. There are two skin systems:
-
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). -
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.
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
texturesproperty 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 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.
| 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. |
- Loader:
PlayerMobSkinReloadListener(SimpleJsonResourceReloadListener, folderplayermob_skins). - Schema/codec:
PlayerMobSkin - Registry:
PlayerMobSkinRegistry(pickRandomis whatfinalizeSpawncalls).
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.
Getting started
No-code (datapacks)
Java API
Patterns