MOD製作チュートリアル > TileEntityの追加

概要

インベントリを持ち、アイテムを保持できるTileEntityを追加する。
GUIの実装はしていない。

ソースコード

  • AluminiumMod.java
package tutorial.aluminiummod;
 
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.block.Block;
 
@Mod(modid = AluminiumMod.MODID, name = AluminiumMod.MODNAME, version = AluminiumMod.VERSION)
public class AluminiumMod {
 
	public static final String MODID = "AluminiumMod";
	public static final String MODNAME = "Aluminium Mod";
	public static final String VERSION = "1.0.0";
 
	public static Block chestAluminium;
 
	@EventHandler
	public void perInit(FMLPreInitializationEvent event) {
		chestAluminium = new BlockAluminiumChest()
				.setBlockName("chestAluminium")
				.setBlockTextureName("aluminiummod:Aluminium_Chest");
		GameRegistry.registerBlock(chestAluminium, "chestAluminium");
		GameRegistry.registerTileEntity(TileEntityAluminiumChest.class, "TileEntityAluminiumChest");
	}
 
}
 

  • BlockAluminiumChest.java
package tutorial.aluminiummod;
 
import java.util.Random;
 
import net.minecraft.block.Block;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
 
public class BlockAluminiumChest extends Block implements ITileEntityProvider {
 
	private Random random = new Random();
 
	public BlockAluminiumChest() {
		super(Material.rock);
		this.setCreativeTab(CreativeTabs.tabDecorations);
		this.setHardness(5.0F);
		this.setResistance(1.0F);
		this.setStepSound(soundTypeMetal);
		isBlockContainer = true;
	}
 
	@Override
	public TileEntity createNewTileEntity(World world, int meta) {
		return new TileEntityAluminiumChest();
	}
 
	@Override
	public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) {
		// TileEntityを取得し、プレイヤーが手にアイテムを持っていないなら取り出し、持っているなら入れる。
		TileEntity tileEntity = world.getTileEntity(x, y, z);
		if (tileEntity == null || !(tileEntity instanceof TileEntityAluminiumChest))
			return false;
		TileEntityAluminiumChest chest = (TileEntityAluminiumChest) tileEntity;
		if (player.getHeldItem() == null) {
			player.inventory.mainInventory[player.inventory.currentItem] = chest.tryExportItemStack();
		} else {
			if (chest.tryImportItemStack(player.getHeldItem())) {
				player.inventory.mainInventory[player.inventory.currentItem] = null;
			}
		}
		return true;
	}
 
	@Override
	public void breakBlock(World world, int x, int y, int z, Block block, int meta) {
		// TileEntityの内部にあるアイテムをドロップさせる。
		TileEntityAluminiumChest tileentity = (TileEntityAluminiumChest) world.getTileEntity(x, y, z);
		if (tileentity != null) {
			for (int i = 0; i < tileentity.getSizeInventory(); i++) {
				ItemStack itemStack = tileentity.getStackInSlot(i);
 
				if (itemStack != null) {
					float f = random.nextFloat() * 0.6F + 0.1F;
					float f1 = random.nextFloat() * 0.6F + 0.1F;
					float f2 = random.nextFloat() * 0.6F + 0.1F;
 
					while (itemStack.stackSize > 0) {
						int j = random.nextInt(21) + 10;
 
						if (j > itemStack.stackSize) {
							j = itemStack.stackSize;
						}
 
						itemStack.stackSize -= j;
						EntityItem entityItem = new EntityItem(world, x + f, y + f1, z + f2,
								new ItemStack(itemStack.getItem(), j, itemStack.getItemDamage()));
 
						if (itemStack.hasTagCompound()) {
							entityItem.getEntityItem()
									.setTagCompound(((NBTTagCompound) itemStack.getTagCompound().copy()));
						}
 
						float f3 = 0.025F;
						entityItem.motionX = (float) random.nextGaussian() * f3;
						entityItem.motionY = (float) random.nextGaussian() * f3 + 0.1F;
						entityItem.motionZ = (float) random.nextGaussian() * f3;
						world.spawnEntityInWorld(entityItem);
					}
				}
			}
			world.func_147453_f(x, y, z, block);
		}
		super.breakBlock(world, x, y, z, block, meta);
	}
 
}
 

  • TileEntityAluminiumChest.java
