この記事は"Minecraft Forge4.3x"を前提MODとしています。 |
EnumHelperの利用
ModLoaderを利用したModdingにおいて, Enumというものがコードを冗長にさせた. 特にTool類はEnumToolMaterialがスーパークラスのコンストラクタになっているため, 大抵は新しいEnumを作成し, EnumToolMaterialとの橋渡しをしたり, スーパークラスのコンストラクタで設定された値をサブクラス側で書き換えるなどしていた. ForgeAPIであるEnumHelperはこの問題を解決しうるAPIである. 端的に言えば既存のEnumに新しい定数を追加するAPIである.
今回はEnumHelperを利用して, バニラのツールとは異なる性能のツール3種(ショベル, つるはし, 斧)と剣を追加する. なお, ソースコードの簡略化のためにコンフィグの追加や独自のテクスチャファイルの利用などは今回行わない. それらは別途必要に応じて対象チュートリアルを参照すること.
ソースコード
- ToolSampleCore.java
package mods.toolsample; import net.minecraft.src.*; import net.minecraftforge.common.EnumHelper; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.network.NetworkMod; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.common.registry.LanguageRegistry; @Mod( modid = "ToolSampleMod", name = "Tool Sample Mod", version = "1.0.0" ) @NetworkMod( clientSideRequired = true, serverSideRequired = false ) public class ToolSampleCore { public static Item itemSampleShovel; public static Item itemSampleAxe; public static Item itemSamplePickaxe; public static Item itemSampleSword; public static EnumToolMaterial newToolMaterial; @Mod.Init public void init(FMLInitializationEvent event) { newToolMaterial = EnumHelper.addToolMaterial("GOLDBLOCK", 2, 500, 6.0F, 2, 22); itemSampleSword = (new ItemSampleSword(5000, newToolMaterial)).setIconCoord(4, 4).setItemName("samplesword"); itemSampleShovel = (new ItemSampleShovel(5001, newToolMaterial)).setIconCoord(4, 5).setItemName("sampleshovel"); itemSamplePickaxe = (new ItemSamplePickaxe(5002, newToolMaterial)).setIconCoord(4, 6).setItemName("samplepickaxe"); itemSampleAxe = (new ItemSampleAxe(5003, newToolMaterial)).setIconCoord(4, 7).setItemName("sampleaxe"); LanguageRegistry.addName(itemSampleSword, "Sample Sword"); LanguageRegistry.addName(itemSampleShovel, "Sample Shovel"); LanguageRegistry.addName(itemSamplePickaxe, "Sample Pickaxe"); LanguageRegistry.addName(itemSampleAxe, "Sample Axe"); GameRegistry.addRecipe( new ItemStack(itemSampleSword, 1), new Object[] { "X", "X", "S", Character.valueOf('X'), Block.blockGold, Character.valueOf('S'), Item.stick }); GameRegistry.addRecipe( new ItemStack(itemSampleShovel, 1), new Object[] { "X", "S", "S", Character.valueOf('X'), Block.blockGold, Character.valueOf('S'), Item.stick }); GameRegistry.addRecipe( new ItemStack(itemSamplePickaxe, 1), new Object[] { "XXX", " S ", " S ", Character.valueOf('X'), Block.blockGold, Character.valueOf('S'), Item.stick }); GameRegistry.addRecipe( new ItemStack(itemSampleAxe, 1), new Object[] { "XX ", "XS ", " S ", Character.valueOf('X'), Block.blockGold, Character.valueOf('S'), Item.stick }); } }
- ItemSampleSword.java
package mods.toolsample; import net.minecraft.src.*; public class ItemSampleSword extends ItemSword { private int weaponDamage; private final EnumToolMaterial toolMateiral; public ItemSampleSword(int itemId, EnumToolMaterial _toolMaterial) { super(itemId, _toolMaterial); this.toolMaterial = _toolMaterial; this.maxStackSize = 1; this.weaponDamage = 4 + _toolMaterial.getDamageVsEntity(); this.setMaxDamage(_toolMaterial.getMaxUses()); } }
- ItemSampleShovel.java
package mods.toolsample; import net.minecraft.src.*; public class ItemSampleShovel extends ItemSpade { public ItemSampleShovel(int itemId, EnumToolMaterial toolMaterial) { super(itemId, toolMaterial); } }
- ItemSamplePickaxe.java
package mods.toolsample; import net.minecraft.src.*; public class ItemSamplePickaxe extends ItemPickaxe { public ItemSamplePickaxe(int itemId, EnumToolMaterial toolMaterial) { super(itemId, toolMaterial); } }
- ItemSampleAxe.java
package mods.toolsample; import net.minecraft.src.*; public class ItemSampleAxe extends ItemAxe { public ItemSampleAxe(int itemId, EnumToolMaterial toolMaterial) { super(itemId, toolMaterial); } }
解説
ToolSampleCoreクラス
newToolMaterial = EnumHelper.addToolMaterial("GOLDBLOCK", 2, 500, 6.0F, 2, 22);
ツール類の性能は個々の, たとえばItemStonePickaxeのようなクラスがあるわけではなく, ItemPickaxeの引数にTool Material(ツールの素材)というEnum定数が渡され, そのEnum定数によって生成するインスタンスを変えているだけである. Forgeを使わない場合, 新しい素材による性能の設定は各クラスで行う必要(EnumToolMaterial縛りをなんとかする方法)があったが, ForgeAPIにより, より簡単な方法が実装された. EnumHelperクラスは既存のEnumに新しいEnum定数を追加するAPIである. 今回利用したのはaddToolMaterialメソッドで, 引数は以下のとおり.
- Enum定数名
- 採掘レベル
- 耐久
- 採掘速度
- エンティティに対するダメージ
- エンチャント補正
今回は金ブロックを素材にした. 性能は採掘レベル, 採掘速度, ダメージが鉄と同じで, 耐久とエンチャント補正が鉄よりも高い.
GameRegistry.addRecipe( new ItemStack(itemSampleSword, 1), new Object[] { "X", "X", "S", Character.valueOf('X'), Block.blockGold, Character.valueOf('S'), Item.stick });
新しいレシピを追加する. 今までと異なり今回は定形レシピである. このようにModLoaderとそう違わない箇所もある.
ItemSampleSwordクラス
private int weaponDamage; private final EnumToolMaterial toolMateiral;
他のクラスと異なり剣だけこのようなフィールドを宣言している. これはItemSwordクラスでの上記のフィールドがprivateになっており, 継承しても利用できないためである. そのため, コンストラクタでスーパークラスと同じような処理をしている.
実際の挙動
見た目は金ツールと金の剣だが性能は異なり, ダイヤ鉱石まで掘れる. EnumHelperを利用することで異なる性能のツールをひとつのクラスから容易に作成できるようになる. EnumHelperはMinecraft内のほとんどのEnumに対し新しい定数を追加できる. しかし実際に追加して有効なものは少ない.