Overview & content pipeline
Where datapack (data/) vs. resourcepack (assets/) files live, and how a combined pack is
laid out. → Overview
TiedUp!‘s NPCs (kidnappers, damsels, maids, guards…) pick their appearance from a pool of data-driven skins. A skin is two files: a tiny JSON describing it, plus the texture PNG it points at. Add a JSON + PNG pair to your addon pack and the matching NPC type starts rolling your skin into its random pool — no Java, no model work.
A skin is the JSON (under data/) plus its texture (under assets/) — both live in your one addon
pack. See Packaging for the full folder layout; within it, your two files go
here:
data/<namespace>/skins/<entity-type>/<skin-id>.json ← the definitionassets/tiedup/textures/entity/<…>/<skin-id>.png ← the textureYou only add files — you never edit a shipped one. The <skin-id> part of the filename is
conventional; the actual id comes from the JSON’s id field (see the schema).
Only id is required; everything else has a default.
| Field | Type | Default | Notes |
|---|---|---|---|
id | string | — | Required. The skin id. Also the PNG filename (<id>.png) and the registry key. Must be unique within the type. |
hasSlimArms | bool | false | true = Alex (3px) arms, false = Steve (4px) arms. Matches how you authored the texture. |
defaultName | string | "NPC" | Display name shown for an NPC wearing this skin. |
gender | string | "female" | "male" or "female" (case-insensitive). Anything else falls back to female. Drives model/voice/text selection. |
texture | string (resource location) | derived | Optional. Explicit texture under any namespace, e.g. "mypack:textures/entity/damsel/foo.png". Used verbatim when present; omit it to auto-derive tiedup:textures/entity/<type>/<id>.png. |
The smallest valid definition — id only (gets Steve arms, name "NPC", female):
{ "id": "anastasia"}What the shipped skins actually look like:
{ "id": "anastasia", "hasSlimArms": true, "defaultName": "Anastasia"}A male kidnapper with classic arms:
{ "id": "dean", "hasSlimArms": false, "defaultName": "Dean", "gender": "male"}These are the only ten folder names that are scanned. The folder is the entity type; the texture sub-path is auto-mapped (note several differ from the folder name).
skins/ folder (entity type) | NPC | Texture folder → assets/tiedup/textures/entity/… |
|---|---|---|
kidnapper | Kidnapper | kidnapper/ |
kidnapper_elite | Elite kidnapper | kidnapper/elite/ |
kidnapper_archer | Archer kidnapper | kidnapper/archer/ |
kidnapper_merchant | Merchant kidnapper | kidnapper/merchant/ |
maid | Maid | kidnapper/maid/ |
slave_trader | Trader | kidnapper/trader/ |
labor_guard | Guard | guard/ |
master | Master | master/ |
damsel | Damsel | damsel/ |
damsel_shiny | Shiny damsel | damsel/shiny/ |
So a skin id: "athena" placed in data/<ns>/skins/kidnapper_elite/ looks for its texture at
assets/tiedup/textures/entity/kidnapper/elite/athena.png — the JSON folder and the PNG folder are
not the same string for the special-cased types in the table above.
/reload (or restart) your skins are rescanned. An NPC of that type then picks a
random skin from the pool at spawn — more JSON files mean more variety.id per type: a second skin with an already-used id is dropped, not merged.id) is skipped and the rest still load — if a skin
doesn’t appear, you’ll see a warning in the log.An NPC’s display name comes from its skin’s defaultName — except numbered “mob” skins
(ids like dam_mob_1, knp_mob_1, …), which get a random name from a gender-matched pool.
Those pools are data-driven too. Add names by dropping JSON in data/<namespace>/tiedup_npc_names/:
{ "gender": "female", "names": ["Mireille", "Soraya", "Bao"] }| Field | Notes |
|---|---|
gender | "female" or "male". A name is only drawn from the pool matching the NPC’s gender. |
names | array of strings; blank entries are ignored. |
Your file merges into the pool (it never replaces the built-in names), so you only add. The picked name travels to clients with the entity, so a name pool installed on the server only works in multiplayer — no client copy needed. Male NPCs draw from the male pool (a small male pool ships by default); if a gender’s pool is empty, names fall back to the other gender, then to a built-in shortlist.
assets/tiedup/textures/entity/damsel/rosalind.png (the tiedup namespace, the
damsel/ folder from the type table, filename = your id).data/<your-ns>/skins/damsel/rosalind.json:
{ "id": "rosalind", "hasSlimArms": true, "defaultName": "Rosalind", "gender": "female"}/reload (or restart). Your skin joins the damsel pool, and new damsels can roll it.