TileEntityの追加(1.7.10)

1.7.10の開発講座を修正中です。このページには誤りや古い情報が含まれる可能性があります。

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

ソースコード


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"); }

}


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); }

}


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)

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

使用例

プレゼントボックスを追加している部分。


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]; }

}


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; }

}

コメントはこちらです。(スパム対策の為コメントは手動承認になっています。未承認のコメントは表示されないので連投はお控え下さい。)

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください