Minecraft Forge 1.13.2 変更点などまとめ Part2
セットアップ段階での話は既に書いたので、主にアイテムとかブロックとかの登録方法の変更について書いておこうと思います。
mikan-alpha.hatenablog.comForge 1.13.2の現時点での仕様
FML(Pre、Post)InitializationEventの廃止
まずmdkをEclipseで開いて少し弄ってれば分かりますが、今まで使われていたこれらのイベントが廃止されました。(ついでにEventHandlerアノテーションも廃止されたようです)
代わりとして、FMLCommonSetupEvent、FMLClientSetupEvent、InterModEnqueueEvent、InterModProcessEventが実装され、以下の順番で発火されます。
(RegistryEvent.Register)→ FMLCommonSetupEvent → FMLClientSetupEvent → InterModEnqueueEvent → InterModProcessEvent
※このように引数にfinal修飾子が必要になった
private void setup(final FMLCommonSetupEvent event) { // some preinit code }
ただ、書いておけば勝手に発火されるのではなく、メインのクラスのコンストラクタにてリスナーというやつを追加しておく必要があります。
※ModのメインクラスがExampleMod.javaの場合
public ExampleMod() { // Register the setup method for modloading FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup); // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); }
またこれに伴ってアイテムやブロック、Entityなどの登録の仕方が若干変わりました。
アイテムなどの登録は上の4つのイベントが発火されるより前に行われ、具体的には上に書いたRegistryEvent.Register<T>のときに行われます。
@Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD) public static class RegistryEvents { @SubscribeEvent public static void onBlocksRegistry(final RegistryEvent.Register<Block> blockRegister) { // register a new block here } @SubscribeEvent public static void onItemsRegistry(final RegistryEvent.Register<Item> itemRegister) { // register a new item here } @SubscribeEvent public static void onEntityTypesRegistry(final RegistryEvent.Register<EntityType<?>> entityRegister) { // register a new entity here } }
メインのクラスの中にネストする形で上記のMod.EventBusSubscriberアノテーションを付けたクラスを作り、その中にレジストリのイベントをまとめておくと簡単です。
具体的なアイテム・ブロックなどの登録方法
1.10あたりからオブジェクトホルダーとかいうのを使った登録方法があるのですが、私は1.8からModdingをしている老人なので(ほぼ)昔からと同じ方法でやっています。
ModItems.java
import net.minecraft.item.Item; import net.minecraftforge.registries.ForgeRegistries; public class ModItems { public static Item test; public static void init() { test = new ItemTest(); } public static void register() { ForgeRegistries.ITEMS.registerAll(test); } }
このinit()とregister()を上のRegistryEvent.Register<Item>のときに実行してやればめでたく1.13の世界にアイテムが追加できます。
@SubscribeEvent public static void onItemsRegistry(final RegistryEvent.Register<Item> itemRegister) { ModItems.init(); ModItems.register(); }
あと、アイテムとブロックのレンダラーを何もしなくても登録してくれるようになりました。
assetsのいつもの場所にjsonを置いておけば勝手に読み込んでくれます。
アイテムのプロパティの設定の仕方が変わった
上のソースではItemTestクラスとしてごまかしてしまいましたが、アイテムのスタックできる数の設定とか、ブロックの硬さの設定とか、そこらへんも少し変わりました。
具体的には、ItemクラスのコンストラクタにはItem.Propertiesのインスタンス、BlockクラスのコンストラクタにはBlock.Propertiesのインスタンスを渡す必要があります。
どういうことか、ざっくり解説します。
まず、無機能アイテムをつくるとして、Itemを継承したクラスを作ります。
public class ItemTest extends Item { public ItemTest() { // このPropertiesにいろいろくっつける super(new Properties()); this.setRegistryName(modid, name); } }
すると1.12まではスーパークラスに何も渡す必要は無かったのですが、こんな感じにItem.Propertiesのインスタンスを生成してやって渡す必要があります。
で、今まではthis.setCreativeTab(...);みたいにやってたのですが、こういった情報は全てPropertiesが持つことになりました。例えばタブの設定をしたければこう書きます。
public class ItemTest extends Item { public ItemTest() { // このPropertiesにいろいろくっつける super(new Properties().group(ItemGroup.BUILDING_BLOCKS)); this.setRegistryName(modid, name); } }
あとUnlocalizedNameは廃止されたっぽいですね。
ブロックのPropertiesの方もアイテムと似たような感じなので省略します。
Entityの登録の仕方はかなりまるっと変わった
タイトルが全てです。結構変わってます。そもそも、Entity自体ではなくEntityTypeというやつを登録するようになりました。
ModEntities.java
import net.minecraft.entity.EntityType; public class ModEntities { public static EntityType<EntityTest> test; public static void init() { test = EntityType.Builder.create(EntityTest.class, EntityTest::new).tracker(60, 5, true).build(name); } public static void setName() { test.setRegistryName(modid, name); } }
build()の引数は「MODID:Entityの名前」です。examplemod:testみたいな感じ。
あとは、アイテムとかと同じでinit()とsetName()をRegistryEvent.Register<EntityType<?>>のときに実行して、下記のようにやれば登録できます。上のメソッドだけでは登録になってないので注意。
@SubscribeEvent public static void onEntityTypesRegistry(final RegistryEvent.Register<EntityType<?>> entityRegister) { ModEntities.init(); ModEntities.setName(); entityRegister.getRegistry().registerAll(ModEntities.test); }
Entityのレンダラーに関しては、FMLClientSetupEventのときにRenderingRegistry.registerEntityRenderingHandler()を使って登録してやればOKです。
あと細かいことなど
なんか無限に書けてしまいそうなので細かいやつはまとめてしまいます。
1つ目。langファイルが.jsonになりました。まあこの変更は見やすくなっていいかな、という感じです。
assetsの中のlangに今までen_us.langみたいなのを入れてましたが、これがen_us.jsonになったということです。中身はこんな感じで書きます。
{ "itemGroup.tabExample": "Example", "item.examplemod.test": "Test Item" }
普通のjsonですね。アイテムなら「item.(MODのID).(RegistryName)」の後にローカライズ後の文字列、ブロックなら「block.(MODのID).(RegistryName)」の後に、という風に書きます。まあ、習うよりやったほうが速いと思います。(暴論)
2つ目に、クリエイティブタブの作り方が少し変わりました。
public static ItemGroup tabExample = (new ItemGroup("tabExample") { @Override public ItemStack createIcon() { return new ItemStack(Items.IRON_PICKAXE); } });
これをメインのクラスにでも宣言しておけば新規タブの作成完了です。
まあ、ざっと目立つところでの変更点はこんな感じでしょうか。
バイオームの追加とかはまだ手を付けてないので、大幅に変わっているようだったらまた書きたいと思います。では、素敵なModdingライフを。