package tutorial.aluminiummod;
 
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
 
public class TileEntityAluminiumChest extends TileEntity implements IInventory {
 
	protected ItemStack[] itemStacks = new ItemStack[54];
	protected byte importingSlot;
	protected byte exportingSlot;
 
	public boolean tryImportItemStack(ItemStack itemStack) {
		for (int i = 0; i < this.getSizeInventory(); i++) {
			importingSlot = this.getNextSlot(importingSlot);
			if (itemStacks[importingSlot] == null) {
				itemStacks[importingSlot] = itemStack.copy();
				return true;
			}
		}
		return false;
	}
 
	public ItemStack tryExportItemStack() {
		for (int i = 0; i < this.getSizeInventory(); i++) {
			exportingSlot = this.getNextSlot(exportingSlot);
			if (itemStacks[exportingSlot] != null) {
				ItemStack itemStack = itemStacks[exportingSlot].copy();
				itemStacks[exportingSlot] = null;
				return itemStack;
			}
		}
		return null;
	}
 
	protected byte getNextSlot(byte slot) {
		slot++;
		if (slot >= this.getSizeInventory())
			slot = 0;
		return slot;
	}
 
	@Override
	public void writeToNBT(NBTTagCompound nbt) {
		super.writeToNBT(nbt);
		NBTTagList nbttaglist = new NBTTagList();
		for (int i = 0; i < itemStacks.length; i++) {
			if (itemStacks[i] == null)
				continue;
			NBTTagCompound nbt1 = new NBTTagCompound();
			nbt1.setByte("Slot", (byte) i);
			itemStacks[i].writeToNBT(nbt1);
			nbttaglist.appendTag(nbt1);
		}
		nbt.setTag("Items", nbttaglist);
		nbt.setByte("ImportingSlot", importingSlot);
		nbt.setByte("ExportingSlot", exportingSlot);
	}
 
	@Override
	public void readFromNBT(NBTTagCompound nbt) {
		super.readFromNBT(nbt);
		NBTTagList nbttaglist = nbt.getTagList("Items", 10);
		itemStacks = new ItemStack[54];
		for (int i = 0; i < nbttaglist.tagCount(); i++) {
			NBTTagCompound nbt1 = nbttaglist.getCompoundTagAt(i);
			byte b0 = nbt1.getByte("Slot");
			if (0 <= b0 && b0 < itemStacks.length) {
				itemStacks[b0] = ItemStack.loadItemStackFromNBT(nbt1);
			}
		}
		importingSlot = nbt.getByte("ImportingSlot");
		exportingSlot = nbt.getByte("ExportingSlot");
	}
 
	@Override
	public int getSizeInventory() {
		return 54;
	}
 
	@Override
	public ItemStack getStackInSlot(int slot) {
		return itemStacks[slot];
	}
 
	@Override
	public ItemStack decrStackSize(int slot, int amount) {
		if (itemStacks[slot] == null)
			return null;
		ItemStack itemstack;
		if (itemStacks[slot].stackSize <= amount) {
			itemstack = itemStacks[slot];
			itemStacks[slot] = null;
			return itemstack;
		}
		itemstack = itemStacks[slot].splitStack(amount);
		if (itemStacks[slot].stackSize < 1) {
			itemStacks[slot] = null;
		}
		return itemstack;
	}
 
	@Override
	public ItemStack getStackInSlotOnClosing(int slot) {
		return null;
	}
 
	@Override
	public void setInventorySlotContents(int slot, ItemStack itemStack) {
		itemStacks[slot] = itemStack;
		if (itemStack != null && itemStack.stackSize > this.getInventoryStackLimit()) {
			itemStack.stackSize = this.getInventoryStackLimit();
		}
	}
 
