Site icon May's Notes

Minecraft 1.21 Fabric 模組開發(3)-新增方塊

Minecraft 1.21 Fabric 模組開發(3)-新增方塊

Minecraft 1.21 Fabric 模組開發(1)-前置準備
Minecraft 1.21 Fabric 模組開發(2)-新增物品

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

創建方塊

src/main/java/com/<mod_id>/block 底下新增 ModBlocks.java

// block/ModBlocks.java
package com.may.firstmod.block;

import com.may.firstmod.MaysMod;
import com.may.firstmod.item.ModItemGroup;
import com.may.firstmod.item.ModItems;
import net.minecraft.block.Block;
import net.minecraft.block.ExperienceDroppingBlock;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.intprovider.UniformIntProvider;

public class ModBlocks {
    public static final Block CREEPER_BLOCK = registerBlock(
            "creeper_block",
            new ExperienceDroppingBlock(
                    UniformIntProvider.create(2, 6),
                    Block.Settings.create().sounds(BlockSoundGroup.METAL).strength(4.0f).requiresTool()
            ),
            ModItemGroup.CREEPER_GROUP_KEY
    );
    public static final Block CREEPER_ORE = registerBlock(
            "creeper_ore",
            new ExperienceDroppingBlock(
                    UniformIntProvider.create(2, 6),
                    Block.Settings.create().sounds(BlockSoundGroup.METAL).strength(4.0f).requiresTool()
            ),
            ModItemGroup.CREEPER_GROUP_KEY
    );

    // 註冊方塊
    public static Block registerBlock(String name, Block block, RegistryKey<ItemGroup>... itemGroups) {
        BlockItem blockItem = new BlockItem(block, new Item.Settings());
        Identifier id = Identifier.of(MaysMod.MOD_ID, name);

        ModItems.registerItem(name, blockItem, itemGroups);
        return Registry.register(Registries.BLOCK, id, block);
    }

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

XxxMod.java 中初始化 ModBlocks

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

import com.may.firstmod.block.ModBlocks;
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();
		ModBlocks.initialize();
	}
}

定義方塊

方塊紋理

將方塊的圖片(16×16, png)放到 assets/textures/block 裡面。

方塊模型

新增 assets/models/block/creeper_block.json

{
  "parent": "block/cube_all",
  "textures": {
    "all": "mays-mod:block/creeper_block"
  }
}

以及 creeper_ore.json

{
  "parent": "block/cube_all",
  "textures": {
    "all": "mays-mod:block/creeper_ore"
  }
}

物品模型

物品模型只需要繼承方塊的模型就好。

新增 assets/models/item/creeper_block.json

{
  "parent": "mays-mod:block/creeper_block"
}

以及 creeper_ore.json

{
  "parent": "mays-mod:block/creeper_ore"
}

方塊狀態

用於指示遊戲要渲染哪個模型

新增 assets/blockstates/creeper_block.json

{
  "variants": {
    "": { "model": "mays-mod:block/creeper_block" }
  }
}

以及 creeper_ore.json

{
  "variants": {
    "": { "model": "mays-mod:block/creeper_ore" }
  }
}

詳細的方塊狀態:https://docs.fabricmc.net/zh_cn/develop/blocks/blockstates

定義方塊挖掘工具和等級

在開始之前需要先了解方塊標籤這個概念

方塊標籤(Block Tags)

是用來對方快進行分類和標記的機制。

在遊戲中按 F3 準心對向方塊,右邊可以看到方塊標籤:

以鑽石礦為例:

金礦多了一條特殊的

鐵礦多了一條

新增資料包(data)

src/main/resources 底下新增以下資料夾:

data
data/minecraft
data/minecraft/tags/block/mineable

挖掘工具

data/minecraft/tags/block/mineable 底下新增 pickaxe.json, axe.json, hoe.json, shovel.json

// pickaxe.json
{
  "replace": false,
  "values": [
    "mays-mod:creeper_block",
    "mays-mod:creeper_ore"
  ]
}

values 可以為空陣列 [],比如目前 axe.json, hoe.json, shovel.json 的 values 都可以設成空陣列。

挖掘等級

data/minecraft/tags/block 底下新增 needs_stone_tool.json, needs_iron_tool.json, needs_diamond_tool.json,json檔的內容為:

{
  "replace": false,
  "values": [
    "mays-mod:creeper_block",
    "mays-mod:creeper_ore"
  ]
}

values 可以為空陣列,比如目前 axe.json, hoe.json, shovel.json 的 values 都可以設成空陣列

定義方塊掉落物

戰利品表生成器:https://misode.github.io/loot-table/

可以用鐵原礦(iron_ore)來做參考。

新增 src/main/resources/data/loot_table/blocks/creeper_ore.json 貼上生成的戰利品表json

