Site icon May's Notes

Minecraft 1.21 Fabric 模組開發(5)-新增挖掘工具

Minecraft 1.21 Fabric 模組開發(1)-前置準備
Minecraft 1.21 Fabric 模組開發(2)-新增物品
Minecraft 1.21 Fabric 模組開發(3)-新增方塊
Minecraft 1.21 Fabric 模組開發(4)-資料產生(Data Generation)

寫在前頭
1.不是JAVA教學所以不解釋程式碼為何這樣寫,想知道為什麼這麼寫可以在 Fabric docs 或 Fabric wiki 裡面找到。
2.我的模組名稱為 mays-mod,程式碼中看到 mays-mod 的地方請自行換成你的 mod 名稱。
3.圖片看不清的話可以點擊放大看。

創建工具材質類

新增枚舉類 /java/com/<mod_id>/ModToolMaterial.java

package com.may.firstmod.item;

import com.may.firstmod.util.ModTags;
import net.minecraft.block.Block;
import net.minecraft.item.ToolMaterial;
import net.minecraft.recipe.Ingredient;
import net.minecraft.registry.tag.TagKey;

import java.util.function.Supplier;

public enum ModToolMaterial implements ToolMaterial {
    // 可以參考 net/minecraft/item/ToolMaterials.java
    CREEPER_INGOT(
        ModTags.Blocks.INCORRECT_FOR_CREEPER_TOOL, // Inverse Tag: 該工具無法挖掘的內容
        600, // 耐久度
        4.5f, // 採礦速度
        3.5f, // 攻擊傷害
        25, // 附魔能力
        () -> Ingredient.ofItems(ModItems.CREEPER_INGOT) // 修復道具
    );

    private final TagKey<Block> inverseTag;
    private final int itemDurability;
    private final float miningSpeed;
    private final float attackDamage;
    private final int enchantability;
    private final Supplier<Ingredient> repairIngredient;

    ModToolMaterial(TagKey<Block> inverseTag, int itemDurability, float miningSpeed, float attackDamage, int enchantability, Supplier<Ingredient> repairIngredient) {
        this.inverseTag = inverseTag;
        this.itemDurability = itemDurability;
        this.miningSpeed = miningSpeed;
        this.attackDamage = attackDamage;
        this.enchantability = enchantability;
        this.repairIngredient = repairIngredient;
    }

    @Override
    public int getDurability() {
        return this.itemDurability;
    }

    @Override
    public float getMiningSpeedMultiplier() {
        return this.miningSpeed;
    }

    @Override
    public float getAttackDamage() {
        return this.attackDamage;
    }

    @Override
    public TagKey<Block> getInverseTag() {
        return this.inverseTag;
    }

    @Override
    public int getEnchantability() {
        return this.enchantability;
    }

    @Override
    public Ingredient getRepairIngredient() {
        return this.repairIngredient.get();
    }
}

可以參考 net/minecraft/item/ToolMaterials.java

public enum ToolMaterials implements ToolMaterial {
    WOOD(BlockTags.INCORRECT_FOR_WOODEN_TOOL, 59, 2.0F, 0.0F, 15, () -> Ingredient.fromTag(ItemTags.PLANKS)),
    STONE(BlockTags.INCORRECT_FOR_STONE_TOOL, 131, 4.0F, 1.0F, 5, () -> Ingredient.fromTag(ItemTags.STONE_TOOL_MATERIALS)),
    IRON(BlockTags.INCORRECT_FOR_IRON_TOOL, 250, 6.0F, 2.0F, 14, () -> Ingredient.ofItems(Items.IRON_INGOT)),
    DIAMOND(BlockTags.INCORRECT_FOR_DIAMOND_TOOL, 1561, 8.0F, 3.0F, 10, () -> Ingredient.ofItems(Items.DIAMOND)),
    GOLD(BlockTags.INCORRECT_FOR_GOLD_TOOL, 32, 12.0F, 0.0F, 22, () -> Ingredient.ofItems(Items.GOLD_INGOT)),
    NETHERITE(BlockTags.INCORRECT_FOR_NETHERITE_TOOL, 2031, 9.0F, 4.0F, 15, () -> Ingredient.ofItems(Items.NETHERITE_INGOT));
    // ...

/java/com/<mod_id>/util/ModTags.java 新增 INCORRECT_FOR_CREEPER_TOOL

package com.may.firstmod.util;

import com.may.firstmod.MaysMod;
import net.minecraft.block.Block;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.Identifier;

public class ModTags {
    public static class Blocks {
        public static final TagKey<Block> INCORRECT_FOR_CREEPER_TOOL = createTag("incorrect_for_creeper_tool");

        private static TagKey<Block> createTag(String name) {
            return TagKey.of(RegistryKeys.BLOCK, Identifier.of(MaysMod.MOD_ID, name));
        }
    }

