User Tools

Site Tools


tutorial:armor

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
tutorial:armor [2020/10/09 20:50] – [Adding Knockback Protection] sakiratutorial:armor [2023/08/20 10:19] (current) – [Texturing] wjz_p
Line 3: Line 3:
 ==== Introduction ==== ==== Introduction ====
  
-While Armor is a bit more complicated to add then a normal block/item, once you can understand it, it becomes simple to make. +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)
-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 [[https://github.com/gdude2002/Gilded-Netherite|this mod GitHub repository]]
  
 ==== Creating an Armor Material class ==== ==== Creating an Armor Material class ====
Line 11: Line 11:
 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.  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.+This class will implement <yarn class_1741>, and it'll start by assigning values to armor points (called PROTECTION_VALUES). All its following arguments will make use of @Override.
  
-<code java [enable_line_numbers="true"]> +<yarncode java [enable_line_numbers="true"]> 
-public class CustomArmorMaterial implements ArmorMaterial +public class CustomArmorMaterial implements class_1741 
-    private static final int[] BASE_DURABILITY = new int[] {13, 15, 16, 11}; + private static final int[] BASE_DURABILITY = new int[] {13, 15, 16, 11}; 
-    private static final int[] PROTECTION_VALUES = new int[] {A, B, C, D};  + private static final int[] PROTECTION_VALUES = new int[] {A, B, C, D};  
-     + 
-    // In which A is helmet, B chestplate, C leggings and D boots.  + // 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}+ // For reference, Leather uses {1, 2, 3, 1}, and Diamond/Netherite {3, 6, 8, 3}
 } }
-</code>+</yarncode>
  
 The next arguments are defined as follows (don't worry about the names, you'll see how we implement it below them): The next arguments are defined as follows (don't worry about the names, you'll see how we implement it below them):
  
-  - getDurability: how many hits can armor take before breaking. Uses the int we wrote on 'BASE_DURABILITY' to calculate. Leather uses 5, Diamond 33, Netherite 37. +  - <yarn method_7696>: how many hits can armor take before breaking. Uses the int we wrote on 'BASE_DURABILITY' to calculate. Leather uses 5, Diamond 33, Netherite 37. 
-  - getPretectionAmount: calls for the 'PROTECTION_VALUES' int we already wrote above. +  - <yarn method_7697>: calls for the 'PROTECTION_VALUES' int we already wrote above. 
-  - getEnchantability: This will be how likely the armor can get high level or multiple enchantments in an enchantment book. +  - <yarn method_7699>: This will be how likely the armor can get high level or multiple enchantments in an enchantment book. 
-  - SoundEvent getEquipSound: The standard used by vanilla armor is ''SoundEvents.ITEM_ARMOR_EQUIP_X'', X being the type of armor. +  - <yarn class_3414 method_7698>: The standard used by vanilla armor is ''<yarn class_3417>.ITEM_ARMOR_EQUIP_X'', X being the type of armor. 
-  - Ingredient getRepairIngridient: what item are we gonna be using to repair the armor on an anvil. It can be either a vanilla item or one of your own. +  - <yarn class_1856 method_7695>: what item are we gonna be using to repair the armor on an anvil. It can be either a vanilla item or one of your own. 
-  - String getName: what the parent item of the armor is. In Diamond armor, it'd be "diamond"+  - String <yarn method_7694>: what the parent item of the armor is. In Diamond armor, it'd be "diamond"
-  - getToughness: This is a second protection value where the armor is more durable against high value attacks. Value goes as 'X.0F'+  - <yarn method_7700>: This is a second protection value where the armor is more durable against high value attacks. Value goes as 'X.0F'
  
 And the new value introduced on 1.16 And the new value introduced on 1.16
-  - getKnockbackResistance: leave this value at 0. If you want to implement it, write '0.XF' (in which X is how much knockback protection you want), and I'll teach you how to make it work later on.+  - <yarn method_24355>: leave this value at 0. If you want to implement it, write '0.XF' (in which X is how much knockback protection you want), and I'll teach you how to make it work later on.
  
  
 I'll leave all variables written as X or A, B, C, D. With those arguments, it should now look something like this: I'll leave all variables written as X or A, B, C, D. With those arguments, it should now look something like this:
  