	@Override
	public boolean hasCustomInventoryName() {
		return false;
	}
 
	@Override
	public String getInventoryName() {
		return "container.AluminiumMod.AluminiumChest";
	}
 
	@Override
	public int getInventoryStackLimit() {
		return 64;
	}
 
	@Override
	public boolean isUseableByPlayer(EntityPlayer player) {
		return worldObj.getTileEntity(xCoord, yCoord, zCoord) != this ? false : player.getDistanceSq(xCoord + 0.5D, yCoord + 0.5D, zCoord + 0.5D) <= 64.0D;
	}
 
	@Override
	public void openInventory() {}
 
	@Override
	public void closeInventory() {}
 
	@Override
	public boolean isItemValidForSlot(int slot, ItemStack itemStack) {
		return true;
	}
 
}
 

解説

GameRegistry

void registerTileEntity(Class<? extends TileEntity> tileEntityClass, String id)

TileEntityをマップに追加する処理。
これをやらないとreadFromNBTが呼ばれず、エラーが出る。

Block

boolean isBlockContainer

TileEntityを持つブロックかどうか。
使われてないようだが一応設定しておく。

boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ)

ブロックが右クリックされた時の処理。

void breakBlock(World world, int x, int y, int z, Block block, int meta)

ブロックが破壊された時の処理。

ITileEntityProvider

TileEntityを持つブロックのためのインターフェース。

TileEntity createNewTileEntity(World world, int meta)

TileEntityのインスタンスを生成し返す。

TileEntity

void writeToNBT(NBTTagCompound nbt)

引数のNBTにTileEntityのデータを書き込む処理。

void readFromNBT(NBTTagCompound nbt)

引数のNBTからTileEntityのデータを読み込む処理。

IInventory

インベントリを持つTileEntityのためのインターフェース。

int getSizeInventory()

インベントリのスロット数を返す。

ItemStack getStackInSlot(int slot)

引数のスロットに入っているItemStackを返す。

ItemStack decrStackSize(int slot, int amount)

第一引数のスロットに入ってるItemStackのスタック数を第二引数の量減らす。

ItemStack getStackInSlotOnClosing(int slot)

GUIが閉じられた時に、引数のスロットの中身を返し、消す処理。
エンチャントテーブルなど、GUIを閉じたときにドロップするものが使う。

void setInventorySlotContents(int slot, ItemStack itemStack)

引数のスロットの中身を設定する。

boolean hasCustomInventoryName()

名札でつけられた名前を持つかどうか。

String getInventoryName()

デフォルトの名前を返す。

int getInventoryStackLimit()

インベントリのスタック数の最大値を返す。

boolean isUseableByPlayer(EntityPlayer player)

引数のプレイヤーがGUIを開けるかどうか。

void openInventory()

GUIを開いたときの処理。

void closeInventory()

GUIを閉じたときの処理。

boolean isItemValidForSlot(int slot, ItemStack itemStack)

ホッパーなどが引数のスロットにアクセスできるかを返す。

使用例

プレゼントボックスを追加している部分。
+オファレンMOD
  • OfalenModCore.java
package nahama.ofalenmod;
 
/*略*/
 
/**
 * @author Akasata Nahama
 */
@Mod(modid = OfalenModCore.MODID, name = OfalenModCore.MODNAME, version = OfalenModCore.VERSION)
public class OfalenModCore {
 
	public static final String MODID = "OfalenMod";
	public static final String MODNAME = "Ofalen Mod";
	public static final String MCVERSION = "1.7.10";
	public static final String OMVERSION = "1.1.0";
	public static final String VERSION = "[" + MCVERSION + "]" + OMVERSION;
 
 
/*略*/
 
	/** 初期化前処理。 */
	@EventHandler
	public void preInit(FMLPreInitializationEvent event) {
/*略*/
		OfalenModBlockCore.registerBlock();
/*略*/
	}
 
/*略*/
 
}
 

  • OfalenModBlockCore.java
