初心者modderの備忘録

マイクラのmodを作りたくて、初めて見たのですが難しくて忘れそうなので自分用の備忘録も兼ねてブログにしようと思います

9日目 イベントリの追加

前回作ったint型のカウンターしか持たないTileEntityにイベントリを追加していこうと思います。
なので、今回はメインのクラスは触らず、BlockTomatoとTileEntityTomatoを書き換えます。

まず、TileEntityクラスを書き換えていきます。

TileEntityTomato.java

package test4mod;

import javax.annotation.Nullable;

import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.ItemStackHandler;

public class TileEntityTomato extends TileEntity{
	private ItemStackHandler inventory = new ItemStackHandler(1);

	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound compound) {
		compound.setTag("inventory", inventory.serializeNBT());
		return super.writeToNBT(compound);
	}
	
	@Override
	public void readFromNBT(NBTTagCompound compound) {
		inventory.deserializeNBT(compound.getCompoundTag("inventory"));
		super.readFromNBT(compound);
	}
	
	@Override
	public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing facing) {
		return capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || super.hasCapability(capability, facing);
	}
	
	@SuppressWarnings("unchecked")
	@Nullable
	@Override
	public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) {
		return capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ? (T)inventory : super.getCapability(capability, facing);
	}
}


1行目の
private ItemStackHandler inventory = new ItemStackHandler(1);
は引数にイベントリの数を入力します。今回は1つしかイベントリを持たないので1を入力。

後の行は正直あまり理解できていないのですが、前回int型の変数を保管するためにsetIntegerやgetIntegerを使ったのと同じようにイベントリを補完するために必要なコードくらいの認識です。


続いて、Blockクラスを書き換えていきます。

BlockTomato.java_part1

@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ) {
	if (!world.isRemote) {
		TileEntityTomato te = (TileEntityTomato) world.getTileEntity(pos);
		IItemHandler itemHandler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side);
		if (!player.isSneaking()) {
			if (player.getHeldItemMainhand().isEmpty()) {
				player.setHeldItem(hand, itemHandler.extractItem(0, 64, false));
			} else {
				player.setHeldItem(hand, itemHandler.insertItem(0, player.getHeldItemMainhand(), false));
			}
			te.markDirty();
		} else {
			ItemStack stack = itemHandler.getStackInSlot(0);
			if (!stack.isEmpty()) {
				System.out.println(stack.getItem().getRegistryName()+" "+stack.getCount());
			} else {
				System.out.println("Empty");
			}
		}
	}
	return true;
}

まず、右クリックしたときの処理を変更します。
サーバーかどうかを判断し、サーバーならTileEntityを生成します。
その後、非スニーク状態で、かつ、何も手にもっていない場合は引き出し、何か持っている場合は預ける処理をします。
スニーク状態で右クリックすると、中に何か入っている場合にはそのアイテム名と数を、空の場合はEmptyとそれぞれコンソール上に出力します。


BlockTomato.java_part2

@Override
public void breakBlock(World world, BlockPos pos, IBlockState state) {
	TileEntityTomato te = (TileEntityTomato) world.getTileEntity(pos);
	IItemHandler itemHandler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, EnumFacing.NORTH);
	ItemStack stack = itemHandler.getStackInSlot(0);
	if (!stack.isEmpty()) {
		EntityItem item = new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(), stack);
		world.spawnEntity(item);
	}
	super.breakBlock(world, pos, state);
}

次に、BreakBlockの処理を書き換えてブロックが壊されたときに中のアイテムをアイテムエンティティとしてドロップさせます。


これで実行してみました。

f:id:json_fileman:20190109013956g:plain


このときのログがこちらです。

f:id:json_fileman:20190109014035p:plain


ちゃんと出力されていますね!

次回はこのイベントリをguiを使って操作できるようにしたいと思います。

今回のファイルを載せておきます。
testmod.java
BlockTomato.java
TileEntityTomato.java