{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "bonus_rolls": 0,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "type": "minecraft:item",
              "name": "mays-mod:creeper_ore",
              "conditions": [
                {
                  "condition": "minecraft:match_tool",
                  "predicate": {
                    "predicates": {
                      "minecraft:enchantments": [
                        {
                          "enchantments": "minecraft:silk_touch",
                          "levels": {
                            "min": 1
                          }
                        }
                      ]
                    }
                  }
                }
              ]
            },
            {
              "type": "minecraft:item",
              "name": "mays-mod:raw_creeper",
              "functions": [
                {
                  "function": "minecraft:apply_bonus",
                  "enchantment": "minecraft:fortune",
                  "formula": "minecraft:ore_drops"
                },
                {
                  "function": "minecraft:explosion_decay"
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

同理,新增 creeper_block.json 參考 iron_block 的戰利品表修改一下,這邊就不演示了。

具體屬性用途請參考:戰利品表物品修飾器

方塊配方

配方(type)有很多種,分為:crafting_shaped(有序合成), crafting_shapeless(無序合成), smelting(熔爐), stonecutting(切石機), campfire_cooking(營火), blasting(高爐), smithing(鍛造台), smoking(煙燻爐)…

有序合成(crafting_shaped)

這一步要完成用苦力帕錠(creeper_ingot)合成苦力帕方塊(creeper_block)

從 minecraft 原始檔 data/Minecraft/recipe 裡面找到鐵塊的合成法 iron_block.json 複製到 data/recipe 裡面。

iron_block.json 內容如下:

{
  "type": "minecraft:crafting_shaped",
  "category": "building",
  "key": {
    "#": {
      "item": "minecraft:iron_ingot"
    }
  },
  "pattern": [
    "###",
    "###",
    "###"
  ],
  "result": {
    "count": 1,
    "id": "minecraft:iron_block"
  }
}

pattern 是用於有序合成,最大為3個字串元素,每個字串最多3個字元,每個字元代表的意思在key中定義。沒擺東西可以留空(半形空格),比如說:

"# #",
" # ",
"# #"

也可以是 2*2 以內,這樣就不需要合成台製作。

"##"

假設我想使用九個苦力怕錠合成一個苦力怕方塊,先將檔名改為 creeper_block.json

然後將檔案中的 minecraft:iron_ingot 改為 mays-mod:creeper_ingot,把 minecraft:iron_block 改為 mays-mod:creeper_block

{
  "type": "minecraft:crafting_shaped",
  "category": "building",
  "key": {
    "#": {
      "item": "mays-mod:creeper_ingot"
    }
  },
  "pattern": [
    "###",
    "###",
    "###"
  ],
  "result": {
    "count": 1,
    "id": "mays-mod:creeper_block"
  }
}

熔爐(smelting)

這一步要完成用苦力帕原礦(raw_creeper)冶煉成苦力帕錠(creeper_ingot)

從 minecraft 原始檔 data/Minecraft/recipe 裡面找到 copper_ingot_from_smelting_copper_ore.json 複製到 data/recipe 裡面

記得將檔名和檔案中的 minecraft:copper_ore, minecraft:copper_ingot 替換掉。

{
  "type": "minecraft:smelting",
  "category": "misc",
  "cookingtime": 200,
  "experience": 0.7,
  "group": "creeper_ingot",
  "ingredient": {
    "item": "mays-mod:raw_creeper"
  },
  "result": {
    "id": "mays-mod:creeper_ingot"
  }
}

因為有太多,這邊只能簡單介紹有序合成熔爐兩個,其他請參考:https://minecraft.fandom.com/wiki/Recipe

標籤(Tags)

標籤可以用來分組不同模組的物品,使這些物品互相兼容。

假設我現在要新增一個標籤是 special_ores,包含了:我自定義的苦力怕礦,還有原本就有的鐵礦、煤礦、金礦、鑽石礦、青金石礦、紅石礦、綠寶石礦、銅礦石,只需要新增 /data/<mod_id>/tags/block/special_ores.json  將這些礦通通寫進 values:

{
  "replace": false,
  "values": [
    "mays-mod:creeper_ore",
    "#minecraft:coal_ores",
    "#minecraft:iron_ores",
    "#minecraft:gold_ores",
    "#minecraft:lapis_ores",
    "#minecraft:diamond_ores",
    "#minecraft:redstone_ores",
    "#minecraft:emerald_ores",
    "#minecraft:copper_ores"
  ]
}

接著在 java/com/<mod_id>/util 新增 ModTags.java

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> SPECIAL_ORES = createTag("special_ores");

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

    public static class Items {

    }
}

未來如果你需要檢查一個方塊是否屬於 special_ores 這個標籤,就可以這麼新增一個 isSpecialOres 方法:

private boolean isSpecialOres(BlockState state) {
  return state.isIn(ModTags.Blocks.SPECIAL_ORES);
}
Exit mobile version