package nahama.ofalenmod.core;
 
/*略*/
 
public class OfalenModBlockCore {
 
/*略*/
	public static Block boxPresentOfalen;
 
	/** ブロックを登録する処理。 */
	public static void registerBlock() {
/*略*/
		boxPresentOfalen = new BlockPresentBox()
				.setBlockName("boxPresentOfalen")
				.setBlockTextureName("ofalenmod:present_box");
		GameRegistry.registerBlock(boxPresentOfalen, "boxPresentOfalen");
		GameRegistry.registerTileEntity(TileEntityPresentBox.class, "TileEntityOfalenPresentBox");
	}
 
}
 

  • BlockPresentBox.java
package nahama.ofalenmod.block;
 
/*略*/
 
public class BlockPresentBox extends Block implements ITileEntityProvider {
 
	private Random random = new Random();
	/** 0:下,1:上,2:横,3:クリスマス下,4;クリスマス上,5:クリスマス横 */
	private IIcon[] iicon = new IIcon[6];
 
	public BlockPresentBox() {
		super(Material.sponge);
		this.setCreativeTab(OfalenModCore.tabOfalen);
		this.setHardness(1.0F);
		this.setResistance(1.0F);
		this.setStepSound(Block.soundTypeCloth);
	}
 
	@Override
	public TileEntity createNewTileEntity(World world, int meta) {
		return new TileEntityPresentBox();
	}
 
/*略*/
 
	/** ブロックが破壊された時の処理。 */
	@Override
	public void breakBlock(World world, int x, int y, int z, Block block, int meta) {
		// TileEntityの内部にあるアイテムをドロップさせる。
		TileEntityPresentBox tileentity = (TileEntityPresentBox) world.getTileEntity(x, y, z);
		if (tileentity != null) {
			for (int i = 0; i < tileentity.getSizeInventory(); i++) {
				ItemStack itemStack = tileentity.getStackInSlot(i);
 
				if (itemStack != null) {
					float f = random.nextFloat() * 0.6F + 0.1F;
					float f1 = random.nextFloat() * 0.6F + 0.1F;
					float f2 = random.nextFloat() * 0.6F + 0.1F;
 
					while (itemStack.stackSize > 0) {
						int j = random.nextInt(21) + 10;
 
						if (j > itemStack.stackSize) {
							j = itemStack.stackSize;
						}
 
						itemStack.stackSize -= j;
						EntityItem entityItem = new EntityItem(world, x + f, y + f1, z + f2, new ItemStack(itemStack.getItem(), j, itemStack.getItemDamage()));
 
						if (itemStack.hasTagCompound()) {
							entityItem.getEntityItem().setTagCompound(((NBTTagCompound) itemStack.getTagCompound().copy()));
						}
 
						float f3 = 0.025F;
						entityItem.motionX = (float) random.nextGaussian() * f3;
						entityItem.motionY = (float) random.nextGaussian() * f3 + 0.1F;
						entityItem.motionZ = (float) random.nextGaussian() * f3;
						world.spawnEntityInWorld(entityItem);
					}
				}
			}
			world.func_147453_f(x, y, z, block);
		}
		super.breakBlock(world, x, y, z, block, meta);
	}
 
	/** ブロックのアイコンを登録する処理。 */
	@Override
	@SideOnly(Side.CLIENT)
	public void registerBlockIcons(IIconRegister register) {
		for (int i = 0; i < 6; i++) {
			iicon[i] = register.registerIcon(this.getTextureName() + "-" + i);
		}
	}
 
	/** ブロックのアイコンを返す。 */
	@Override
	@SideOnly(Side.CLIENT)
	public IIcon getIcon(int side, int meta) {
		int i = 2;
		if (side == 0)
			i = 0;
		if (side == 1)
			i = 1;
		if (OfalenModAnniversaryHandler.isChristmas)
			i += 3;
		return iicon[i];
	}
 
}
 

  • TileEntityPresentBox.java
package nahama.ofalenmod.tileentity;
 
