While armor is a bit more complicated to implement than a normal block or item, once you understand it, it becomes simple to implement. To add armor, we'll first make a CustomArmorMaterial class, then register the items. We'll also take a look at how to texture them. There's a special chapter at the end of this document that explains how to add knockback to the armor, since the method is only accessible through a mixin (as of 1.16.3).
An example for this document can be found in this mod GitHub repository.
Since new armor needs to be set with a new name (as well as extra things like armor points and durability), we'll have to create a new class for our CustomArmorMaterial.
This class will implement ArmorMaterial, and it'll start by assigning values to armor points (called PROTECTION_VALUES). All its following arguments will make use of @Override.
public class CustomArmorMaterial implements ArmorMaterial { private static final int[] BASE_DURABILITY = new int[] {13, 15, 16, 11}; private static final int[] PROTECTION_VALUES = new int[] {A, B, C, D}; // In which A is boots, B leggings, C chestplate, and D helmet. // For reference, Leather uses {1, 2, 3, 1}, and Diamond/Netherite {3, 6, 8, 3} }
The next arguments are defined as follows (don't worry about the names, you'll see how we implement it below them):
SoundEvents.ITEM_ARMOR_EQUIP_X
, X being the type of armor.And the new value introduced on 1.16
I'll leave all variables written as X or A, B, C, D. With those arguments, it should now look something like this:
public class CustomArmorMaterial implements ArmorMaterial { private static final int[] BASE_DURABILITY = new int[] {13, 15, 16, 11}; private static final int[] PROTECTION_VALUES = new int[] {A, B, C, D}; @Override public int method_7696(EquipmentSlot slot) { return BASE_DURABILITY[slot.getEntitySlotId()] * X; } @Override public int method_7697(EquipmentSlot slot) { return PROTECTION_VALUES[slot.getEntitySlotId()]; } @Override public int getEnchantability() { return X; } @Override public SoundEvent getEquipSound() { return SoundEvents.ITEM_ARMOR_EQUIP_X; } @Override public Ingredient getRepairIngredient() { return Ingredient.ofItems(RegisterItems.X); } @Override // Must be all lowercase return "name"; } @Override public float getToughness() { return X.0F; } @Override public float getKnockbackResistance() { return 0.XF; } }
Now that you have the basics of the armor material class, let's register your armor items in a new class we'll simply call RegisterItems.
In the item tutorial, we've created a class TutorialItems
for items in the mod. Here we place them here, and use the convenient register
method we've introducted in the item tutorial.
public final class TutorialItems { // [...] public static final ArmorMaterial CUSTOM_ARMOR_MATERIAL = new CustomArmorMaterial(); public static final Item CUSTOM_MATERIAL = register(new CustomMaterialItem(new Item.Settings()), "custom_material"); // If you made a new material, this is where you would note it. public static final Item CUSTOM_MATERIAL_HELMET = register(new ArmorItem(CUSTOM_ARMOR_MATERIAL, EquipmentSlot.HEAD, new Item.Settings()), "custom_material_helmet"); public static final Item CUSTOM_MATERIAL_CHESTPLATE = register(new ArmorItem(CUSTOM_ARMOR_MATERIAL, EquipmentSlot.CHEST, new Item.Settings()), "custom_material_chestplate"); public static final Item CUSTOM_MATERIAL_LEGGINGS = register(new ArmorItem(CUSTOM_ARMOR_MATERIAL, EquipmentSlot.LEGS, new Item.Settings()), "custom_material_leggings"); public static final Item CUSTOM_MATERIAL_BOOTS = register(new ArmorItem(CUSTOM_ARMOR_MATERIAL, EquipmentSlot.FEET, new Item.Settings()), "custom_material_boots"); }
Your armor items are done. Now we'll just create a separate item group for that.
public final class TutorialItemGroups { public static final ItemGroup TEST_GROUP = FabricItemGroup.builder() .icon(() -> new ItemStack(TutorialItems.CUSTOM_MATERIAL)) // This uses the model of the new material you created as an icon, but you can reference to whatever you like .displayName(Text.translatable("itemGroup.tutorial.test_group")) .entries((context, entries) -> { entries.add(CUSTOM_MATERIAL) .add(CUSTOM_MATERIAL_HELMET) .add(CUSTOM_MATERIAL_CHESTPLATE) .add(CUSTOM_MATERIAL_LEGGINGS) .add(CUSTOM_MATERIAL_BOOTS); }) .build(); public static void initialize() { // Since 1.21: } }
If you did those above in the separate classes, remember to statically initialize the classes in your ModInitializer
, if you haven't done yet:
public class ExampleMod implements ModInitializer { [...] @Override public void onInitialize() { TutorialItems.initialize(); TUtorialItemGroups.initialize(); } }
That's it! Your armor should now exist in game, untextured still, but present and able to be given with /give.
Now we'll be assigning the textures to each piece.
We're going to assume you
x_helmet.png
, x_chestplate.png
etc.)x_layer_1.png
and x_layer_2.png
)And assign them to each armor item.
The following should be the same with all armor items, only changing which part are we using. We'll use helmet for our example.
{ "parent": "item/generated", "textures": { "layer0": "tutorial:item/custom_material_helmet" } }
Repeat with all armor items.
Generally, mod textures go under resources/assets/<modid>, however armor textures go specifically in the minecraft directory:
To give your on-body armor a texture, place X_layer_1.png
and X_layer_2.png
(where X is the getName
argument you chose in your armor material class) into 'resources/assets/minecraft/textures/models/armor'.
If you followed everything, you should now be able to have a full armor set!