Site icon May's Notes

Minecraft 1.21 Fabric 模組開發(2)-新增物品

Minecraft 1.21 Fabric 模組開發(2)-新增物品

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

模組設定

目前只需要知道這些檔案的用處就好,不需要去改任何設定。

創建模組客戶端

創建一個 XxxModClient.java 在 src/main/java/<mod_id> 底下。

在 class 後面加上 implements ClientModInitializer,然後重寫一個 onInitializeClient 方法:

// MaysModClient.java
package com.may.firstmod;

import net.fabricmc.api.ClientModInitializer;

public class MaysModClient implements ClientModInitializer {
    @Override
    public  void onInitializeClient() {

    }
}

打開 fabric.mod.json 在 entrypoints 加上 client

"entrypoints": {
		"main": [
			"com.may.firstmod.MaysMod"
		],
		"client": [
			"com.may.firstmod.MaysModClient"
		],
		"fabric-datagen": [
			"com.may.firstmod.MaysModDataGenerator"
		]
	},

生成 Minecraft 原始檔

開啟 Gradle 視窗找到 Tasks > fabric > genSources 雙擊生成 Minecraft 原始檔。

外部庫 > net.minecraft:minecraft-merged… > net.minecraft 這裡面就是 Minecraft 的原始檔。

目前原始檔它是 class 檔,我們需要先將它反編譯成 java 檔。隨便打開一個檔案,上方會跳出提示,點擊「選擇源」然後選 xxxxx-sources.jar,就會反編譯成 java 檔。

同步到 GitHub

這一步是方便版本控制或者和其他人合作開發,不需要的話可以跳過

VCS > 在 GitHub 上共享項目 > 添加帳戶(通過GitHub登入) > 共享

全選不做任何修改按「添加」就會將當前專案推上 github 了。

創建物品

我的目標是新增一個苦力怕礦,使用鐵稿以上挖掘後掉落苦力怕原礦苦力怕原礦可以拿去燒成苦力怕錠

XxxMod.java 新增一個字串 MOD_ID,把 LoggerFactory.getLogger 裡面的 mod id 替換成 MOD_ID

// MaysMod.java
public class MaysMod implements ModInitializer {
  public static final String MOD_ID = "mays-mod";
	public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);

	@Override
	public void onInitialize() {
		LOGGER.info("Hello Fabric world!");
	}
}

main/java/com/<package_name> 底下新增 item.ModItems java類,以後 mod 中的所有物品都會在這定義。

新增 registerItem 和 initialize 兩個方法:

// item/ModItems.java
package com.may.firstmod.item;

import com.may.firstmod.MaysMod;
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemGroups;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.util.Identifier;

public class ModItems {
    // 註冊物品
    public static Item registerItem(String name, Item item, RegistryKey<ItemGroup>... itemGroups) {
        Item registeredItem = Registry.register(Registries.ITEM, Identifier.of(MaysMod.MOD_ID, name), item);
        for (RegistryKey<ItemGroup> itemGroup: itemGroups) {
            ItemGroupEvents.modifyEntriesEvent(itemGroup).register(entries -> entries.add(registeredItem));
        }
        return registeredItem;
    }

    public static void initialize() {
        MaysMod.LOGGER.debug("Registering mod items for" + MaysMod.MOD_ID);
    }
}

使用 registerItem 方法添加物品,這邊的 maxCount 為最大堆疊量

// item/ModItems.java
public static final Item RAW_CREEPER = registerItem("raw_creeper", new Item(new Item.Settings().maxCount(64)));
public static final Item CREEPER_INGOT = registerItem("creeper_ingot", new Item(new Item.Settings().maxCount(64)));

如果不知道物品如何命名的話,可以參考同種物品在 wiki 上面的命名空間 ID。

回到 XxxMod.java 的 onInitialize 中調用 ModItems.initialize 方法註冊物品

// MaysMod.java
package com.may.firstmod;

import com.may.firstmod.item.ModItems;
import net.fabricmc.api.ModInitializer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MaysMod implements ModInitializer {
    public static final String MOD_ID = "mays-mod";
	public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);

	@Override
	public void onInitialize() {
		LOGGER.info("Hello Fabric world!");
		ModItems.initialize();
	}
}

修改物品模型和材質

src/main/resources/assets/<mod_id> 中新建以下資料夾

blockstates
lang
models
models/block
models/item
textures
textures/block
textures/item

新增語系檔

lang 底下新增 en.json 和 zh_tw.json

en.json

{
  "item.mays-mod.creeper_ingot": "Creeper Ingot",
  "item.mays-mod.raw_creeper": "Raw Creeper"
}

zh_tw.json

{
  "item.mays-mod.creeper_ingot": "苦力怕錠",
  "item.mays-mod.raw_creeper": "苦力怕原礦"
}

語系檔寫法:https://fabricmc.net/wiki/zh_cn:tutorial:lang

新增材質

models/item 底下新增 raw_creeper.json

因為是2D平面所以只有一個 layer

{
  "parent": "item/generated",
  "textures": {
    "layer0": "mays-mod:item/raw_creeper"
  }
}

同樣新增 creeper_ingot.json 內容都一樣,只有 layer0 後面要修改。

