User Tools

Site Tools


zh_cn:tutorial:armor

This is an old revision of the document!


添加盔甲

介绍

盔甲是比一般的方块或者物品更复杂一点的实现,但是只要了解了,实现还是很简单的。如需添加盔甲,需要先做一个CustomArmorMaterial类,然后注册物品。无门还需要看看如何为盔甲提供材质。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).

本文档的一个例子可以在本模组GitHub仓库找到。

创建盔甲材料类

新的盔甲需要和一个新的名称(以及额外的一些内容,例如盔甲点和耐久度)一起设置,我们需要为我们的CustomArmorMaterial创建一个新的类。

本类实现ArmorMaterial,并以指定值为盔甲点(称为PROTECTION_VALUES)开始。所有这些参数都会充分利用 @Override。

  1. public class CustomArmorMaterial implements ArmorMaterial {
  2. private static final int[] BASE_DURABILITY = new int[] {13, 15, 16, 11};
  3. private static final int[] PROTECTION_VALUES = new int[] {A, B, C, D};
  4.  
  5. // 其中A是头盔,B是胸甲,C是护腿,D是靴子。
  6. // 例如,皮革使用{1, 2, 3, 1},钻石和下界合金使用{3, 6, 8, 3}
  7. }

接下来的变量如下定义(无需担心名称,下面你会看到如何实现):

  1. 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.
  2. getProtectionAmount: calls for the 'PROTECTION_VALUES' int we already wrote above.
  3. getEnchantability: This will be how likely the armor can get high level or multiple enchantments in an enchantment book.
  4. SoundEvent getEquipSound: The standard used by vanilla armor is SoundEvents.ITEM_ARMOR_EQUIP_X, X being the type of armor.
  5. Ingredient getRepairIngredient: 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.
  6. String getName: what the parent item of the armor is. In Diamond armor, it'd be “diamond”.
  7. getToughness: This is a second protection value where the armor is more durable against high value attacks. Value goes as 'X.0F'

在1.16引入的新值

  1. 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.

接下来所有的参数都会写成 X 或者 A、B、C、D。加上这些参数之后,效果应该如下:

  1. public class CustomArmorMaterial implements ArmorMaterial {
  2. private static final int[] BASE_DURABILITY = new int[] {13, 15, 16, 11};
  3. private static final int[] PROTECTION_VALUES = new int[] {A, B, C, D};
  4.  
  5. @Override
  6. public int getDurability(EquipmentSlot slot) {
  7. return BASE_DURABILITY[slot.getEntitySlotId()] * X;
  8. }
  9.  
  10. @Override
  11. public int getProtectionAmount(EquipmentSlot slot) {
  12. return PROTECTION_VALUES[slot.getEntitySlotId()];
  13. }
  14.  
  15. @Override
  16. public int getEnchantability() {
  17. return X;
  18. }
  19.  
  20. @Override
  21. public SoundEvent getEquipSound() {
  22. return SoundEvents.ITEM_ARMOR_EQUIP_X;
  23. }
  24.  
  25. @Override
  26. public Ingredient getRepairIngredient() {
  27. return Ingredient.ofItems(RegisterItems.X);
  28. }
  29.  
  30. @Override
  31. public String getName() {
  32. return "name";
  33. }
  34.  
  35. @Override
  36. public float getToughness() {
  37. return X.0F;
  38. }
  39.  
  40. @Override
  41. public float getKnockbackResistance() {
  42. return 0.XF;
  43. }
  44. }

注意你有盔甲材料类的基础了,所以在新的类中注册你的盔甲物品,即RegisterItems。

创建盔甲物品

我们准备创建一个叫做RegisterItems的新的类以实现新的盔甲物件。这也会是注册工具的地方,如果你准备制作像锭这样的新物品(我们简单称为Custom_Material)。这一步同时还会将这些物品放在创造模式物品栏中,如果需要也可以删除这一部分。

