Minecraft 1.21 Fabric 模組開發(1)-前置準備
Minecraft 1.21 Fabric 模組開發(2)-新增物品
Minecraft 1.21 Fabric 模組開發(3)-新增方塊
Minecraft 1.21 Fabric 模組開發(4)-資料產生(Data Generation)
Minecraft 1.21 Fabric 模組開發(5)-新增挖掘工具
寫在前頭
1.不是JAVA教學所以不解釋程式碼為何這樣寫,想知道為什麼這麼寫可以在 Fabric docs 或 Fabric wiki 裡面找到。
2.我的模組名稱為mays-mod
,程式碼中看到 mays-mod 的地方請自行換成你的 mod 名稱。
3.圖片看不清的話可以點擊放大看。
創建盔甲材料類
如果要新增盔甲,需要先實現 ModArmorMaterial 類,類別中還會需要建立一個靜態方法用於註冊盔甲材料。
/java/com/item/ModArmorMaterial.java
package com.may.firstmod.item;
import com.may.firstmod.MaysMod;
import net.minecraft.item.ArmorItem;
import net.minecraft.item.ArmorMaterial;
import net.minecraft.recipe.Ingredient;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.Identifier;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class ModArmorMaterial {
public static final RegistryEntry<ArmorMaterial> CREEPER = registerMaterial(
"creeper",
Map.of(
ArmorItem.Type.HELMET, 3,
ArmorItem.Type.CHESTPLATE, 8,
ArmorItem.Type.LEGGINGS, 6,
ArmorItem.Type.BOOTS, 3
),
15,
SoundEvents.ITEM_ARMOR_EQUIP_IRON,
() -> Ingredient.ofItems(ModItems.CREEPER_INGOT),
3.0F,
0.1F,
true
);
/**
* 註冊盔甲材質
*
* @param id
* @param defensePoints - 護甲值
* @param enchantability - 附魔能力, 數字越高可以接受更高的附魔
* @param equipSound - 裝備時的聲音
* @param repairIngredientSupplier - 修復材料
* @param toughness - 盔甲吸收的傷害, 數字越高吸收的傷害越多
* @param knockbackResistance - 擊退抗性, 數字越高玩家接收的擊退越少
* @param dyeable - 是否可以染色
* @return
*/
public static RegistryEntry<ArmorMaterial> registerMaterial(String id, Map<ArmorItem.Type, Integer> defensePoints, int enchantability, RegistryEntry<SoundEvent> equipSound, Supplier<Ingredient> repairIngredientSupplier, float toughness, float knockbackResistance, boolean dyeable) {
// Get the supported layers for the armor material
List<ArmorMaterial.Layer> layers = List.of(
new ArmorMaterial.Layer(Identifier.of(MaysMod.MOD_ID, id), "", dyeable)
);
ArmorMaterial material = new ArmorMaterial(defensePoints, enchantability, equipSound, repairIngredientSupplier, layers, toughness, knockbackResistance);
// Register the material within the ArmorMaterials registry.
material = Registry.register(Registries.ARMOR_MATERIAL, Identifier.of(MaysMod.MOD_ID, id), material);
// The majority of the time, you'll want the RegistryEntry of the material - especially for the ArmorItem constructor.
return RegistryEntry.of(material);
}
public static void initialize() {
}
;
}
可以參考 net/minecraft/item/ArmorMaterials
是怎麼註冊盔甲材質的:
public static final RegistryEntry<ArmorMaterial> NETHERITE = register("netherite", Util.make(new EnumMap(ArmorItem.Type.class), map -> {
map.put(ArmorItem.Type.BOOTS, 3);
map.put(ArmorItem.Type.LEGGINGS, 6);
map.put(ArmorItem.Type.CHESTPLATE, 8);
map.put(ArmorItem.Type.HELMET, 3);
map.put(ArmorItem.Type.BODY, 11);
}), 15, SoundEvents.ITEM_ARMOR_EQUIP_NETHERITE, 3.0F, 0.1F, () -> Ingredient.ofItems(Items.NETHERITE_INGOT));
創建盔甲物品
/java/com/item/ModItems.java
public static final Item CREEPER_HELMET = registerItem(
"creeper_helmet",
new ArmorItem(ModArmorMaterial.CREEPER, ArmorItem.Type.HELMET, new Item.Settings().maxDamage(ArmorItem.Type.BOOTS.getMaxDamage(15))),
CREEPER_GROUP_KEY
);
public static final Item CREEPER_CHESTPLATE = registerItem(
"creeper_chestplate",
new ArmorItem(ModArmorMaterial.CREEPER, ArmorItem.Type.CHESTPLATE, new Item.Settings().maxDamage(ArmorItem.Type.BOOTS.getMaxDamage(15))),
CREEPER_GROUP_KEY
);
public static final Item CREEPER_LEGGINGS = registerItem(
"creeper_leggings",
new ArmorItem(ModArmorMaterial.CREEPER, ArmorItem.Type.LEGGINGS, new Item.Settings().maxDamage(ArmorItem.Type.BOOTS.getMaxDamage(15))),
CREEPER_GROUP_KEY
);
public static final Item CREEPER_BOOTS = registerItem(
"creeper_boots",
new ArmorItem(ModArmorMaterial.CREEPER, ArmorItem.Type.BOOTS, new Item.Settings().maxDamage(ArmorItem.Type.BOOTS.getMaxDamage(15))),
CREEPER_GROUP_KEY
);
修改 Providers
ModItemTagProvider
為了讓自訂盔甲也能使用鍛造模板和附魔,需要向 TRIMMABLE_ARMOR
, ARMOR_ENCHANTABLE
添加我們的盔甲:
package com.may.firstmod.datagen;
import com.may.firstmod.item.ModItems;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.registry.tag.ItemTags;
import java.util.concurrent.CompletableFuture;
public class ModItemTagProvider extends FabricTagProvider.ItemTagProvider {
// ...
@Override
protected void configure(RegistryWrapper.WrapperLookup wrapperLookup) {
// ...
getOrCreateTagBuilder(ItemTags.TRIMMABLE_ARMOR)
.add(ModItems.CREEPER_BOOTS, ModItems.CREEPER_CHESTPLATE, ModItems.CREEPER_LEGGINGS, ModItems.CREEPER_HELMET);
getOrCreateTagBuilder(ItemTags.ARMOR_ENCHANTABLE)
.add(ModItems.CREEPER_BOOTS, ModItems.CREEPER_CHESTPLATE, ModItems.CREEPER_LEGGINGS, ModItems.CREEPER_HELMET);
}
}
ModModelsProvider
/java/com/datagen/ModModelsProvider.java
package com.may.firstmod.datagen;
import com.may.firstmod.block.ModBlocks;
import com.may.firstmod.item.ModItems;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricModelProvider;
import net.minecraft.data.client.BlockStateModelGenerator;
import net.minecraft.data.client.ItemModelGenerator;
import net.minecraft.data.client.Models;
import net.minecraft.item.ArmorItem;
public class ModModelsProvider extends FabricModelProvider {
// ...
@Override
public void generateItemModels(ItemModelGenerator itemModelGenerator) {
// ...
// 盔甲
itemModelGenerator.registerArmor((ArmorItem) ModItems.CREEPER_HELMET);
itemModelGenerator.registerArmor((ArmorItem) ModItems.CREEPER_CHESTPLATE);
itemModelGenerator.registerArmor((ArmorItem) ModItems.CREEPER_BOOTS);
itemModelGenerator.registerArmor((ArmorItem) ModItems.CREEPER_LEGGINGS);
}
}
ModRecipesProvider
/java/com/datagen/ModRecipesProvider.java
package com.may.firstmod.datagen;
import com.may.firstmod.block.ModBlocks;
import com.may.firstmod.item.ModItems;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.Items;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.registry.RegistryWrapper;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class ModRecipesProvider extends FabricRecipeProvider {
// ...
@Override
public void generate(RecipeExporter exporter) {
// ...
// 苦力怕盔甲合成
ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, ModItems.CREEPER_HELMET)
.input('X', ModItems.CREEPER_INGOT)
.pattern("XXX")
.pattern("X X")
.pattern(" ")
.criterion("has_creeper_ingot", conditionsFromItem(ModItems.CREEPER_INGOT))
.offerTo(exporter);
ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, ModItems.CREEPER_BOOTS)
.input('X', ModItems.CREEPER_INGOT)
.pattern(" ")
.pattern("X X")
.pattern("X X")
.criterion("has_creeper_ingot", conditionsFromItem(ModItems.CREEPER_INGOT))
.offerTo(exporter);
ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, ModItems.CREEPER_CHESTPLATE)
.input('X', ModItems.CREEPER_INGOT)
.pattern("X X")
.pattern("XXX")
.pattern("XXX")
.criterion("has_creeper_ingot", conditionsFromItem(ModItems.CREEPER_INGOT))
.offerTo(exporter);
ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, ModItems.CREEPER_LEGGINGS)
.input('X', ModItems.CREEPER_INGOT)
.pattern("XXX")
.pattern("X X")
.pattern("X X")
.criterion("has_creeper_ingot", conditionsFromItem(ModItems.CREEPER_INGOT))
.offerTo(exporter);
}
}
記得語系檔也要加上。
註冊盔甲材質
盔甲的材質有兩層,一種是物品材質,一種是模型材質:
- 將盔甲的物品材質放入
/assets/<mod_id>/textures/item
,檔名格式為x_helmet.png
,x_chestplate.png
… - 並把盔甲模型材質放入
/assets/<mod_id>/textures/models/armor
,檔名格式為x_layer_1.png
,x_layer_2.png
…
圖可以參考官方的拿來修改。
我使用的圖片:https://imgur.com/a/eLiEuvh