001package net.minecraft.entity.item; 002 003import net.minecraft.entity.player.EntityPlayer; 004import net.minecraft.inventory.Container; 005import net.minecraft.inventory.IInventory; 006import net.minecraft.item.ItemStack; 007import net.minecraft.nbt.NBTTagCompound; 008import net.minecraft.nbt.NBTTagList; 009import net.minecraft.util.DamageSource; 010import net.minecraft.world.World; 011import net.minecraftforge.common.MinecraftForge; 012import net.minecraftforge.event.entity.minecart.MinecartInteractEvent; 013 014public abstract class EntityMinecartContainer extends EntityMinecart implements IInventory 015{ 016 private ItemStack[] minecartContainerItems = new ItemStack[36]; 017 private boolean field_94112_b = true; 018 019 public EntityMinecartContainer(World par1World) 020 { 021 super(par1World); 022 } 023 024 public EntityMinecartContainer(World par1World, double par2, double par4, double par6) 025 { 026 super(par1World, par2, par4, par6); 027 } 028 029 public void func_94095_a(DamageSource par1DamageSource) 030 { 031 super.func_94095_a(par1DamageSource); 032 033 for (int i = 0; i < this.getSizeInventory(); ++i) 034 { 035 ItemStack itemstack = this.getStackInSlot(i); 036 037 if (itemstack != null) 038 { 039 float f = this.rand.nextFloat() * 0.8F + 0.1F; 040 float f1 = this.rand.nextFloat() * 0.8F + 0.1F; 041 float f2 = this.rand.nextFloat() * 0.8F + 0.1F; 042 043 while (itemstack.stackSize > 0) 044 { 045 int j = this.rand.nextInt(21) + 10; 046 047 if (j > itemstack.stackSize) 048 { 049 j = itemstack.stackSize; 050 } 051 052 itemstack.stackSize -= j; 053 EntityItem entityitem = new EntityItem(this.worldObj, this.posX + (double)f, this.posY + (double)f1, this.posZ + (double)f2, new ItemStack(itemstack.itemID, j, itemstack.getItemDamage())); 054 float f3 = 0.05F; 055 entityitem.motionX = (double)((float)this.rand.nextGaussian() * f3); 056 entityitem.motionY = (double)((float)this.rand.nextGaussian() * f3 + 0.2F); 057 entityitem.motionZ = (double)((float)this.rand.nextGaussian() * f3); 058 this.worldObj.spawnEntityInWorld(entityitem); 059 } 060 } 061 } 062 } 063 064 /** 065 * Returns the stack in slot i 066 */ 067 public ItemStack getStackInSlot(int par1) 068 { 069 return this.minecartContainerItems[par1]; 070 } 071 072 /** 073 * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a 074 * new stack. 075 */ 076 public ItemStack decrStackSize(int par1, int par2) 077 { 078 if (this.minecartContainerItems[par1] != null) 079 { 080 ItemStack itemstack; 081 082 if (this.minecartContainerItems[par1].stackSize <= par2) 083 { 084 itemstack = this.minecartContainerItems[par1]; 085 this.minecartContainerItems[par1] = null; 086 return itemstack; 087 } 088 else 089 { 090 itemstack = this.minecartContainerItems[par1].splitStack(par2); 091 092 if (this.minecartContainerItems[par1].stackSize == 0) 093 { 094 this.minecartContainerItems[par1] = null; 095 } 096 097 return itemstack; 098 } 099 } 100 else 101 { 102 return null; 103 } 104 } 105 106 /** 107 * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem - 108 * like when you close a workbench GUI. 109 */ 110 public ItemStack getStackInSlotOnClosing(int par1) 111 { 112 if (this.minecartContainerItems[par1] != null) 113 { 114 ItemStack itemstack = this.minecartContainerItems[par1]; 115 this.minecartContainerItems[par1] = null; 116 return itemstack; 117 } 118 else 119 { 120 return null; 121 } 122 } 123 124 /** 125 * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections). 126 */ 127 public void setInventorySlotContents(int par1, ItemStack par2ItemStack) 128 { 129 this.minecartContainerItems[par1] = par2ItemStack; 130 131 if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit()) 132 { 133 par2ItemStack.stackSize = this.getInventoryStackLimit(); 134 } 135 } 136 137 /** 138 * Called when an the contents of an Inventory change, usually 139 */ 140 public void onInventoryChanged() {} 141 142 /** 143 * Do not make give this method the name canInteractWith because it clashes with Container 144 */ 145 public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) 146 { 147 return this.isDead ? false : par1EntityPlayer.getDistanceSqToEntity(this) <= 64.0D; 148 } 149 150 public void openChest() {} 151 152 public void closeChest() {} 153 154 /** 155 * Returns true if automation is allowed to insert the given stack (ignoring stack size) into the given slot. 156 */ 157 public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) 158 { 159 return true; 160 } 161 162 /** 163 * Returns the name of the inventory. 164 */ 165 public String getInvName() 166 { 167 return this.isInvNameLocalized() ? this.func_95999_t() : "container.minecart"; 168 } 169 170 /** 171 * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't 172 * this more of a set than a get?* 173 */ 174 public int getInventoryStackLimit() 175 { 176 return 64; 177 } 178 179 /** 180 * Teleports the entity to another dimension. Params: Dimension number to teleport to 181 */ 182 public void travelToDimension(int par1) 183 { 184 this.field_94112_b = false; 185 super.travelToDimension(par1); 186 } 187 188 /** 189 * Will get destroyed next tick. 190 */ 191 public void setDead() 192 { 193 if (this.field_94112_b) 194 { 195 for (int i = 0; i < this.getSizeInventory(); ++i) 196 { 197 ItemStack itemstack = this.getStackInSlot(i); 198 199 if (itemstack != null) 200 { 201 float f = this.rand.nextFloat() * 0.8F + 0.1F; 202 float f1 = this.rand.nextFloat() * 0.8F + 0.1F; 203 float f2 = this.rand.nextFloat() * 0.8F + 0.1F; 204 205 while (itemstack.stackSize > 0) 206 { 207 int j = this.rand.nextInt(21) + 10; 208 209 if (j > itemstack.stackSize) 210 { 211 j = itemstack.stackSize; 212 } 213 214 itemstack.stackSize -= j; 215 EntityItem entityitem = new EntityItem(this.worldObj, this.posX + (double)f, this.posY + (double)f1, this.posZ + (double)f2, new ItemStack(itemstack.itemID, j, itemstack.getItemDamage())); 216 217 if (itemstack.hasTagCompound()) 218 { 219 entityitem.getEntityItem().setTagCompound((NBTTagCompound)itemstack.getTagCompound().copy()); 220 } 221 222 float f3 = 0.05F; 223 entityitem.motionX = (double)((float)this.rand.nextGaussian() * f3); 224 entityitem.motionY = (double)((float)this.rand.nextGaussian() * f3 + 0.2F); 225 entityitem.motionZ = (double)((float)this.rand.nextGaussian() * f3); 226 this.worldObj.spawnEntityInWorld(entityitem); 227 } 228 } 229 } 230 } 231 232 super.setDead(); 233 } 234 235 /** 236 * (abstract) Protected helper method to write subclass entity data to NBT. 237 */ 238 protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) 239 { 240 super.writeEntityToNBT(par1NBTTagCompound); 241 NBTTagList nbttaglist = new NBTTagList(); 242 243 for (int i = 0; i < this.minecartContainerItems.length; ++i) 244 { 245 if (this.minecartContainerItems[i] != null) 246 { 247 NBTTagCompound nbttagcompound1 = new NBTTagCompound(); 248 nbttagcompound1.setByte("Slot", (byte)i); 249 this.minecartContainerItems[i].writeToNBT(nbttagcompound1); 250 nbttaglist.appendTag(nbttagcompound1); 251 } 252 } 253 254 par1NBTTagCompound.setTag("Items", nbttaglist); 255 } 256 257 /** 258 * (abstract) Protected helper method to read subclass entity data from NBT. 259 */ 260 protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) 261 { 262 super.readEntityFromNBT(par1NBTTagCompound); 263 NBTTagList nbttaglist = par1NBTTagCompound.getTagList("Items"); 264 this.minecartContainerItems = new ItemStack[this.getSizeInventory()]; 265 266 for (int i = 0; i < nbttaglist.tagCount(); ++i) 267 { 268 NBTTagCompound nbttagcompound1 = (NBTTagCompound)nbttaglist.tagAt(i); 269 int j = nbttagcompound1.getByte("Slot") & 255; 270 271 if (j >= 0 && j < this.minecartContainerItems.length) 272 { 273 this.minecartContainerItems[j] = ItemStack.loadItemStackFromNBT(nbttagcompound1); 274 } 275 } 276 } 277 278 /** 279 * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig. 280 */ 281 public boolean interact(EntityPlayer par1EntityPlayer) 282 { 283 if(MinecraftForge.EVENT_BUS.post(new MinecartInteractEvent(this, par1EntityPlayer))) 284 { 285 return true; 286 } 287 if (!this.worldObj.isRemote) 288 { 289 par1EntityPlayer.displayGUIChest(this); 290 } 291 292 return true; 293 } 294 295 protected void func_94101_h() 296 { 297 int i = 15 - Container.func_94526_b(this); 298 float f = 0.98F + (float)i * 0.001F; 299 this.motionX *= (double)f; 300 this.motionY *= 0.0D; 301 this.motionZ *= (double)f; 302 } 303}