    public static class Items {

    }
}

建立工具物品

新增工具到 ModItems.java

public static final Item CREEPER_PICKAXE = registerItem(
        "creeper_pickaxe",
        new PickaxeItem(
                ModToolMaterial.CREEPER_INGOT,
                new Item.Settings().attributeModifiers(PickaxeItem.createAttributeModifiers(ModToolMaterial.CREEPER_INGOT, 1.0F, -2.8F))
        ),
        CREEPER_GROUP_KEY
);
public static final Item CREEPER_AXE = registerItem(
        "creeper_axe",
        new AxeItem(
                ModToolMaterial.CREEPER_INGOT,
                new Item.Settings().attributeModifiers(AxeItem.createAttributeModifiers(ModToolMaterial.CREEPER_INGOT, 5.0F, -3.0F))
        ),
        CREEPER_GROUP_KEY
);
public static final Item CREEPER_SHOVEL = registerItem(
        "creeper_shovel",
        new ShovelItem(
                ModToolMaterial.CREEPER_INGOT,
                new Item.Settings().attributeModifiers(ShovelItem.createAttributeModifiers(ModToolMaterial.CREEPER_INGOT, 1.5F, -3.0F))
        ),
        CREEPER_GROUP_KEY
);
public static final Item CREEPER_HOE = registerItem(
        "creeper_hoe",
        new HoeItem(
                ModToolMaterial.CREEPER_INGOT,
                new Item.Settings().attributeModifiers(HoeItem.createAttributeModifiers(ModToolMaterial.CREEPER_INGOT, -3.0F, 0.0F))
        ),
        CREEPER_GROUP_KEY
);
public static final Item CREEPER_SWORD = registerItem(
        "creeper_sword",
        new SwordItem(
                ModToolMaterial.CREEPER_INGOT,
                new Item.Settings().fireproof().attributeModifiers(SwordItem.createAttributeModifiers(ModToolMaterial.CREEPER_INGOT, 3, -2.4F))
        ),
        CREEPER_GROUP_KEY
);

修改 Providers

BlockTag

/java/com/datagen/ModBlockTagProvider.java 新增 INCORRECT_FOR_CREEPER_TOOL

package com.may.firstmod.datagen;

import com.may.firstmod.block.ModBlocks;
import com.may.firstmod.util.ModTags;
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.BlockTags;

import java.util.concurrent.CompletableFuture;

public class ModBlockTagProvider extends FabricTagProvider.BlockTagProvider {
    public ModBlockTagProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) {
        super(output, registriesFuture);
    }

    @Override
    protected void configure(RegistryWrapper.WrapperLookup arg) {
        // ...

        getOrCreateTagBuilder(ModTags.Blocks.INCORRECT_FOR_CREEPER_TOOL);
    }
}

ItemTag

為了讓自訂工具也能使用附魔,需要向 SWORD_ENCHANTABLE, MINING_LOOT_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.SWORD_ENCHANTABLE)
                .add(ModItems.CREEPER_SWORD);
        getOrCreateTagBuilder(ItemTags.MINING_ENCHANTABLE)
                .add(ModItems.CREEPER_AXE, ModItems.CREEPER_HOE, ModItems.CREEPER_SHOVEL, ModItems.CREEPER_PICKAXE);
    }
}

Models

/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;

public class ModModelsProvider extends FabricModelProvider {
    // ...

    @Override
    public void generateItemModels(ItemModelGenerator itemModelGenerator) {
        // ...
        itemModelGenerator.register(ModItems.CREEPER_AXE, Models.HANDHELD);
        itemModelGenerator.register(ModItems.CREEPER_PICKAXE, Models.HANDHELD);
        itemModelGenerator.register(ModItems.CREEPER_HOE, Models.HANDHELD);
        itemModelGenerator.register(ModItems.CREEPER_SWORD, Models.HANDHELD);
        itemModelGenerator.register(ModItems.CREEPER_SHOVEL, Models.HANDHELD);
    }
}

Recipes

添加工具的合成表

/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_AXE)
                .input('#', Items.STICK)
                .input('X', ModItems.CREEPER_INGOT)
                .pattern("XX")
                .pattern("X#")
                .pattern(" #")
                .criterion("has_creeper_ingot", conditionsFromItem(ModItems.CREEPER_INGOT))
                .offerTo(exporter);
        ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, ModItems.CREEPER_HOE)
                .input('#', Items.STICK)
                .input('X', ModItems.CREEPER_INGOT)
                .pattern("XX")
                .pattern(" #")
                .pattern(" #")
                .criterion("has_creeper_ingot", conditionsFromItem(ModItems.CREEPER_INGOT))
                .offerTo(exporter);
        ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, ModItems.CREEPER_PICKAXE)
                .input('#', Items.STICK)
                .input('X', ModItems.CREEPER_INGOT)
                .pattern("XXX")
                .pattern(" # ")
                .pattern(" # ")
                .criterion("has_creeper_ingot", conditionsFromItem(ModItems.CREEPER_INGOT))
                .offerTo(exporter);
        ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, ModItems.CREEPER_SHOVEL)
                .input('#', Items.STICK)
                .input('X', ModItems.CREEPER_INGOT)
                .pattern("X")
                .pattern("#")
                .pattern("#")
                .criterion("has_creeper_ingot", conditionsFromItem(ModItems.CREEPER_INGOT))
                .offerTo(exporter);
        ShapedRecipeJsonBuilder.create(RecipeCategory.COMBAT, ModItems.CREEPER_SWORD)
                .input('#', Items.STICK)
                .input('X', ModItems.CREEPER_INGOT)
                .pattern("X")
                .pattern("X")
                .pattern("#")
                .criterion("has_creeper_ingot", conditionsFromItem(ModItems.CREEPER_INGOT))
                .offerTo(exporter);
    }
}

記得語系檔中添加工具的名稱。

註冊工具材質

將物品材質放入 /assets/<mod_id>/textures/item

圖可以參考官方的拿來修改。

我使用的圖片:https://imgur.com/a/h64ETYX

Exit mobile version