接著將準備好物品的圖片(16×16, png)放入 textures/item 中。

如何自製材質?

我自己是用小畫家,先在網上找到素材(可以是透明的),然後用小畫家開啟

將像素調整成16×16

調整完後圖片會很小,需要拉大到800倍

然後切換成鉛筆工具開始畫,畫完保存成png格式

啟動 Minecraft

開啟 Gradle 視窗找到 Tasks > fabric > runClient 雙擊會自動開啟 Minecraft

可以做一些基礎設置,比如將介面改為繁體中文然後關閉聲音,然後創建一個創造模式的存檔。

由於我們還沒設置物品的類別,所以無法從物品欄中找到,只能通過 give 指令先獲取:

/give @a mays-mod:raw_creeper

定義物品類別

item 底下新增 ModItemGroup.java,新增一個 CREEPER_GROUP 的全新分類

寫法請參考:https://docs.fabricmc.net/develop/items/custom-item-groups
標準註冊表:https://fabricmc.net/wiki/zh_cn:tutorial:registry_types

// item/ModItemGroup.java
package com.may.firstmod.item;

import com.may.firstmod.MaysMod;
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;

public class ModItemGroup {
    public static final RegistryKey<ItemGroup> CREEPER_GROUP_KEY = RegistryKey.of(Registries.ITEM_GROUP.getKey(), Identifier.of(MaysMod.MOD_ID, "creeper_group"));
    public static final ItemGroup CREEPER_GROUP = FabricItemGroup.builder()
            .icon(() -> new ItemStack(ModItems.CREEPER_ORE))
            .displayName(Text.translatable("itemGroup.mays-mod.creeper_group"))
            .build();

    public static void initialize() {
        Registry.register(Registries.ITEM_GROUP, Identifier.of(MaysMod.MOD_ID, "creeper_group"), CREEPER_GROUP);
    }
}

回到 XxxMod.java 中初始化 ModItemGroup

// MaysMod.java
package com.may.firstmod;

import com.may.firstmod.item.ModItemGroup;
import com.may.firstmod.item.ModItems;
import net.fabricmc.api.ModInitializer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MaysMod implements ModInitializer {
  public static final String MOD_ID = "mays-mod";
	public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);

	@Override
	public void onInitialize() {
		LOGGER.info("Hello Fabric world!");
		ModItems.initialize();
		ModItemGroup.initialize();
	}
}

語系檔中記得新增 itemGroup.mays-mod.creeper_group 的翻譯

{
  "item.mays-mod.creeper_ingot": "Creeper Ingot",
  "item.mays-mod.raw_creeper": "Raw Creeper",
  "itemGroup.mays-mod.creeper_group": "Creeper Group"
}
{
  "item.mays-mod.creeper_ingot": "苦力怕錠",
  "item.mays-mod.raw_creeper": "苦力怕原礦",
  "itemGroup.mays-mod.creeper_group": "苦力怕類別"
}

回到 ModItems.java 中在物品後方加上物品的類別:

// ModItems.java
public static final Item RAW_CREEPER = registerItem("raw_creeper", new Item(new Item.Settings().maxCount(64)), CREEPER_GROUP_KEY, ItemGroups.INGREDIENTS);
public static final Item CREEPER_INGOT = registerItem("creeper_ingot", new Item(new Item.Settings().maxCount(64)), CREEPER_GROUP_KEY, ItemGroups.INGREDIENTS);

如此一來新增的物品就會被放到全新的類別苦力帕分類中:

苦力怕原礦和苦力怕錠會被同樣會被放到原材料中:

創建食物

食物其實跟新增物品差不多的步驟,只不過需要新增一個 /java/com/<mod_id>/item/ModFoodComponents.java

package com.may.firstmod.item;

import net.minecraft.component.type.FoodComponent;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;

public class ModFoodComponents {
    public static final FoodComponent SWEET_POTATO = new FoodComponent.Builder()
            .alwaysEdible()
            .snack()
            // The duration is in ticks, 20 ticks = 1 second
            .statusEffect(new StatusEffectInstance(StatusEffects.STRENGTH, 10 * 20, 1), 1.0f)
            .statusEffect(new StatusEffectInstance(StatusEffects.INSTANT_HEALTH, 10 * 20, 1), 1.0f)
            .build();

}

/item/custom 底下新增 SweetPotato.java

package com.may.firstmod.item.custom;

import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.tooltip.TooltipType;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;

import java.util.List;

public class SweetPotato extends Item {
    public SweetPotato(Settings settings) {
        super(settings);
    }

    @Override
    public void appendTooltip(ItemStack stack, TooltipContext context, List<Text> tooltip, TooltipType type) {
        tooltip.add(Text.translatable("itemTooltip.mays-mod.sweetpotato").formatted(Formatting.GOLD));
    }
}

ModItems.java 中新增食物 SWEET_POTATO

    public static final Item SWEET_POTATO = registerItem("sweet_potato", new SweetPotato(new Item.Settings().food(ModFoodComponents.SWEET_POTATO)), ItemGroups.FOOD_AND_DRINK);

然後將食物圖片放進 /resources/assets/mays-mod/textures/item,語系檔加上 item.mays-mod.sweet_potato 即可。

Exit mobile version