tutorial:armor
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
tutorial:armor [2020/10/09 20:24] – [Texturing] sakira | tutorial:armor [2022/03/17 15:17] – fix furnygo | ||
---|---|---|---|
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' |
- | 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' | + | An example for this document can be found in [[https:// |
==== Creating an Armor Material class ==== | ==== Creating an Armor Material class ==== | ||
Line 15: | Line 15: | ||
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
public class CustomArmorMaterial implements ArmorMaterial { | 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}; | + | 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 helmet, B chestplate, C leggings and D boots. |
- | // For reference, Leather uses {1, 2, 3, 1}, and Diamond/ | + | // For reference, Leather uses {1, 2, 3, 1}, and Diamond/ |
} | } | ||
</ | </ | ||
Line 26: | Line 26: | ||
- getDurability: | - getDurability: | ||
- | - getPretectionAmount: calls for the ' | + | - getProtectionAmount: calls for the ' |
- getEnchantability: | - getEnchantability: | ||
- SoundEvent getEquipSound: | - SoundEvent getEquipSound: | ||
- | - Ingredient | + | - Ingredient |
- String getName: what the parent item of the armor is. In Diamond armor, it'd be " | - String getName: what the parent item of the armor is. In Diamond armor, it'd be " | ||
- getToughness: | - getToughness: | ||
Line 41: | Line 41: | ||
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
public class CustomArmorMaterial implements ArmorMaterial { | 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}; | + | private static final int[] PROTECTION_VALUES = new int[] {A, B, C, D}; |
- | | + | @Override |
- | public int getDurability(EquipmentSlot slot) { | + | public int getDurability(EquipmentSlot slot) { |
- | return BASE_DURABILITY[slot.getEntitySlotId()] * X; | + | return BASE_DURABILITY[slot.getEntitySlotId()] * X; |
- | } | + | } |
- | | + | @Override |
- | public int getProtectionAmount(EquipmentSlot slot) { | + | public int getProtectionAmount(EquipmentSlot slot) { |
- | return PROTECTION_VALUES[slot.getEntitySlotId()]; | + | return PROTECTION_VALUES[slot.getEntitySlotId()]; |
- | } | + | } |
- | | + | @Override |
- | public int getEnchantability() { | + | public int getEnchantability() { |
- | return X; | + | return X; |
- | } | + | } |
- | | + | @Override |
- | public SoundEvent getEquipSound() { | + | public SoundEvent getEquipSound() { |
- | return SoundEvents.ITEM_ARMOR_EQUIP_X; | + | return SoundEvents.ITEM_ARMOR_EQUIP_X; |
- | } | + | } |
- | | + | @Override |
- | public Ingredient getRepairIngredient() { | + | public Ingredient getRepairIngredient() { |
- | return Ingredient.ofItems(RegisterItems.X); | + | return Ingredient.ofItems(RegisterItems.X); |
- | } | + | } |
- | | + | @Override |
- | public String getName() { | + | public String getName() { |
- | return " | + | // Must be all lowercase |
- | } | + | return " |
+ | } | ||
- | | + | @Override |
- | public float getToughness() { | + | public float getToughness() { |
- | return X.0F; | + | return X.0F; |
- | } | + | } |
- | | + | @Override |
- | public float getKnockbackResistance() { | + | public float getKnockbackResistance() { |
- | return 0.XF; | + | return 0.XF; |
- | } | + | } |
} | } | ||
</ | </ | ||
Line 93: | Line 94: | ||
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 " | 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 " | ||
- | The syntax of groups is //.group([Your mod name here].[YOUR_MOD_NAME_BUT_IN_CAPS]_GROUP)//. I'll be referring to it as ExampleMod: | + | The syntax of groups is //.group(YourModName.YOUR_MOD_NAME_BUT_IN_CAPS_GROUP)//. I'll be referring to it as ExampleMod: |
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
public class RegisterItems { | public class RegisterItems { | ||
- | public static final ArmorMaterial | + | |
- | | + | public static final Item CUSTOM_MATERIAL = new CustomMaterialItem(new Item.Settings().group(ExampleMod.EXAMPLE_MOD_GROUP)); |
// 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(CustomArmorMaterial, EquipmentSlot.HEAD, | + | public static final Item CUSTOM_MATERIAL_HELMET = new ArmorItem(CUSTOM_ARMOR_MATERIAL, EquipmentSlot.HEAD, |
- | public static final Item CUSTOM_MATERIAL_CHESTPLATE = new ArmorItem(CustomArmorMaterial, EquipmentSlot.CHEST, | + | public static final Item CUSTOM_MATERIAL_CHESTPLATE = new ArmorItem(CUSTOM_ARMOR_MATERIAL, EquipmentSlot.CHEST, |
- | public static final Item CUSTOM_MATERIAL_LEGGINGS = new ArmorItem(CustomArmorMaterial, EquipmentSlot.LEGS, | + | public static final Item CUSTOM_MATERIAL_LEGGINGS = new ArmorItem(CUSTOM_ARMOR_MATERIAL, EquipmentSlot.LEGS, |
- | public static final Item CUSTOM_MATERIAL_BOOTS = new ArmorItem(CustomArmorMaterial, EquipmentSlot.FEET, | + | public static final Item CUSTOM_MATERIAL_BOOTS = new ArmorItem(CUSTOM_ARMOR_MATERIAL, EquipmentSlot.FEET, |
} | } | ||
</ | </ | ||
- | Now that your items are properly created, | + | Now that your items are properly created, |
We'll be writing this right below your last ArmorItem. | We'll be writing this right below your last ArmorItem. | ||
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
- | public static void register() { | + | public static void register() { |
- | Registry.register(Registry.ITEM, | + | Registry.register(Registry.ITEM, |
- | Registry.register(Registry.ITEM, | + | Registry.register(Registry.ITEM, |
- | Registry.register(Registry.ITEM, | + | Registry.register(Registry.ITEM, |
- | Registry.register(Registry.ITEM, | + | Registry.register(Registry.ITEM, |
- | Registry.register(Registry.ITEM, | + | Registry.register(Registry.ITEM, |
- | } | + | } |
</ | </ | ||
Line 131: | Line 132: | ||
.build(); | .build(); | ||
- | @Override | + | |
public void onInitialize() { | public void onInitialize() { | ||
RegisterItems.register(); | RegisterItems.register(); | ||
Line 137: | Line 138: | ||
</ | </ | ||
- | That's it! Your armor should now exist in game, untextured still, but present and able to be given with /summon. | + | 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. | Now we'll be assigning the textures to each piece. | ||
Line 153: | Line 154: | ||
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. | ||
- | < | + | < |
{ | { | ||
- | | + | " |
- | " | + | " |
- | " | + | " |
- | } | + | } |
} | } | ||
</ | </ | ||
Line 165: | Line 165: | ||
Repeat with all armor items. | Repeat with all armor items. | ||
- | To give your on-body armor a texture, | + | To give your on-body armor a texture, simply |
+ | |||
If you followed everything, you should now be able to have a full armor set! | 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! | ||
+ | |||
+ | Mojang decided that they were not only going to hardcode getKnockbackResistance, | ||
+ | |||
+ | To get around this, we're gonna make a mixin that goes into ArmorItem. If this is your first time, [[tutorial: | ||
+ | |||
+ | We'll make a class called ArmorItemMixin, | ||
+ | |||
+ | <code java [enable_line_numbers:" | ||
+ | @Mixin (ArmorItem.class) | ||
+ | public abstract class ArmorItemMixin { | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | Now we have to make a @Shadow to modify knockbackResistance, | ||
+ | |||
+ | <code java [enable_line_numbers:" | ||
+ | @Mixin (ArmorItem.class) | ||
+ | public abstract class ArmorItemMixin { | ||
+ | @Shadow @Final private static UUID[] MODIFIERS; | ||
+ | @Shadow @Final @Mutable private Multimap< | ||
+ | @Shadow @Final protected float knockbackResistance; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Next we @Inject our GENERIC_KNOCKBACK_RESISTANCE into the ArmorMaterial constructor. | ||
+ | |||
+ | <code java [enable_line_numbers:" | ||
+ | @Mixin (ArmorItem.class) | ||
+ | public abstract class ArmorItemMixin { | ||
+ | |||
+ | @Shadow @Final private static UUID[] MODIFIERS; | ||
+ | @Shadow @Final @Mutable private Multimap< | ||
+ | @Shadow @Final protected float knockbackResistance; | ||
+ | | ||
+ | @Inject(method = "< | ||
+ | private void constructor(ArmorMaterial material, EquipmentSlot slot, Item.Settings settings, CallbackInfo ci) { | ||
+ | UUID uUID = MODIFIERS[slot.getEntitySlotId()]; | ||
+ | |||
+ | if (material == RegisterItems.customArmorMaterial) { | ||
+ | ImmutableMultimap.Builder< | ||
+ | |||
+ | this.attributeModifiers.forEach(builder:: | ||
+ | |||
+ | builder.put( | ||
+ | EntityAttributes.GENERIC_KNOCKBACK_RESISTANCE, | ||
+ | new EntityAttributeModifier(uUID, | ||
+ | "Armor knockback resistance", | ||
+ | this.knockbackResistance, | ||
+ | EntityAttributeModifier.Operation.ADDITION | ||
+ | ) | ||
+ | ); | ||
+ | |||
+ | this.attributeModifiers = builder.build(); | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Now your armor has the knockback resistance value you assigned to it back on CustomArmorMaterial. |
tutorial/armor.txt · Last modified: 2024/07/04 16:32 by mineblock11