うまげーむさん

Fortniteなどのゲームの情報を主に投稿します。Twitterでブログの更新をツイートしてます。(@umageemu)

【マインクラフト Modding】1.15対応 自作MODの作り方 #5 ブロック、レシピの追加

このシリーズのまとめはこちら:

umagame.hatenablog.jp

どうも。

完全にこのシリーズにはまってしまいました。

はじめに

今回はブロックと、レシピの追加をやります。

前回作った圧縮土をさらに圧縮した、圧縮された土ブロックを作ります。

そして、前回のアイテムのレシピも設定します。

前回の記事:

umagame.hatenablog.jp

ブロックの追加

ブロックのクラス

ブロックは前回やったアイテムと同じように、ブロックのクラスとブロック登録用のクラスを作ります。

まずはブロックのクラスを作りましょう。

f:id:Umagame:20200314220743p:plain

前回と同じようにBlockクラスを継承して、コンストラクタを追加します。

package com.umagame.dirtmod.block;

import net.minecraft.block.Block;

public class BlockSuperCompressedDirt extends Block{

    public BlockSuperCompressedDirt(Properties properties) {
        super(properties);
    }
}

コンストラクタの中身についてですが、前回と違って今回はPropertiesクラスのcreateメソッドを使います。

あと、ID(レジストリーネーム)も設定しておきます。

public BlockSuperCompressedDirt() {
    super(Properties.create(Material.ROCK));
    this.setRegistryName("super_compressed_dirt");
}

createを使うことにより、ブロックの材質(Material)を設定できます。

今回は圧縮されまくっているので、石と同じROCKにしておきます。

あと、hardnessAndResistanceを使って硬さ、爆発耐性を設定します。

硬さと爆発耐性に関しては、こちらのサイトを参考にすると良いです。

https://minecraft-ja.gamepedia.com/採掘

https://minecraft.gamepedia.com/Explosion

Minecraft Wiki

硬さは、上のサイトでいうと一番左の値を入力しましょう。

今回は、バニラの石と同じにするため硬さを1.5、爆発耐性を6にします。

public BlockSuperCompressedDirt() {
    super(Properties.create(Material.ROCK).hardnessAndResistance(1.5F,6.0F));
}

次に採掘レベルと、適正ツールを設定します。

採掘レベルはgetHarvestLevel、適正ツールはgetHarvestToolで設定します。

採掘レベルを設定することで、鉱石のようにツールの材質によって取れるか取れないかを設定することができます。(0なら木、1なら石、2なら鉄、3ならダイアツルハシ)

今回は石と同じにするので採掘レベルを0、適正ツールをツルハシにします。

最終的にこうなります。

package com.umagame.dirtmod.block;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.material.Material;
import net.minecraftforge.common.ToolType;

public class BlockSuperCompressedDirt extends Block{

    public BlockSuperCompressedDirt() {
        super(Properties.create(Material.ROCK).hardnessAndResistance(1.5F,6.0F));
        this.setRegistryName("super_compressed_dirt");
    }
    
    @Override
    public int getHarvestLevel(BlockState state) {
        return 0;
    }
    @Override
    public ToolType getHarvestTool(BlockState state) {
        return ToolType.PICKAXE;
    }
}

これでブロックのクラスはOKです。

ブロックの登録

登録用クラスを作ります。

f:id:Umagame:20200314223408p:plain

中身は前回同様、丸パクリです。

package com.umagame.dirtmod.init;

import com.google.common.base.Preconditions;
import com.umagame.dirtmod.block.BlockSuperCompressedDirt;
import com.umagame.dirtmod.main.DirtMod;

import net.minecraft.block.Block;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.Item.Properties;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
import net.minecraftforge.registries.ObjectHolder;

@ObjectHolder(DirtMod.MOD_ID)
public class DirtModBlocks {

    public static final BlockSuperCompressedDirt SUPER_COMPRESSED_DIRT = null;

    @Mod.EventBusSubscriber(modid = DirtMod.MOD_ID, bus = Bus.MOD)
    public static class Register {

        @SubscribeEvent
        public static void registerBlock(final RegistryEvent.Register<Block> event) {
            final Block[] blocks = {
                    new BlockSuperCompressedDirt()
            };

            event.getRegistry().registerAll(blocks);
        }

        @SubscribeEvent
        public static void registerBlockItems(final RegistryEvent.Register<Item> event) {
            final BlockItem[] items = {
                    new BlockItem(SUPER_COMPRESSED_DIRT,new Properties().group(DirtMod.DIRTMOD_TAB))
            };

            for(final BlockItem item : items) {
                final Block block = item.getBlock();
                final ResourceLocation registryName = Preconditions.checkNotNull(block.getRegistryName(), "Block %s has a null registry name", block);
                event.getRegistry().register(item.setRegistryName(registryName));
            }
        }
    }
}

前回と違うところは、ブロックのインスタンス(SUPER_COMPRESSED_DIRT)を作っているところと、

ブロックそのものと、アイテムとしてのブロックをそれぞれ登録しているところです。(registerBlock、registerBlockItems)

とりあえずこれをコピペすればOKです。

03/24追記:このコードだと最初のpublic static final Block...のところでエラーが出る場合があるので、nullを返すメソッドを作ってそれを使います。

こんな感じでメソッドを作って、

public static <T> T Null() {
    return null;
}

