Repository navigation
Feature Armor Appearance
Naturally-spawned armor now rolls two independent cosmetic effects at chest/pot/armor-stand generation time: leather pieces have a 30 % chance to be dyed with one of the 16 vanilla DyeColors, and any ArmorItem (leather, chainmail, iron, gold, diamond, netherite, turtle helmet) has an additional 15 % chance to receive an armor trim. Rolls run alongside the existing durability / enchantment / name gates, keyed on the same (world seed, carriage index, local pos, slot) mix — so the same chest at the same world seed always produces the same dyed-and-trimmed gear, even across reloads.
Crafted armor is untouched. The hook lives entirely inside ContainerContentsRoller.rollItemStack, which is the single entry point for items spawned into Dungeon Train containers, decorated pots, and armor stand loadouts. Crafting tables, anvils, vanilla loot tables outside the train, villager trades, and entity drops never enter this code path.
| Item | Trigger | Outcome |
|---|---|---|
leather_helmet / leather_chestplate / leather_leggings / leather_boots
|
30 % independent roll |
DataComponents.DYED_COLOR stamped with DyeColor#getTextureDiffuseColor — same RGB a vanilla dye-on-armor crafting recipe produces |
Color is picked uniformly from DyeColor.values() (16 entries: white, orange, magenta, light_blue, yellow, lime, pink, gray, light_gray, cyan, purple, blue, brown, green, red, black).
| Item | Trigger | Outcome |
|---|---|---|
Any ArmorItem instance |
15 % independent roll |
DataComponents.TRIM stamped with a random ArmorTrim(material, pattern)
|
Pattern: uniform random across every Holder.Reference<TrimPattern> registered in Registries.TRIM_PATTERN (covers all 19 vanilla patterns and any data-pack additions).
Material: weighted toward common metals so rare-gem trims feel rare:
| Weight | Materials | Approx. share |
|---|---|---|
| 3 | iron, copper, redstone, quartz | ~57 % |
| 2 | gold, lapis, amethyst | ~29 % |
| 1 | diamond, emerald, netherite | ~14 % |
A leather chestplate can roll both a dye (30 %) and a trim (15 %) on the same spawn — the two effects are independent.
Five new salts in ContainerContentsRoller keep the rolls keyed but independent — adding the feature does not perturb the existing durability / enchantment / name outcomes on old worlds:
-
SALT_DYE_CHANCE— does the dye effect fire? -
SALT_DYE_VALUE— which of the 16 colors? -
SALT_TRIM_CHANCE— does the trim effect fire? -
SALT_TRIM_PATTERN— which registered pattern? -
SALT_TRIM_MATERIAL— weighted material pick
All five feed the same mix(localPos, worldSeed, carriageIndex, slot, salt) helper used everywhere else in ContainerContentsRoller. The roll for slot N is independent of slot N±1, so toggling one effect doesn't shift the other.
DYED_COLOR and TRIM are vanilla data components — fully backward-compatible. Existing rolled items in old worlds keep their state; only newly-rolled items get the cosmetics. No save-format change, no migration step.
-
appearance/ArmorAppearanceRoller.java—maybeApplyDyeandmaybeApplyTrim, both stateless utilities. -
editor/ContainerContentsRoller.java— call sites immediately afterNameComposer.applyName(line 611 region).
- Procedural item naming — sibling cosmetic, shares the same hook and the same determinism keys.
- Carriage contents — defines the loot pools whose rolled items run through this pipeline.