(この記事は一連の解説記事の一つになります)
ブロックの追加
ブロックの追加をします。1.14.4のときと少し書き方を変えました(バージョンアップによって実装の方法が変わったという意味ではないです)。
ブロックの登録
\src\main\java\jp\koteko\liveinwater\
├ block
│ └ Blocks.java
├ item
└ LiveInWater.java
package jp.koteko.liveinwater.block;
import jp.koteko.liveinwater.LiveInWater;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import java.util.ArrayList;
import java.util.List;
@Mod.EventBusSubscriber(modid = LiveInWater.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class Blocks {
public static List<Block> blockList = new ArrayList<Block>();
public static Block WATERTREE_ROOT_BLOCK = register("watertree_root_block", new Block(AbstractBlock.Properties.create(Material.WOOD).hardnessAndResistance(2.5F).sound(SoundType.WOOD)));
private static Block register(String key, Block blockIn){
blockList.add(blockIn);
return blockIn.setRegistryName(LiveInWater.MOD_ID, key);
}
@SubscribeEvent
public static void registerBlocks(RegistryEvent.Register<Block> event) {
for (Block block : blockList) {
event.getRegistry().register(block);
}
}
}
前回のアイテム登録と同様のことをブロックについて行います。
宣言・初期化と同時にList
にアイテムを追加し、forループでリストのアイテムをすべてregister()
します。
単なる無機能ブロックの場合Block
クラスのインスタンスとします。コンストラクタの引数にはAbstractBlock.Properties
のインスタンスを与えます。
アイテムの登録
\src\main\java\jp\koteko\liveinwater\
├ block
├ item
│ └ Items.java
└ LiveInWater.java
package jp.koteko.liveinwater.item;
import jp.koteko.liveinwater.LiveInWater;
import jp.koteko.liveinwater.block.Blocks;
import net.minecraft.block.Block;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import java.util.ArrayList;
import java.util.List;
@Mod.EventBusSubscriber(modid = LiveInWater.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class Items {
public static List<Item> itemList = new ArrayList<Item>();
public static final Item WATERTREE_ROOT = register("watertree_root", new Item((new Item.Properties()).group(ItemGroup.MATERIALS)));
public static final Item WATERTREE_ROOT_BLOCK = register("watertree_root_block", Blocks.WATERTREE_ROOT_BLOCK, ItemGroup.BUILDING_BLOCKS);
private static Item register(String key, Item itemIn) {
itemList.add(itemIn);
return itemIn.setRegistryName(LiveInWater.MOD_ID, key);
}
private static Item register(String key, Block blockIn, ItemGroup itemGroupIn) {
return register(key, new BlockItem(blockIn, (new Item.Properties()).group(itemGroupIn)));
}
@SubscribeEvent
public static void registerItems(RegistryEvent.Register<Item> event) {
for (Item item : itemList) {
event.getRegistry().register(item);
}
}
}
ブロックは同時にアイテムとしても存在するので、アイテムも登録します。
register
メソッドをオーバーロード(異なる引数による同名メソッドの定義)してブロックアイテムの登録が行いやすいようにしました。登録名、ブロック、アイテムグループを渡すと、中でグループを設定したBlockItem
をつくり、アイテムのregister
に投げるようにします。
BlockItem
はItem
のサブクラスで、アイテムとしてのブロックはこのクラスのインスタンスとします。
resourcesの設定
\src\main\resources
└ assets
└ liveinwater
├ blockstates
│ └ watertree_root_block.json
├ lang
│ └ en_us.json
│ └ ja_jp.json
├ models
│ ├ block
│ │ └ watertree_root_block.json
│ └ item
│ └ watertree_root_block.json
└ textures
├ block
│ └ watertree_root_block.png
└ item
{
"item.liveinwater.watertree_root_block": "WaterTree Root"
}
{
"item.liveinwater.watertree_root_block": "ウォーターツリーの根"
}
{
"variants": {
"": { "model": "liveinwater:block/watertree_root_block" }
}
}
"model": "[MOD_ID]/[モデルファイルのパス]"
ブロックの状態によってモデルを変えるような場合(たとえば、方向を持つブロックや、フェンスなどの連結するブロック)にはこのファイルを編集しますが、不要な場合このような形です。
{
"parent": "block/cube_all",
"textures": {
"all": "liveinwater:block/watertree_root_block"
}
}
[MOD_ID]:[テクスチャファイルのパス]
parent
はblock/cube_all
を指定します。
これは単純な立方体のモデルで、全面に同じテクスチャを反映します。
{
"parent": "liveinwater:block/watertree_root_block"
}
ブロックアイテムはparent
にブロックのモデルファイルを指定すればよいです。
watertree_root_block.png
テクスチャを作成し、配置します。
ルートテーブルの設定
Minecraft 1.9以降ではドロップを管理する仕組みとしてルートテーブルが導入されました。ブロックのドロップもこれを使って設定します。
\src\main\resources
├ assets
└ data
└ liveinwater
└ loot_tables
└ blocks
└ watertree_root_block.json
前の記事で用意しておいたdata\liveinwater
フォルダ内にblocks\watertree_root_block.json
を配置します。
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"conditions": [
{
"condition": "minecraft:match_tool",
"predicate": {
"enchantments": [
{
"enchantment": "minecraft:silk_touch",
"levels": {
"min": 1
}
}
]
}
}
],
"entries": [
{
"type": "minecraft:item",
"name": "liveinwater:watertree_root_block"
}
]
},
{
"rolls": 1,
"conditions": [
{
"condition": "minecraft:inverted",
"term": {
"condition": "minecraft:match_tool",
"predicate": {
"enchantments": [
{
"enchantment": "minecraft:silk_touch",
"levels": {
"min": 1
}
}
]
}
}
}
],
"entries": [
{
"type": "minecraft:item",
"functions": [
{
"function": "minecraft:apply_bonus",
"enchantment": "minecraft:fortune",
"formula": "minecraft:binomial_with_bonus_count",
"parameters": {
"extra": 3,
"probability": 0.5714286
}
}
],
"name": "liveinwater:watertree_root"
}
]
},
{
"rolls": 1,
"conditions": [
{
"condition": "minecraft:inverted",
"term": {
"condition": "minecraft:match_tool",
"predicate": {
"enchantments": [
{
"enchantment": "minecraft:silk_touch",
"levels": {
"min": 1
}
}
]
}
}
}
],
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:dirt"
}
]
}
]
}
「シルクタッチのツールで破壊した場合ブロックそのもの(watertree_root_block
)を、それ以外の場合は土ブロック(dirt
)1つとアイテム(watertree_root
)をランダム個ドロップする」という例です。詳しい説明は参考ページに譲ります。
(色々と試しましたが重複する記述があり冗長な書き方である可能性があります。)
最小の構成はこのようになります。
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "[MOD_ID]:[ITEM_NAME]"
}
]
}
]
}
type
は何に関するルートテーブルかを選択する。pools
に与えた各プールが順次適応され、rolls
回の抽選によってentries
に与えた各エントリーから結果が選ばれる。エントリーでtype
のname
を返すと指定。
確認
ゲームを起動して確認します。
ブロックとそのアイテムの追加ができていること、表示が正しいこと、シルクタッチでブロックそのもの・非シルクタッチで土とアイテムがドロップすることが確認できました。
参考
[Java]MinecraftのModを作成しよう 1.14.4【2. ブロックの追加】
Minecraft 1.14.4 Forge Modの作成 その4 【ブロックの追加】
ルートテーブル - Minecraft Wiki
loot_tables_1.14.md · GitHub