public static final ... = Null();にすればOKです。

試しに起動してみると、テクスチャがないブロックが追加されています。

f:id:Umagame:20200314230201p:plain

設定した硬さや適正ツールなどはちゃんと反映されています。

テクスチャ、名前の設定

これに関してはほぼ前回と作業は同じです。

まずテクスチャを用意します。

f:id:Umagame:20200314232458p:plain

これをassets/ModのID/textures/blockに置きます。(ファイル名はブロックのIDに)

f:id:Umagame:20200314232659p:plain

次に、assets/ModのID/models/blockにjsonファイルを作ります。

f:id:Umagame:20200314233001p:plain

これにこんな感じで入力します。

{
    "parent": "block/cube_all",
    "textures": {
    "all": "ModのID:block/ブロックのID"
    }
}

今回の場合はこんな感じ。

{
    "parent": "block/cube_all",
    "textures": {
    "all": "dirtmod:block/super_compressed_dirt"
    }
}

また、itemの方にも追加する必要があります。

assets/ModのID/models/itemにまたjsonファイルを作成し、これを入力。

{
    "parent": "ModのID:block/ブロックのID"
}

今回はこんな感じ。

{
    "parent": "dirtmod:block/super_compressed_dirt"
}

ブロックの場合は、models以外にblockstatesも追加しなければいけません。

assets/ModのID/blockstatesに、ブロックのIDで新しくjsonファイルを作ります。

それに、こんな感じで入力。

{
    "variants": {
        "": { "model": "ModのID:block/ブロックのID" }
    }
}

今回はこんな感じ。

{
    "variants": {
        "": { "model": "dirtmod:block/super_compressed_dirt" }
    }
}

次に、assets/ModのID/langのファイルに次の1行を追加します。

"block.ModのID.ブロックのID": "名前"

前の行に「,」を追加するのを忘れずに。

今回でいうとen_usがこんな感じで、

{
    "itemGroup.dirtmod": "DirtMod",
    "item.dirtmod.compressed_dirt": "Compressed Dirt",
    "block.dirtmod.super_compressed_dirt": "Super-Compressed Dirt"
}

ja_jpがこんな感じ。

{
    "itemGroup.dirtmod": "DirtMod",
    "item.dirtmod.compressed_dirt": "圧縮された土",
    "block.dirtmod.super_compressed_dirt": "圧縮された土ブロック"
}

試しに起動すると、ちゃんとテクスチャと名前が反映されています。

f:id:Umagame:20200315004946p:plain

問題発生!

ですが、このブロックをサバイバルで壊してみると...なにもドロップしません。

これは修正する必要があります。

少し調べたところ、ルートテーブルと呼ばれるjsonファイルを作れば良いみたいです。(昔はこんなのなかったのに...)

src/main/resources/data/ModのID/loot_tables/blocksに、jsonファイルを作り、

f:id:Umagame:20200315183242p:plain

こんな感じに入力。

{
    "type": "minecraft:block",
    "pools": [
        {
            "name": "ModのID:好きな名前を入力",
            "rolls": 1,
            "entries": [
            {
                "type": "minecraft:item",
                "name": "ModのID:ブロックのID"
            }
            ],
            "conditions": [
                {
                    "condition": "minecraft:survives_explosion"
                }
            ]
        }
    ]
}

poolsのnameのところは、何でもいいです。(ルートテーブルのIDらしい)

今回の場合はこんな感じ。

{
    "type": "minecraft:block",
    "pools": [
        {
            "name": "dirtmod:dirtmodpool",
            "rolls": 1,
            "entries": [
            {
                "type": "minecraft:item",
                "name": "dirtmod:super_compressed_dirt"
            }
            ],
            "conditions": [
                {
                    "condition": "minecraft:survives_explosion"
                }
            ]
        }
    ]
}

これで起動すると、ドロップするようになります。

レシピの追加

最後にレシピの追加をします。

レシピは、実はjsonファイル一つで追加することができます。

src/main/resources/data/ModのID/recipesに、新しくjsonファイルを作ります。(名前はなんでもいいですが、今回はアイテムのIDに合わせます)

f:id:Umagame:20200315011920p:plain

f:id:Umagame:20200315012002p:plain

jsonの書き方ですが、レシピの追加にぴったりなサイトを見つけてしまいました。

https://crafting.thedestruc7i0n.ca

このサイトでは直感的にレシピを作れて、そのjsonも表示してくれます。(かまどなどのレシピも作れます)

今回は土9個で圧縮された土1個なのでこうしました。

{
    "type": "minecraft:crafting_shaped",
    "pattern": [
        "###",
        "###",
        "###"
    ],
    "key": {
        "#": {
            "item": "minecraft:dirt"
        }
    },
    "result": {
        "item": "dirtmod:compressed_dirt",
        "count": 1
    }
}

起動するとちゃんと追加されてました。

f:id:Umagame:20200315012009p:plain

さいごに

今回はここまでです。

実は、ブロックのテクスチャのところで結構苦戦しました。(笑)

ブロックの場合でもmodels/itemにjsonを作らないといけないのを完全に忘れてて、30分ぐらい取られた気がします...

そういうことがありながら、この記事を書いていたのでもしかしたらソースコード等に間違いがあるかもしれません。そのときはご指摘お願いします。

次回:

umagame.hatenablog.jp

ではでは。