Log summary
Every reload logs one line under the GltfValidation logger:
Validated N GLBs: X passed, Y with warnings, Z with errors.
The mod ships a structural GLB validator that inspects every item’s .glb model on each
resource reload and reports problems before you find them as a broken render in-game. It’s a
quick sanity pass, not a full glTF conformance checker — it reads the file’s header and JSON
chunk only, and flags the handful of mistakes that actually break TiedUp! skinning.
The validator opens each GLB, reads the 12-byte header and the first (JSON) chunk, then
inspects that JSON. It never decodes the binary mesh (BIN) chunk — no vertex positions, no
weight values, no triangles. That keeps it fast and lets it run on every model every reload, but
it also bounds what it can know:
| Checks | Does NOT check |
|---|---|
| Header magic / version / declared length | Per-vertex weight sums (needs the BIN chunk) |
A skins array exists and is non-empty | Bone names / typos against the biped (see below) |
inverseBindMatrices presence, type, count | Triangle count / poly budget |
WEIGHTS_0 / JOINTS_0 on the selected mesh | Embedded textures / materials |
| Multiple non-Player meshes (ambiguity) | UVs, normals, vertex colours |
An Idle animation exists | The actual mesh geometry |
| Animation channels target real skin joints |
F3+T, or after /reload).model GLB of every loaded data-driven item definition, not loose files on disk.So the loop is: edit your GLB → F3+T → check the result. You don’t need to relaunch the game.
Three places, in increasing detail:
Log summary
Every reload logs one line under the GltfValidation logger:
Validated N GLBs: X passed, Y with warnings, Z with errors.
Toast (errors only)
If any model has an error, a system toast pops: “N model(s) have errors. Run /tiedup validate”. Warnings do not toast.
/tiedup validate
The full per-file report, colour-coded, printed in chat. This is where you read the actual findings.
/tiedup validate command/tiedup validate # report every validated GLB/tiedup validate <item_id> # report one model or item (e.g. mymod:models/gltf/binds/wrist_cuffs.glb)Each finding prints as [SEVERITY] CODE: message, coloured red (error), yellow
(warning). A file with no errors is headed green; a file with an error is headed red.
There is no INFO output in practice — every finding the validator emits today is an error or a warning.
| Code | What it means | Fix |
|---|---|---|
MISSING_GLB | The item’s model resource location resolves to no file in any pack. | Check the model path in the item JSON and that the .glb is actually shipped at assets/<ns>/models/gltf/<category>/. |
INVALID_GLB_HEADER | Not a valid GLB: bad magic, wrong version, truncated, or the first chunk isn’t JSON. | Re-export as glTF Binary (.glb) — not .gltf (text), not a renamed .zip. A .gltf+.bin pair won’t pass; export the single binary .glb. |
GLB_TOO_LARGE | The file declares a size over the 50 MB safety cap. | Reduce mesh/texture size. A worn item should be a few hundred KB, not tens of MB. |
GLB_READ_ERROR | The file existed but couldn’t be read/parsed. | Re-export; the file is likely corrupt or partially written. |
NO_SKINS | No skins array, or it’s empty. The mesh isn’t rigged to a skeleton. | Select the mesh AND the armature before exporting, and enable skinning in the glTF exporter so a skin is written. |
IBM_MISSING_TYPE / IBM_WRONG_TYPE | The inverseBindMatrices accessor has no type, or it isn’t MAT4. | Re-export with the skin’s armature selected — these come from a malformed skinning export. |
IBM_COUNT_MISMATCH | The number of inverse-bind matrices ≠ the number of joints in the skin. | Re-export with the skin’s armature selected; don’t hand-edit the joints/IBM arrays out of sync. |
| Code | What it means | Fix |
|---|---|---|
IBM_MISSING | The skin has joints but no inverseBindMatrices. The runtime substitutes identity → mesh renders in bind pose at the origin. | Re-export with skinning enabled so the IBM accessor is written. |
NO_WEIGHTS | The selected mesh’s first primitive has no WEIGHTS_0 attribute → skinning won’t deform correctly. | Weight-paint the mesh to the armature and ensure the exporter includes vertex weights. |
NO_JOINTS | The first primitive has no JOINTS_0 → every vertex binds to joint 0, so the item sticks to the root bone regardless of how you painted it. | Same fix: paint weights and export with joint indices. |
MULTI_MESH_AMBIGUITY | More than one non-Player mesh in the file — the parser can’t be sure which one is your item. | Name your item mesh Item so it’s selected explicitly, or export a single mesh. |
NO_IDLE_ANIMATION | No animations array, or none named Idle. | Usually harmless for a static item (the pose comes from EF-JSON, not the GLB). Only matters if you intended a baked rest pose — most items can ignore this. |
ANIM_CHANNEL_NOT_IN_SKIN | Animation channels target nodes that aren’t in the skin’s joints — the runtime silently drops them. The classic cause: keyframing the Armature object instead of its bones. | In Blender, animate the bones, not the Armature object’s transform. |
When the validator (and the runtime parser) pick which mesh in the file is your item, they use the same rule:
Item wins immediately.Player_* mesh in the file is used.The WEIGHTS_0 / JOINTS_0 checks run against that selected mesh’s first primitive — so if
you ship multiple meshes, name the real one Item to be sure the validator (and the renderer)
look at the right one.
A typical static worn item — one skinned Item mesh, an armature, weights painted, exported as
binary glTF — passes with no errors and at most a NO_IDLE_ANIMATION warning you can ignore. If
you see that and nothing else, you’re good to equip and look. For anything that survived
validation but still renders wrong (bone misplacement, flat-white surface, dropped joints at
equip), continue to Common errors.