物品分组的语法为 .group(你的模组名称.你的分组的大写名称)。这里将其称为ExampleMod:

  1. public class RegisterItems {
  2.  
  3. public static final ArmorMaterial CUSTOM_ARMOR_MATERIAL = new CustomArmorMaterial();
  4. public static final Item CUSTOM_MATERIAL = new CustomMaterialItem(new Item.Settings().group(ExampleMod.EXAMPLE_MOD_GROUP));
  5. // 如果创建了新的材料,则你需要注意这里。
  6. public static final Item CUSTOM_MATERIAL_HELMET = new ArmorItem(CUSTOM_ARMOR_MATERIAL, EquipmentSlot.HEAD, new Item.Settings().group(ExampleMod.EXAMPLE_MOD_GROUP));
  7. public static final Item CUSTOM_MATERIAL_CHESTPLATE = new ArmorItem(CUSTOM_ARMOR_MATERIAL, EquipmentSlot.CHEST, new Item.Settings().group(ExampleMod.EXAMPLE_MOD_GROUP));
  8. public static final Item CUSTOM_MATERIAL_LEGGINGS = new ArmorItem(CUSTOM_ARMOR_MATERIAL, EquipmentSlot.LEGS, new Item.Settings().group(ExampleMod.EXAMPLE_MOD_GROUP));
  9. public static final Item CUSTOM_MATERIAL_BOOTS = new ArmorItem(CUSTOM_ARMOR_MATERIAL, EquipmentSlot.FEET, new Item.Settings().group(ExampleMod.EXAMPLE_MOD_GROUP));
  10.  
  11. }

现在物品创建好了,将其注册并给予适当的名称,你的第一个参数是名字空间,也就是你的模组ID,第二个是你需要给予你的物品的名称。

我们会在最后一个ArmorItem的下面写这些。

  1. public static void register() {
  2. Registry.register(Registry.ITEM, new Identifier("examplemod", "custom_material"), CUSTOM_MATERIAL);
  3. Registry.register(Registry.ITEM, new Identifier("examplemod", "custom_material_helmet"), CUSTOM_MATERIAL_HELMET);
  4. Registry.register(Registry.ITEM, new Identifier("examplemod", "custom_material_chestplate"), CUSTOM_MATERIAL_CHESTPLATE);
  5. Registry.register(Registry.ITEM, new Identifier("examplemod", "custom_material_leggings"), CUSTOM_MATERIAL_LEGGINGS);
  6. Registry.register(Registry.ITEM, new Identifier("examplemod", "custom_material_boots"), CUSTOM_MATERIAL_BOOTS);
  7. }

你的盔甲物品已完成。现在我们在主类中调用Registry。

  1. public static final ItemGroup EXAMPLE_MOD_GROUP = FabricItemGroupBuilder.create(
  2. new Identifier("examplemod", "example_mod_group"))
  3. .icon(() -> new ItemStack(RegisterItems.CUSTOM_MATERIAL)) // 这里将你创建的新的材料的模型用作图标,但是你也可以随时使用你喜欢的
  4. .build();
  5.  
  6. @Override
  7. public void onInitialize() {
  8. RegisterItems.register();
  9. }

好了!你的盔甲现在应该存在于游戏中,虽然还没有材质,但是已经可以通过/give来获得了。

现在分配材质。

提供材质

假定你已经:

  • 有了每一个盔甲物品的材质(x_helmet.png、x_chestplate.png等)
  • 有了穿着的每个盔甲的材质(x_layer_1.png和x_layer_2.png)

将其分配到每一个盔甲物品。

下列过程对于所有盔甲物品都是一样的,只需要修改我们使用的部分。这里以头盔为例。

resources/assets/examplemod/models/item/custom_material_helmet.json
{
	"parent": "item/generated",
	"textures": {
		"layer0": "examplemod:item/custom_material_helmet"
	}
}

重复上述过程,完成其他物品。

要给予穿着的盔甲的材质,只需要将X_layer_1.png和X_layer_2.png(其中X是你在你的盔甲材料类中选择的参数)放到'resources/assets/minecraft/textures/models/armor'。

做完上述步骤,你应该会有一套完整的盔甲!

添加击退保护

And here comes the so very cursed!

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, here's how to register mixins on your fabric.mod.json

We'll make a class called ArmorItemMixin, and write:

@Mixin (ArmorItem.class)
public abstract class ArmorItemMixin {
 
}

Now we have to make a @Shadow to modify knockbackResistance, which is an EntityAttribute

@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;
}

Next we @Inject our GENERIC_KNOCKBACK_RESISTANCE into the ArmorMaterial constructor.

@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();
        }
    }
 
}

Now your armor has the knockback resistance value you assigned to it back on CustomArmorMaterial.

zh_cn/tutorial/armor.1627175694.txt.gz · Last modified: 2021/07/25 01:14 by solidblock