package com.team.kalstuff.tileentity; import java.util.List; import com.team.kalstuff.container.ContainerChickenNest; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.passive.EntityChicken; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.init.Items; import net.minecraft.inventory.Container; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.ItemStackHelper; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntityLockableLoot; import net.minecraft.util.ITickable; import net.minecraft.util.NonNullList; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; public class TileEntityChickenNest extends TileEntityLockableLoot implements IInventory, ITickable { // Create and initialize the items variable that will store the items private NonNullList<ItemStack> inventory = NonNullList.<ItemStack>withSize(1, ItemStack.EMPTY); private EntityChicken chicken; private int cooldown; //Check for items @Override public void update() { if (!world.isRemote) { EntityItem item = CheckForItemEntities(this.world, this.pos.getX(), this.pos.getY(), this.pos.getZ()); if (item != null) { ItemStack itemstack = item.getEntityItem().copy(); item.setEntityItemStack(this.add(itemstack)); } if (this.cooldown > 0) this.cooldown --; if (this.chicken != null && this.chicken.isDead) this.chicken = null; if (this.chicken == null && this.cooldown <= 0) this.chicken = CheckForChickens(this.world, this.pos.getX(), this.pos.getY(), this.pos.getZ()); else if (this.chicken != null) this.chicken.setPosition(this.getPos().getX() + .5, this.getPos().getY(), this.getPos().getZ() + .5); } } //Find a "random" item over the block public static EntityItem CheckForItemEntities(World worldIn, double p_145897_1_, double p_145897_3_, double p_145897_5_) { List<?> list = worldIn.getEntitiesWithinAABB(EntityItem.class, new AxisAlignedBB(p_145897_1_, p_145897_3_, p_145897_5_, p_145897_1_ + 1.0D, p_145897_3_ + 0.5D, p_145897_5_ + 1.0D), null); return list.size() > 0 ? (EntityItem)list.get(0) : null; } //Find a "random" item over the block public static EntityChicken CheckForChickens(World worldIn, double p_145897_1_, double p_145897_3_, double p_145897_5_) { List<?> list = worldIn.getEntitiesWithinAABB(EntityChicken.class, new AxisAlignedBB(p_145897_1_, p_145897_3_, p_145897_5_, p_145897_1_ + 1.0D, p_145897_3_ + 1.0D, p_145897_5_ + 1.0D), null); return list.size() > 0 ? (EntityChicken)list.get(0) : null; } //Checks if there is any space whatsoever, include partial stacks @SuppressWarnings("unused") private boolean hasEmptySpace() { return (this.inventory.get(0) == null || this.inventory.get(0).getCount() != this.inventory.get(0).getMaxStackSize()); //TODO: update this } //Checks if there is any space that the specified item can fit in. Meaning only partial stacks if they're the same item. private boolean hasRoomForItem(ItemStack itemstack) { return (this.inventory.get(0) == null || (this.inventory.get(0).getCount() != this.inventory.get(0).getMaxStackSize() && itemstack.getItem() == this.inventory.get(0).getItem())); //TODO: update this } //Adds as many items from the item stack as it can to the inventory private ItemStack add(ItemStack itemstack) { int i; for (i = 0; i < itemstack.getCount() && this.hasRoomForItem(itemstack); i ++) {//TODO: update this if (this.inventory.get(0) == null) this.inventory.set(0, new ItemStack(itemstack.getItem(), 1)); else this.inventory.get(0).grow(1);//TODO: update this itemstack.shrink(1);//TODO: update this } return itemstack; } // Gets the number of slots in the inventory @Override public int getSizeInventory() { return this.inventory.size(); } // Gets the stack in the given slot @Override public ItemStack getStackInSlot(int slotIndex) { this.fillWithLoot((EntityPlayer)null); return (ItemStack)this.inventory.get(slotIndex); } /** * Removes up to a specified number of items from an inventory slot and returns them in a new stack. */ public ItemStack decrStackSize(int index, int count) { this.fillWithLoot((EntityPlayer)null); ItemStack itemstack = ItemStackHelper.getAndSplit(this.inventory, index, count); return itemstack; } /** * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections). */ public void setInventorySlotContents(int index, ItemStack stack) { this.fillWithLoot((EntityPlayer)null); this.inventory.set(index, stack); if (stack.getCount() > this.getInventoryStackLimit()) { stack.setCount(this.getInventoryStackLimit()); } } // This is the maximum number if items allowed in each slot // This only affects things such as hoppers trying to insert items you need to use the container to enforce this for players // inserting items via the gui @Override public int getInventoryStackLimit() { return 64; } // Return true if the given player is able to use this block. In this case it checks that // 1) the world tileentity hasn't been replaced in the meantime, and // 2) the player isn't too far away from the centre of the block @Override public boolean isUsableByPlayer(EntityPlayer player) { if (this.world.getTileEntity(this.pos) != this) return false; final double X_CENTRE_OFFSET = 0.5; final double Y_CENTRE_OFFSET = 0.5; final double Z_CENTRE_OFFSET = 0.5; final double MAXIMUM_DISTANCE_SQ = 8.0 * 8.0; return player.getDistanceSq(pos.getX() + X_CENTRE_OFFSET, pos.getY() + Y_CENTRE_OFFSET, pos.getZ() + Z_CENTRE_OFFSET) < MAXIMUM_DISTANCE_SQ; } // Return true if the given stack is allowed to go in the given slot. In this case, we can insert anything. // This only affects things such as hoppers trying to insert items you need to use the container to enforce this for players // inserting items via the gui @Override public boolean isItemValidForSlot(int slotIndex, ItemStack itemstack) { return itemstack == new ItemStack(Items.EGG); } // This is where you save any data that you don't want to lose when the tile entity unloads // In this case, it saves the itemstacks stored in the container @Override public NBTTagCompound writeToNBT(NBTTagCompound parentNBTTagCompound) { super.writeToNBT(parentNBTTagCompound); // The super call is required to save and load the tileEntity's location // to use an analogy with Java, this code generates an array of hashmaps // The itemStack in each slot is converted to an NBTTagCompound, which is effectively a hashmap of key->value pairs such // as slot=1, id=2353, count=1, etc // Each of these NBTTagCompound are then inserted into NBTTagList, which is similar to an array. NBTTagList dataForAllSlots = new NBTTagList(); for (int i = 0; i < this.inventory.size(); ++i) { if (this.inventory.get(i) != null) { NBTTagCompound dataForThisSlot = new NBTTagCompound(); dataForThisSlot.setByte("Slot", (byte) i); this.inventory.get(i).writeToNBT(dataForThisSlot); dataForAllSlots.appendTag(dataForThisSlot); } } // the array of hashmaps is then inserted into the parent hashmap for the container parentNBTTagCompound.setTag("Items", dataForAllSlots); return parentNBTTagCompound; } // This is where you load the data that you saved in writeToNBT @Override public void readFromNBT(NBTTagCompound parentNBTTagCompound) { super.readFromNBT(parentNBTTagCompound); this.inventory = NonNullList.<ItemStack>withSize(this.getSizeInventory(), ItemStack.EMPTY); if (!this.checkLootAndRead(parentNBTTagCompound)) { ItemStackHelper.loadAllItems(parentNBTTagCompound, this.inventory); } if (parentNBTTagCompound.hasKey("CustomName", 8)) { this.customName = parentNBTTagCompound.getString("CustomName"); } } // will add a key for this container to the lang file so we can name it in the GUI @Override public String getName() { return "container.chickenNest.name"; } @Override public boolean hasCustomName() { return false; } /*// standard code to look up what the human-readable name is @Override public IChatComponent getDisplayName() { return this.hasCustomName() ? new ChatComponentText(this.getName()) : new ChatComponentTranslation(this.getName()); }*/ public void dropChicken() { if (!world.isRemote) { this.resetCooldown(); if (this.chicken != null) this.chicken.setPositionAndUpdate(this.getPos().getX() + .5, this.getPos().getY() + .6, this.getPos().getZ() + .5); this.chicken = null; } } public void resetCooldown() { this.cooldown = 100; } // ----------------------------------------------------------------------------------------------------------- // The following methods are not needed for this example but are part of IInventory so they must be implemented @Override public void openInventory(EntityPlayer player) {} @Override public void closeInventory(EntityPlayer player) {} @Override public int getField(int id) { return 0; } @Override public void setField(int id, int value) {} @Override public int getFieldCount() { return 0; } @Override public ITextComponent getDisplayName() { return (ITextComponent)(this.hasCustomName() ? new TextComponentString(this.getName()) : new TextComponentTranslation(this.getName(), new Object[0])); } @Override public ItemStack removeStackFromSlot(int index) { return ItemStackHelper.getAndRemove(inventory, index); } @Override public Container createContainer(InventoryPlayer playerInventory, EntityPlayer playerIn) { this.fillWithLoot(playerIn); return new ContainerChickenNest(playerInventory, this); } @Override public String getGuiID() { return "kalstuff:chicken_nest"; } @Override public boolean isEmpty() { return false; } @Override protected NonNullList<ItemStack> getItems() { return this.inventory; } }