Skip to content

Your First Item

This is the fil-rouge tour: build one simple restraint — a pair of wrist cuffs — from an empty Blender file all the way to wearing it in-game. It’s deliberately the minimum path. Each step links to its deep-dive page when you want the full reference.

By the end you’ll have these five files — the item definition (under data/) plus its visuals (under assets/), all in your one add-on pack:

data/mymod/tiedup_items/wrist_cuffs.json ← the item definition
assets/mymod/models/gltf/binds/wrist_cuffs.glb ← the mesh, texture baked inside
assets/mymod/models/item/wrist_cuffs.json ← the inventory icon model
assets/mymod/textures/item/wrist_cuffs.png ← the inventory icon sprite
assets/mymod/lang/en_us.json ← the display name

See Packaging for the full folder layout.

  1. Open the official 20-bone EF biped .blend (EpicFight Animation Rig.blend, bundled at docs/tools/ — a worked example with the cuffs already modeled lives in docs/object/artist object/). Don’t rebuild the skeleton by hand — one mistyped bone name and that joint is silently ignored at render time, with no error.
  2. Save a copy as wrist_cuffs.blend.
  3. Leave the armature in its rest pose (T-pose). You model on top of it.

Add a simple cuff mesh around each wrist. Keep it tight and low-poly:

  • Aim for ≤ 500 triangles (≤ 2000 acceptable — this renders on every nearby player, every frame).
  • UV-unwrap the mesh and bake your texture onto it (see Step 4 — the texture rides inside the .glb).
  • Model in the rest pose so the geometry sits correctly before deformation.

Skin each cuff to the hand it sits on:

PartSkin to
Left cuffHand_L
Right cuffHand_R
A chain between themblend Hand_RHand_L along its length

Rigid cuffs want a single bone per vertex at weight 1.0 — no blending. The renderer matches bones by name against the full biped, so a GLB that lists only Hand_R/Hand_L is perfectly fine — partial bone lists are optimal, not a limitation.

This is the step everyone gets wrong. Meshes use Blender’s built-in glTF exporternot the bundled Epic Fight JSON addon (that addon only makes animations).

  1. Select your mesh and the armature.
  2. File → Export → glTF 2.0 (.glb/.gltf).
  3. Format: glTF Binary (.glb). Under Data → Mesh keep UVs; under Material keep Images so the baked texture travels inside the file.
  4. Export to assets/mymod/models/gltf/binds/wrist_cuffs.glb.

The mesh lives under models/gltf/<category>/. binds is just the category folder — pick any name you like.

A textured .glb now renders its baked texture in-game ✅ Available. If you want player-recolorable zones later, author those zones in grayscale and name their materials with the tintable_ prefix (tintable_0, tintable_1, …) — see Tint & colors.

This is the heart of it, and it’s plain JSON — no Java, no tooling. Create data/mymod/tiedup_items/wrist_cuffs.json:

{
"type": "tiedup:bondage_item",
"display_name": "Wrist Cuffs",
"translation_key": "item.mymod.wrist_cuffs",
"model": "mymod:models/gltf/binds/wrist_cuffs.glb",
"icon": "mymod:item/wrist_cuffs",
"regions": [
"ARMS"
],
"pose_priority": 30,
"escape_difficulty": 100,
"components": {
"lockable": {},
"resistance": {
"id": "chain"
}
}
}

What each field does, briefly (full schema on Item JSON):

  • type — must be tiedup:bondage_item; any other value skips the whole definition.
  • display_name — required. Shown verbatim as the item name only when translation_key is omitted. If you set a translation_key, that key is what renders — and if its lang entry is missing you’ll see the raw key (item.mymod.wrist_cuffs), not this string. So always ship the lang entry (Step 7) when you use a translation_key.
  • model — the GLB resource location. The path is conventional; it only needs to be a valid id.
  • icon — the inventory sprite model (Step 6). Treat icon as required — omit it and the item shows the missing-texture sprite, because the default falls back to a texture that isn’t shipped.
  • regions — the body region(s) the item occupies. ARMS for wrist cuffs. See Bones & regions.
  • pose_priority — higher wins when two items animate the same joint; 1+ is recommended.
  • escape_difficulty — a difficulty value used when no resistance component is present: it’s the fallback struggle resistance and it also adds to the furniture-escape difficulty. Because the example below does ship a resistance component, that component (resistance.id) wins for the struggle resistance and this field is only the fallback. Keep it set as a sane default anyway.
  • components — gameplay behaviors. lockable: {} lets a padlock attach; resistance.id picks a built-in difficulty preset. The registered keys are rope, chain, armbinder, wrap, straitjacket, latex_sack, ribbon, vine, web, slime, tape, gag, blindfold, collar. An unrecognized id silently falls back to 100. Full list on Components.

The icon field points at a normal Minecraft item model. Create assets/mymod/models/item/wrist_cuffs.json:

{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "mymod:item/wrist_cuffs"
}
}

Then drop the 2D sprite at assets/mymod/textures/item/wrist_cuffs.png (16×16 is standard). This icon is what shows in the hotbar and inventory — it’s separate from the 3D .glb worn on the body.

Give the translation_key a display string. Create or extend assets/mymod/lang/en_us.json:

{
"item.mymod.wrist_cuffs": "Wrist Cuffs"
}
  1. Put all five files inside your add-on pack folder under config/tiedup/packs/<addon-name>/ — the data/ half (item JSON) and the assets/ half (GLB, icon model, icon texture, lang) live in the same folder (see Packaging).
  2. Run /reload to pick up the item JSON, then press F3+T to reload client resources (the GLB mesh, icon texture and lang only refresh on a resource reload, not on /reload). A freshly dropped pack is also picked up automatically the next time the world loads.
  3. Give yourself the item — it should appear with your icon and lang name.
  4. Equip it on the ARMS slot and confirm the cuffs render on the body with the baked texture.

Item JSON reference

Every field, every default, every caveat. Item JSON

Components

Locks, resistance, gagging, GPS, shock, ownership, built-in locks. Components

Animations

EF-JSON clips, the constructor block, FULL_BODY vs OVERLAY, per-joint pose nudges. Animations

Tint & colors

Player-recolorable zones with tintable_* materials. Tint & colors