How the pack is built¶
Ember Forge builds one pack from every source, in a fixed order.
1. Merge base packs¶
Each zip in include-packs is merged underneath your items. Their dispatch
tables are read structurally and folded into one table per base material.
This matters more than it sounds. The client's range_dispatch picks the
nearest lower threshold, so an item whose exact id is missing from the pack
a player has renders as some unrelated model — not as nothing. Everything has
to live in one table or items quietly turn into each other.
pack.mcmeta from a base pack is not copied, but its overlay declarations
are carried across. Overlays are how a pack ships different assets per client
version; dropping the declaration leaves the overlay directories present but
unreachable, which blanks every vanilla item the source pack touched.
2. Write dispatch tables¶
For every base material, one assets/minecraft/items/<material>.json:
{"model":{"type":"minecraft:range_dispatch",
"property":"minecraft:custom_model_data",
"entries":[{"threshold":20001,"model":{"type":"minecraft:model","model":"mypack:item/ruby"}}],
"fallback":{"type":"minecraft:model","model":"minecraft:item/paper"}}}
The fallback is mandatory. Without it a plain paper — one with no custom model
data — renders as nothing at all.
3. Copy namespaced assets¶
Only namespaces other than minecraft are copied, so a content pack can never
overwrite a vanilla model for every player wearing the pack. Both layouts are
read:
Attempts to merge models/item, models/block, textures/item or
textures/block into the vanilla namespace are refused and logged.
4. Merge fonts¶
assets/minecraft/font/default.json providers are merged rather than
overwritten. Two packs shipping this file would otherwise fight, and one glyph
set would vanish silently.
5. Validate, then publish¶
Every dispatch entry is resolved: model file, parent chain, every texture. An entry that cannot render is removed so the item falls back to its plain base material. A vanilla model override that cannot render is deleted so the client uses its own built-in model.
[EmberForge] Pruned 41 unrenderable item entr(ies) and 0 vanilla model override(s);
1302 entries verified renderable.
References into the minecraft namespace that the pack does not ship are
assumed fine — those are vanilla assets the client already has.
Determinism¶
Entries are written sorted, with a fixed timestamp of 1980-01-01. Identical
input produces a byte-identical zip and therefore a stable SHA-1. If the hash
changed on every rebuild, every client that already downloaded the pack would
reject it.