package de.take_weiland.mods.commons.tileentity; import com.google.common.collect.Iterators; import de.take_weiland.mods.commons.inv.Inventories; import de.take_weiland.mods.commons.inv.NameableInventory; import de.take_weiland.mods.commons.util.Blocks; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import javax.annotation.Nonnull; import java.util.Iterator; /** * <p>Basic implementation of a {@link net.minecraft.tileentity.TileEntity} with an Inventory. Similar to * {@link de.take_weiland.mods.commons.inv.AbstractInventory}.</p> * <p>Note that this class implements {@link de.take_weiland.mods.commons.inv.NameableInventory}, so if you * use {@link Blocks#init} on your block (or * use {@link de.take_weiland.mods.commons.templates.SCItemBlock} as your custom ItemBlock class), this TileEntity * will automatically take the name of a renamed ItemStack when placed. To control that behavior, implement * {@link de.take_weiland.mods.commons.tileentity.TileAutoName}.</p> */ public abstract class TileEntityInventory extends TileEntity implements IInventory, NameableInventory, Iterable<ItemStack> { private static final String CUSTOM_NAME_KEY = "_sc$customName"; private static final String INV_KEY = "_sc$inventory"; private boolean hasName = false; private String name; /** * Backing ItemStack storage */ protected final ItemStack[] storage; /** * <p>This constructor calls {@link #getSizeInventory()} to determine the size of the inventory. It needs to be overridden and work properly when called from this constructor.</p> */ protected TileEntityInventory() { storage = new ItemStack[getSizeInventory()]; } /** * <p>Alternate constructor that doesn't need {@link #getSizeInventory()} to be overridden.</p> * * @param size the size of this inventory */ protected TileEntityInventory(int size) { storage = new ItemStack[size]; } /** * <p>Get the unlocalized name of this inventory.</p> * * @return the unlocalized name */ protected abstract String unlocalizedName(); @Override public ItemStack getStackInSlot(int slot) { return storage[slot]; } @Override public ItemStack decrStackSize(int slot, int count) { return Inventories.decreaseStackSize(this, slot, count); } @Override public ItemStack getStackInSlotOnClosing(int slot) { return Inventories.getAndRemove(this, slot); } @Override public void setInventorySlotContents(int slot, ItemStack item) { storage[slot] = item; onInventoryChanged(); } @Override public int getSizeInventory() { return storage.length; } @Override public String getInvName() { return hasCustomName() ? getCustomName() : unlocalizedName(); } @Override public boolean isInvNameLocalized() { return hasCustomName(); } @Override public int getInventoryStackLimit() { return 64; } @Override public boolean isUseableByPlayer(EntityPlayer player) { return worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) == this && player.getDistanceSq(xCoord, yCoord, zCoord) <= 64; } @Override public boolean isItemValidForSlot(int slot, ItemStack item) { return true; } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); Inventories.readInventory(storage, nbt, INV_KEY); if (nbt.hasKey(CUSTOM_NAME_KEY)) { setCustomName(nbt.getString(CUSTOM_NAME_KEY)); } } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); Inventories.writeInventory(storage, nbt, INV_KEY); if (hasCustomName()) { nbt.setString(CUSTOM_NAME_KEY, getCustomName()); } } @Override public void openChest() { } @Override public void closeChest() { } // NameableInventory @Override public boolean hasCustomName() { return hasName; } @Override public void setCustomName(String name) { hasName = true; this.name = name; } @Override public String getCustomName() { return name; } @Nonnull @Override public Iterator<ItemStack> iterator() { return Iterators.forArray(storage); } }