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!