-<code java [enable_line_numbers="true"]> +<yarncode java [enable_line_numbers="true"]> 
-public class CustomArmorMaterial implements ArmorMaterial +public class CustomArmorMaterial implements class_1741 
-    private static final int[] BASE_DURABILITY = new int[] {13, 15, 16, 11}; + private static final int[] BASE_DURABILITY = new int[] {13, 15, 16, 11}; 
-    private static final int[] PROTECTION_VALUES = new int[] {A, B, C, D};+ private static final int[] PROTECTION_VALUES = new int[] {A, B, C, D};
  
-    @Override + @Override 
-    public int getDurability(EquipmentSlot slot) { + public int method_7696(class_1304 slot) { 
-        return BASE_DURABILITY[slot.getEntitySlotId()] * X; + return BASE_DURABILITY[slot.method_5927()] * X; 
-    }+ }
  
-    @Override + @Override 
-    public int getProtectionAmount(EquipmentSlot slot) { + public int method_7697(class_1304 slot) { 
-        return PROTECTION_VALUES[slot.getEntitySlotId()]; + return PROTECTION_VALUES[slot.method_5927()]; 
-    }+ }
  
-    @Override + @Override 
-    public int getEnchantability() { + public int method_7699() { 
-        return X; + return X; 
-    }+ }
  
-    @Override + @Override 
-    public SoundEvent getEquipSound() { + public class_3414 method_7698() { 
-        return SoundEvents.ITEM_ARMOR_EQUIP_X; + return class_3417.ITEM_ARMOR_EQUIP_X; 
-    }+ }
  
-    @Override + @Override 
-    public Ingredient getRepairIngredient() { + public class_1856 method_7695() { 
-        return Ingredient.ofItems(RegisterItems.X); + return class_1856.method_8091(RegisterItems.X); 
-    }+ }
  
-    @Override + @Override 
-    public String getName() { + public String method_7694() { 
-        return "name"; + // Must be all lowercase 
-    }+ return "name"; 
 + }
  
-    @Override + @Override 
-    public float getToughness() { + public float method_7700() { 
-        return X.0F; + return X.0F; 
-    }+ }
  
-    @Override + @Override 
-    public float getKnockbackResistance() { + public float method_24355() { 
-        return 0.XF; + return 0.XF; 
-    }+ }
 } }
-</code>+</yarncode>
  
  
Line 91: Line 92:
 ==== Creating Armor Items ==== ==== Creating Armor Items ====
  
