package net.minecraft.entity.item; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.DamageSource; import net.minecraft.world.World; public abstract class EntityMinecartContainer extends EntityMinecart implements IInventory { private ItemStack[] minecartContainerItems = new ItemStack[36]; /** * When set to true, the minecart will drop all items when setDead() is called. When false (such as when travelling * dimensions) it preserves its contents. */ private boolean dropContentsWhenDead = true; private static final String __OBFID = "CL_00001674"; public EntityMinecartContainer(World p_i1716_1_) { super(p_i1716_1_); } public EntityMinecartContainer(World p_i1717_1_, double p_i1717_2_, double p_i1717_4_, double p_i1717_6_) { super(p_i1717_1_, p_i1717_2_, p_i1717_4_, p_i1717_6_); } public void killMinecart(DamageSource p_94095_1_) { super.killMinecart(p_94095_1_); for (int i = 0; i < this.getSizeInventory(); ++i) { ItemStack itemstack = this.getStackInSlot(i); if (itemstack != null) { float f = this.rand.nextFloat() * 0.8F + 0.1F; float f1 = this.rand.nextFloat() * 0.8F + 0.1F; float f2 = this.rand.nextFloat() * 0.8F + 0.1F; while (itemstack.stackSize > 0) { int j = this.rand.nextInt(21) + 10; if (j > itemstack.stackSize) { j = itemstack.stackSize; } itemstack.stackSize -= j; EntityItem entityitem = new EntityItem(this.worldObj, this.posX + (double)f, this.posY + (double)f1, this.posZ + (double)f2, new ItemStack(itemstack.getItem(), j, itemstack.getMetadata())); float f3 = 0.05F; entityitem.motionX = (double)((float)this.rand.nextGaussian() * f3); entityitem.motionY = (double)((float)this.rand.nextGaussian() * f3 + 0.2F); entityitem.motionZ = (double)((float)this.rand.nextGaussian() * f3); this.worldObj.spawnEntityInWorld(entityitem); } } } } /** * Returns the stack in slot i */ public ItemStack getStackInSlot(int slotIn) { return this.minecartContainerItems[slotIn]; } /** * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a * new stack. */ public ItemStack decrStackSize(int index, int count) { if (this.minecartContainerItems[index] != null) { ItemStack itemstack; if (this.minecartContainerItems[index].stackSize <= count) { itemstack = this.minecartContainerItems[index]; this.minecartContainerItems[index] = null; return itemstack; } else { itemstack = this.minecartContainerItems[index].splitStack(count); if (this.minecartContainerItems[index].stackSize == 0) { this.minecartContainerItems[index] = null; } return itemstack; } } else { return null; } } /** * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem - * like when you close a workbench GUI. */ public ItemStack getStackInSlotOnClosing(int index) { if (this.minecartContainerItems[index] != null) { ItemStack itemstack = this.minecartContainerItems[index]; this.minecartContainerItems[index] = null; return itemstack; } else { return null; } } /** * 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.minecartContainerItems[index] = stack; if (stack != null && stack.stackSize > this.getInventoryStackLimit()) { stack.stackSize = this.getInventoryStackLimit(); } } /** * For tile entities, ensures the chunk containing the tile entity is saved to disk later - the game won't think it * hasn't changed and skip it. */ public void markDirty() {} /** * Do not make give this method the name canInteractWith because it clashes with Container */ public boolean isUseableByPlayer(EntityPlayer player) { return this.isDead ? false : player.getDistanceSqToEntity(this) <= 64.0D; } public void openChest() {} public void closeChest() {} /** * Returns true if automation is allowed to insert the given stack (ignoring stack size) into the given slot. */ public boolean isItemValidForSlot(int index, ItemStack stack) { return true; } /** * Returns the name of the inventory */ public String getInventoryName() { return this.isCustomInventoryName() ? this.func_95999_t() : "container.minecart"; } /** * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't * this more of a set than a get?* */ public int getInventoryStackLimit() { return 64; } /** * Teleports the entity to another dimension. Params: Dimension number to teleport to */ public void travelToDimension(int dimensionId) { this.dropContentsWhenDead = false; super.travelToDimension(dimensionId); } /** * Will get destroyed next tick. */ public void setDead() { if (this.dropContentsWhenDead) { for (int i = 0; i < this.getSizeInventory(); ++i) { ItemStack itemstack = this.getStackInSlot(i); if (itemstack != null) { float f = this.rand.nextFloat() * 0.8F + 0.1F; float f1 = this.rand.nextFloat() * 0.8F + 0.1F; float f2 = this.rand.nextFloat() * 0.8F + 0.1F; while (itemstack.stackSize > 0) { int j = this.rand.nextInt(21) + 10; if (j > itemstack.stackSize) { j = itemstack.stackSize; } itemstack.stackSize -= j; EntityItem entityitem = new EntityItem(this.worldObj, this.posX + (double)f, this.posY + (double)f1, this.posZ + (double)f2, new ItemStack(itemstack.getItem(), j, itemstack.getMetadata())); if (itemstack.hasTagCompound()) { entityitem.getEntityItem().setTagCompound((NBTTagCompound)itemstack.getTagCompound().copy()); } float f3 = 0.05F; entityitem.motionX = (double)((float)this.rand.nextGaussian() * f3); entityitem.motionY = (double)((float)this.rand.nextGaussian() * f3 + 0.2F); entityitem.motionZ = (double)((float)this.rand.nextGaussian() * f3); this.worldObj.spawnEntityInWorld(entityitem); } } } } super.setDead(); } /** * (abstract) Protected helper method to write subclass entity data to NBT. */ protected void writeEntityToNBT(NBTTagCompound tagCompound) { super.writeEntityToNBT(tagCompound); NBTTagList nbttaglist = new NBTTagList(); for (int i = 0; i < this.minecartContainerItems.length; ++i) { if (this.minecartContainerItems[i] != null) { NBTTagCompound nbttagcompound1 = new NBTTagCompound(); nbttagcompound1.setByte("Slot", (byte)i); this.minecartContainerItems[i].writeToNBT(nbttagcompound1); nbttaglist.appendTag(nbttagcompound1); } } tagCompound.setTag("Items", nbttaglist); } /** * (abstract) Protected helper method to read subclass entity data from NBT. */ protected void readEntityFromNBT(NBTTagCompound tagCompund) { super.readEntityFromNBT(tagCompund); NBTTagList nbttaglist = tagCompund.getTagList("Items", 10); this.minecartContainerItems = new ItemStack[this.getSizeInventory()]; for (int i = 0; i < nbttaglist.tagCount(); ++i) { NBTTagCompound nbttagcompound1 = nbttaglist.getCompoundTagAt(i); int j = nbttagcompound1.getByte("Slot") & 255; if (j >= 0 && j < this.minecartContainerItems.length) { this.minecartContainerItems[j] = ItemStack.loadItemStackFromNBT(nbttagcompound1); } } } /** * First layer of player interaction */ public boolean interactFirst(EntityPlayer player) { if(net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.minecart.MinecartInteractEvent(this, player))) return true; if (!this.worldObj.isRemote) { player.displayGUIChest(this); } return true; } protected void applyDrag() { int i = 15 - Container.calcRedstoneFromInventory(this); float f = 0.98F + (float)i * 0.001F; this.motionX *= (double)f; this.motionY *= 0.0D; this.motionZ *= (double)f; } }