4日目 アイテムの機能の追加
今回は簡単な機能を持ったアイテムを作成しようと思います。前回作成したトマトは何の機能も持たないアイテムだったので、もう少し実用的な何かを作りたいと思います。
まずは、トマトを追加したときと同じようにアイテムを登録します。
1日目 アイテムの追加 - 初心者modderの備忘録
モンスターエッグのような効果を持ったアイテムを作りたいのでトマトエッグと名付けてクラスを作成します。
ItemTomatoEgg.java
package testmod; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.item.Item; public class ItemTomatoEgg extends Item { public ItemTomatoEgg() { this.setCreativeTab(CreativeTabs.MATERIALS); this.setUnlocalizedName("tomato_egg"); this.setRegistryName("tomato_egg"); } }
testmod.java
package testmod; import net.minecraft.block.Block; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.registry.ForgeRegistries; @Mod(modid = testmod.MOD_ID, name = testmod.MOD_NAME, version = testmod.MOD_VERSION) public class testmod { public static final String MOD_ID = "testmod"; public static final String MOD_NAME = "testmod"; public static final String MOD_VERSION = "1.0.0"; public static final Item Tomato = new ItemTomato(); public static final Item TomatoEgg = new ItemTomatoEgg(); public static final Block Tomato_Block = new BlockTomato(); @Mod.EventHandler public void preInit(FMLPreInitializationEvent event) { ForgeRegistries.ITEMS.register(Tomato); ForgeRegistries.ITEMS.register(new ItemBlock(Tomato_Block).setRegistryName("testmod", "block_tomato")); ForgeRegistries.ITEMS.register(TomatoEgg); ForgeRegistries.BLOCKS.register(Tomato_Block); if(event.getSide().isClient()) { ModelLoader.setCustomModelResourceLocation(Tomato, 0, new ModelResourceLocation(new ResourceLocation("testmod", "tomato"), "inventory")); ModelLoader.setCustomModelResourceLocation(TomatoEgg, 0, new ModelResourceLocation(new ResourceLocation("testmod", "tomato_egg"), "inventory")); ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(Tomato_Block), 0, new ModelResourceLocation(new ResourceLocation("testmod", "block_tomato"), "inventory")); } } }
続いて、jsonファイル、テクスチャー画像、langファイルも設定してください。
テクスチャーにはこの画像を用いました。
あとは、ひたすらItemTomatoEggにコードを書き足していきます。
まず、右クリックの発動には2種類あります。クワのようにブロックにカーソルを合わせて右クリックする場合と、エンダーパールのように空中などカーソルがあっていなくても発動できる場合です。
今回は、選択したマスにモンスターをスポーンさせたいのでカーソルを合わせて使うタイプのアイテムに設定します。
クワは消費アイテムじゃないので、消費アイテムだと花火がそれに該当するようです。なので、参照ライブラリーからItemFireWork.classを開いて「Ctrl」+「F」で検索を開いて「click」で検索をかけました。すると一番上に「Called when a Block is right-clicked with this Item」とコメントされたメソッドが出てきたのでこれを参考にItemTomatoEggを編集します。
ItemTomatoEgg.java_ed1
public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { ItemStack itemstack = player.getHeldItem(hand); System.out.println("Block is Clicked"); if (!player.capabilities.isCreativeMode) { itemstack.shrink(1); } return EnumActionResult.SUCCESS; }
今書き足したのは、printlnでコンソールにメッセージを出力し、アイテムを1つ消費するだけの機能です。
実際に開いて、ブロックに合わせて右クリックしてみるとコンソール上にメッセージが出力されていることが確認できました。
このようにコンソール上に出力しておくことで、プログラムの動きを追えるようになるので便利だと思います。
右クリックを認識していることが確認できたので、ちゃんとした機能を実装しようと思います。
ItemTomatoEgg.java_ed2
public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { ItemStack itemstack = player.getHeldItem(hand); EntityLiving living = new EntityChicken(worldIn); living.setPosition(pos.offset(facing).getX()+0.5,pos.offset(facing).getY(),pos.offset(facing).getZ()+0.5); if(!worldIn.isRemote) worldIn.spawnEntity(living); System.out.println("Block is Clicked"); if (!player.capabilities.isCreativeMode) { itemstack.shrink(1); } return EnumActionResult.SUCCESS; }
こんな感じで動くようになりました。
今回はオリジナルのMOBがいないので、にわとりのスポーンエッグになりましたが、スポーンするエンティティをオリジナルにすれば専用のスポーンエッグにもなりますね。
ちなみに、if(!worldIn.isRemote)とsetPositionのX,Z座標の+0.5は最初は入れてなくてバグが起きました。
if(!worldIn.isRemote)を入れないとサーバー側とクライアント側とで2回実行されるためなのか、一度の使用で2羽のニワトリが生まれました。
また、getX()やgetZ()で得られる座標はint型で整数値なので、そのままだと選択しているブロックの角にスポーンするようでした。なので、となりに壁がある所でアイテムを使用すると壁に埋まって窒息してしまいました。
XとZ座標をそれぞれ+0.5することで選択したブロックの中心にスポーンするようになりました。
ちなみにほぼ同じ機能でアイテムをスポーンさせることもできます。
ItemTomatoEgg.java_ed3
public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { ItemStack itemstack = player.getHeldItem(hand); EntityItem item = new EntityItem(worldIn, pos.offset(facing).getX()+0.5, pos.offset(facing).getY(), pos.offset(facing).getZ()+0.5, new ItemStack(Items.BEEF, 4)); if(!worldIn.isRemote) worldIn.spawnEntity(item); System.out.println("Block is Clicked"); if (!player.capabilities.isCreativeMode) { itemstack.shrink(1); } return EnumActionResult.SUCCESS; }
spawnEntityの引数をEntityChickenからEntityItemに変更して、それに伴って数ヶ所変更しました。
4行目の最後のItemStackの第一引数がアイテム第二引数が個数です。
次回は、もう一つの右クリックの機能を持ったアイテムの追加をしようと思います。
最終的なItemTomatoEggのファイルをあげておきます。
ItemTomatoEgg.java(EntityChicken)
ItemTomatoEgg.java(ItemBeef)