import nahama.ofalenmod.handler.OfalenModAnniversaryHandler;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
 
public class TileEntityPresentBox extends TileEntity implements IInventory {
 
	protected ItemStack[] itemStacks = new ItemStack[54];
	protected String owner;
 
/*略*/
 
	@Override
	public void writeToNBT(NBTTagCompound nbt) {
		super.writeToNBT(nbt);
		NBTTagList nbttaglist = new NBTTagList();
		for (int i = 0; i < itemStacks.length; i++) {
			if (itemStacks[i] == null)
				continue;
			NBTTagCompound nbt1 = new NBTTagCompound();
			nbt1.setByte("Slot", (byte) i);
			itemStacks[i].writeToNBT(nbt1);
			nbttaglist.appendTag(nbt1);
		}
		nbt.setTag("Items", nbttaglist);
		nbt.setString("Owner", owner);
	}
 
	@Override
	public void readFromNBT(NBTTagCompound nbt) {
		super.readFromNBT(nbt);
		NBTTagList nbttaglist = nbt.getTagList("Items", 10);
		itemStacks = new ItemStack[54];
		for (int i = 0; i < nbttaglist.tagCount(); i++) {
			NBTTagCompound nbt1 = nbttaglist.getCompoundTagAt(i);
			byte b0 = nbt1.getByte("Slot");
			if (0 <= b0 && b0 < itemStacks.length) {
				itemStacks[b0] = ItemStack.loadItemStackFromNBT(nbt1);
			}
		}
		owner = nbt.getString("Owner");
	}
 
	/** インベントリのスロット数を返す。 */
	@Override
	public int getSizeInventory() {
		return 54;
	}
 
	/** スロットのアイテムを返す。 */
	@Override
	public ItemStack getStackInSlot(int slot) {
		return itemStacks[slot];
	}
 
	/** スロットのスタック数を減らす。 */
	@Override
	public ItemStack decrStackSize(int slot, int amount) {
		if (itemStacks[slot] == null)
			return null;
		ItemStack itemstack;
		if (itemStacks[slot].stackSize <= amount) {
			itemstack = itemStacks[slot];
			itemStacks[slot] = null;
			return itemstack;
		}
		itemstack = itemStacks[slot].splitStack(amount);
		if (itemStacks[slot].stackSize < 1) {
			itemStacks[slot] = null;
		}
		return itemstack;
	}
 
	@Override
	public ItemStack getStackInSlotOnClosing(int slot) {
		return null;
	}
 
	/** スロットの中身を設定する。 */
	@Override
	public void setInventorySlotContents(int slot, ItemStack itemStack) {
		itemStacks[slot] = itemStack;
		if (itemStack != null && itemStack.stackSize > this.getInventoryStackLimit()) {
			itemStack.stackSize = this.getInventoryStackLimit();
		}
	}
 
	/** 金床で設定された名前を持つかどうか。 */
	@Override
	public boolean hasCustomInventoryName() {
		return false;
	}
 
	/** インベントリの名前を返す。 */
	@Override
	public String getInventoryName() {
		return "container.OfalenMod.PresentBox";
	}
 
	/** このインベントリの最大スタック数を返す。 */
	@Override
	public int getInventoryStackLimit() {
		return 64;
	}
 
	/** プレイヤーが使用できるかどうか。 */
	@Override
	public boolean isUseableByPlayer(EntityPlayer player) {
		if (owner != null && !player.getCommandSenderName().equals(owner))
			return false;
		return worldObj.getTileEntity(xCoord, yCoord, zCoord) != this ? false : player.getDistanceSq(xCoord + 0.5D, yCoord + 0.5D, zCoord + 0.5D) <= 64.0D;
	}
 
	@Override
	public void openInventory() {}
 
	@Override
	public void closeInventory() {}
 
	/** スロットにアクセスできるかどうか。 */
	@Override
	public boolean isItemValidForSlot(int slot, ItemStack itemStack) {
		return false;
	}
 
}
 

コメント

この項目に関する質問などをどうぞ。
名前: