寫在前頭
1.不是JAVA教學所以不解釋程式碼為何這樣寫,想知道為什麼這麼寫可以在 Fabric docs 或 Fabric wiki 裡面找到。
2.我的模組名稱為mays-mod
,程式碼中看到 mays-mod 的地方請自行換成你的 mod 名稱。
3.圖片看不清的話可以點擊放大看。
模組設定
目前只需要知道這些檔案的用處就好,不需要去改任何設定。
src/main/resources/fabric.mod.json
mod設定檔"version": "${version}",
填入的是 gralde.properties 中的 mod_version
gralde.properties
專案設定檔- mod icon 在
src/main/resources/assets/<mod_id>
中替換 icon.png
創建模組客戶端
創建一個 MaysModClient.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"
]
},
不要完全照著我的寫,因為每個人的mod名稱不一樣,記得要改。
生成 Minecraft 原始檔
開啟 Gradle 視窗找到 Tasks > fabric > genSources
雙擊生成 Minecraft 原始檔。
外部庫 > net.minecraft:minecraft-merged… > net.minecraft 這裡面就是 Minecraft 的原始檔。
目前原始檔它是 class 檔,我們需要先將它反編譯成 java 檔。隨便打開一個檔案,上方會跳出提示,點擊「選擇源」然後選 xxxxx-sources.jar
,就會反編譯成 java 檔。
同步到 GitHub
這一步是方便版本控制或者和其他人合作開發,不需要的話可以跳過。
VCS > 在 GitHub 上共享項目 > 添加帳戶(通過GitHub登入) > 共享
全選不做任何修改按「添加」就會將當前專案推上 github 了。
創建物品
我的目標是新增一個苦力怕礦,使用鐵稿以上挖掘後掉落苦力怕原礦,苦力怕原礦可以拿去燒成苦力怕錠。
MaysMod.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/<mod_id>/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。
- 苦力怕原礦:參考鐵原礦
raw_iron
命名成raw_creeper
- 苦力怕錠:參考鐵錠
iron_ingot
命名成creeper_ingot
回到 MaysMod.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": "苦力怕原礦"
}
新增材質
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);
}
}
回到 MaysMod.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()
.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/<mod_id>/textures/item
,語系檔加上 item.mays-mod.sweet_potato
即可。