-We're gonna make a new class called RegisterItems to implement your new armor pieces. This will also be the place to, for example, register tools, if you're making a new item like an ingot (We'll refer to this as a "Custom_Material"). This setup will also put the items on a new Creative tab, but you're free to delete that part+We're gonna make a new class called RegisterItems to implement your new armor pieces. This will also be the place to, for example, register tools, if you're making a new item like an ingot (We'll refer to this as a "Custom_Material").
  
-The syntax of groups is //.group(YourModName.YOUR_MOD_NAME_BUT_IN_CAPS_GROUP)//. I'll be referring to it as ExampleMod: +<yarncode java [enable_line_numbers="true"]>
- +
-<code java [enable_line_numbers="true"]>+
 public class RegisterItems { public class RegisterItems {
  
-   public static final ArmorMaterial customArmorMaterial = new CustomArmorMaterial(); +    public static final class_1741 CUSTOM_ARMOR_MATERIAL = new CustomArmorMaterial(); 
-   public static final Item CUSTOM_MATERIAL = new CustomMaterialItem(new Item.Settings().group(ExampleMod.EXAMPLE_MOD_GROUP));+    public static final class_1792 CUSTOM_MATERIAL = new CustomMaterialItem(new class_1792.class_1793());
     // If you made a new material, this is where you would note it.     // If you made a new material, this is where you would note it.
-    public static final Item CUSTOM_MATERIAL_HELMET = new ArmorItem(CustomArmorMaterialEquipmentSlot.HEAD, new Item.Settings().group(ExampleMod.EXAMPLE_MOD_GROUP)); +    public static final class_1792 CUSTOM_MATERIAL_HELMET = new class_1738(CUSTOM_ARMOR_MATERIALclass_1304.field_6169, new class_1792.class_1793()); 
-    public static final Item CUSTOM_MATERIAL_CHESTPLATE = new ArmorItem(CustomArmorMaterialEquipmentSlot.CHEST, new Item.Settings().group(ExampleMod.EXAMPLE_MOD_GROUP)); +    public static final class_1792 CUSTOM_MATERIAL_CHESTPLATE = new class_1738(CUSTOM_ARMOR_MATERIALclass_1304.field_6174, new class_1792.class_1793()); 
-    public static final Item CUSTOM_MATERIAL_LEGGINGS = new ArmorItem(CustomArmorMaterialEquipmentSlot.LEGS, new Item.Settings().group(ExampleMod.EXAMPLE_MOD_GROUP)); +    public static final class_1792 CUSTOM_MATERIAL_LEGGINGS = new class_1738(CUSTOM_ARMOR_MATERIALclass_1304.field_6172, new class_1792.class_1793()); 
-    public static final Item CUSTOM_MATERIAL_BOOTS = new ArmorItem(CustomArmorMaterialEquipmentSlot.FEET, new Item.Settings().group(ExampleMod.EXAMPLE_MOD_GROUP));+    public static final class_1792 CUSTOM_MATERIAL_BOOTS = new class_1738(CUSTOM_ARMOR_MATERIALclass_1304.field_6166, new class_1792.class_1793());
  
 } }
-</code>+</yarncode>
  
-Now that your items are properly created, lets register them and give them proper names. Your first parameter is going to be your namespace, which is your ModID, and then next one the name you want to give to your item.+Now that your items are properly created, let'register them and give them proper names. Your first parameter is going to be your namespace, which is your mod ID, and then next one the name you want to give to your item.
  
-We'll be writing this right below your last ArmorItem.+We'll be writing this right below your last <yarn class_1738>.
  
-<code java [enable_line_numbers="true"]> +<yarncode java [enable_line_numbers="true"]> 
- public static void register() { +public static void register() { 
-        Registry.register(Registry.ITEM, new Identifier("examplemod", "custom_material"), CUSTOM_MATERIAL); +    class_2378.method_10230(class_7923.field_41178, new class_2960("tutorial", "custom_material"), CUSTOM_MATERIAL); 
-        Registry.register(Registry.ITEM, new Identifier("examplemod", "custom_material_helmet"), CUSTOM_MATERIAL_HELMET); +    class_2378.method_10230(class_7923.field_41178, new class_2960("tutorial", "custom_material_helmet"), CUSTOM_MATERIAL_HELMET); 
-        Registry.register(Registry.ITEM, new Identifier("examplemod", "custom_material_chestplate"), CUSTOM_MATERIAL_CHESTPLATE); +    class_2378.method_10230(class_7923.field_41178, new class_2960("tutorial", "custom_material_chestplate"), CUSTOM_MATERIAL_CHESTPLATE); 
-        Registry.register(Registry.ITEM, new Identifier("examplemod", "custom_material_leggings"), CUSTOM_MATERIAL_LEGGINGS); +    class_2378.method_10230(class_7923.field_41178, new class_2960("tutorial", "custom_material_leggings"), CUSTOM_MATERIAL_LEGGINGS); 
-        Registry.register(Registry.ITEM, new Identifier("examplemod", "custom_material_boots"), CUSTOM_MATERIAL_BOOTS); +    class_2378.method_10230(class_7923.field_41178, new class_2960("tutorial", "custom_material_boots"), CUSTOM_MATERIAL_BOOTS); 
-    +
-</code>+</yarncode>
  
 Your armor items are done. Now we'll just call the Registry on our main class (and annotate the new group). Your armor items are done. Now we'll just call the Registry on our main class (and annotate the new group).
  
-<code java [enable_line_numbers="true"]> +<yarncode java [enable_line_numbers="true"]> 
-public static final ItemGroup EXAMPLE_MOD_GROUP = FabricItemGroupBuilder.create( +public static final class_1761 EXAMPLE_MOD_GROUP = FabricItemGroupBuilder.create( 
-            new Identifier("examplemod", "example_mod_group")) +    new class_2960("tutorial", "example_mod_group")) 
-            .icon(() -> new ItemStack(RegisterItems.CUSTOM_MATERIAL)) // This uses the model of the new material you created as an icon, but you can reference to whatever you like +    .icon(() -> new class_1799(RegisterItems.CUSTOM_MATERIAL)) // This uses the model of the new material you created as an icon, but you can reference to whatever you like 
-            .build();+    .build();
  
 @Override @Override
-    public void onInitialize() { +public void onInitialize() { 
-        RegisterItems.register(); +    RegisterItems.register(); 
-    +
-</code>+</yarncode>
  
 That's it! Your armor should now exist in game, untextured still, but present and able to be given with /give. That's it! Your armor should now exist in game, untextured still, but present and able to be given with /give.
Line 153: Line 152:
 The following should be the same with all armor items, only changing which part are we using. We'll use helmet for our example. The following should be the same with all armor items, only changing which part are we using. We'll use helmet for our example.
  
-<code JavaScript resources/assets/examplemod/models/item/custom_material_helmet.json>+<code JSON resources/assets/tutorial/models/item/custom_material_helmet.json>
 { {
-  "parent": "item/generated", + "parent": "item/generated", 
-  "textures":+ "textures":
-    "layer0": "examplemod:item/custom_material_helmet" + "layer0": "tutorial:item/custom_material_helmet" 
-  } + }
 } }
 </code> </code>
Line 165: Line 163:
 Repeat with all armor items. Repeat with all armor items.
  
-To give your on-body armor a texture, you'll simply put the layer_1.png and layer_2.png on 'resources/assets/minecraft/textures/models/armor'.+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 <yarn method_7694> 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! 
  
-====Adding Knockback Protection==== 
  
-And here comes the so very cursed! +If you followed everythingyou should now be able to have a full armor set!
- +
-Mojang decided that they were not only going to hardcode getKnockbackResistance, but they were also gonna make it immutable! Fun stuff. +
- +
-To get around this, we're gonna make a mixin that goes into ArmorItem. If this is your first time[[tutorial:mixin_registration|here's how to register mixins on your fabric.mod.json]] +
- +
-We'll make a class called ArmorItemMixin, and write: +
- +
-<code java [enable_line_numbers:"true"]> +
-@Mixin (ArmorItem.class) +
-public abstract class ArmorItemMixin { +
- +
-+
-</code> +
- +
-Now we have to make @Shadow to modify knockbackResistance, which is and EntityAttribute +
- +
-<code java [enable_line_numbers:"true"]> +
-@Mixin (ArmorItem.class) +
-public abstract class ArmorItemMixin { +
- +
-    @Shadow @Final private static UUID[] MODIFIERS; +
-    @Shadow @Final @Mutable private Multimap<EntityAttribute, EntityAttributeModifier> attributeModifiers; +
-    @Shadow @Final protected float knockbackResistance; +
-     +
-+
-</code> +
- +
-Next we @Inject our GENERIC_KNOCKBACK_RESISTANCE into the ArmorMaterial constructor. +
- +
-<code java [enable_line_numbers:"true"]> +
-@Mixin (ArmorItem.class) +
-public abstract class ArmorItemMixin { +
- +
-    @Shadow @Final private static UUID[] MODIFIERS; +
-    @Shadow @Final @Mutable private Multimap<EntityAttribute, EntityAttributeModifier> attributeModifiers; +
-    @Shadow @Final protected float knockbackResistance; +
-     +
-    @Inject(method = "<init>", at = @At(value = "RETURN")) +
-    private void constructor(ArmorMaterial material, EquipmentSlot slot, Item.Settings settings, CallbackInfo ci) { +
-        UUID uUID = MODIFIERS[slot.getEntitySlotId()]; +
- +
-        if (material == RegisterItems.customArmorMaterial) { +
-            ImmutableMultimap.Builder<EntityAttribute, EntityAttributeModifier> builder = ImmutableMultimap.builder(); +
- +
-            this.attributeModifiers.forEach(builder::put); +
- +
-            builder.put( +
-                    EntityAttributes.GENERIC_KNOCKBACK_RESISTANCE, +
-                    new EntityAttributeModifier(uUID, +
-                            "Armor knockback resistance", +
-                            this.knockbackResistance, +
-                            EntityAttributeModifier.Operation.ADDITION +
-                    ) +
-            ); +
- +
-            this.attributeModifiers = builder.build(); +
-        } +
-    } +
-     +
-+
-</code> +
- +
-Now your armor has the knockback resistance value you assigned to it back on CustomArmorMaterial.+
tutorial/armor.1602276605.txt.gz · Last modified: 2020/10/09 20:50 by sakira