001package net.minecraft.tileentity; 002 003import java.util.Random; 004import net.minecraft.entity.player.EntityPlayer; 005import net.minecraft.inventory.IInventory; 006import net.minecraft.item.ItemStack; 007import net.minecraft.nbt.NBTTagCompound; 008import net.minecraft.nbt.NBTTagList; 009 010public class TileEntityDispenser extends TileEntity implements IInventory 011{ 012 private ItemStack[] dispenserContents = new ItemStack[9]; 013 014 /** 015 * random number generator for instance. Used in random item stack selection. 016 */ 017 private Random dispenserRandom = new Random(); 018 protected String field_94050_c; 019 020 /** 021 * Returns the number of slots in the inventory. 022 */ 023 public int getSizeInventory() 024 { 025 return 9; 026 } 027 028 /** 029 * Returns the stack in slot i 030 */ 031 public ItemStack getStackInSlot(int par1) 032 { 033 return this.dispenserContents[par1]; 034 } 035 036 /** 037 * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a 038 * new stack. 039 */ 040 public ItemStack decrStackSize(int par1, int par2) 041 { 042 if (this.dispenserContents[par1] != null) 043 { 044 ItemStack itemstack; 045 046 if (this.dispenserContents[par1].stackSize <= par2) 047 { 048 itemstack = this.dispenserContents[par1]; 049 this.dispenserContents[par1] = null; 050 this.onInventoryChanged(); 051 return itemstack; 052 } 053 else 054 { 055 itemstack = this.dispenserContents[par1].splitStack(par2); 056 057 if (this.dispenserContents[par1].stackSize == 0) 058 { 059 this.dispenserContents[par1] = null; 060 } 061 062 this.onInventoryChanged(); 063 return itemstack; 064 } 065 } 066 else 067 { 068 return null; 069 } 070 } 071 072 /** 073 * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem - 074 * like when you close a workbench GUI. 075 */ 076 public ItemStack getStackInSlotOnClosing(int par1) 077 { 078 if (this.dispenserContents[par1] != null) 079 { 080 ItemStack itemstack = this.dispenserContents[par1]; 081 this.dispenserContents[par1] = null; 082 return itemstack; 083 } 084 else 085 { 086 return null; 087 } 088 } 089 090 public int getRandomStackFromInventory() 091 { 092 int i = -1; 093 int j = 1; 094 095 for (int k = 0; k < this.dispenserContents.length; ++k) 096 { 097 if (this.dispenserContents[k] != null && this.dispenserRandom.nextInt(j++) == 0) 098 { 099 i = k; 100 } 101 } 102 103 return i; 104 } 105 106 /** 107 * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections). 108 */ 109 public void setInventorySlotContents(int par1, ItemStack par2ItemStack) 110 { 111 this.dispenserContents[par1] = par2ItemStack; 112 113 if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit()) 114 { 115 par2ItemStack.stackSize = this.getInventoryStackLimit(); 116 } 117 118 this.onInventoryChanged(); 119 } 120 121 /** 122 * Add item stack in first available inventory slot 123 */ 124 public int addItem(ItemStack par1ItemStack) 125 { 126 for (int i = 0; i < this.dispenserContents.length; ++i) 127 { 128 if (this.dispenserContents[i] == null || this.dispenserContents[i].itemID == 0) 129 { 130 this.setInventorySlotContents(i, par1ItemStack); 131 return i; 132 } 133 } 134 135 return -1; 136 } 137 138 /** 139 * Returns the name of the inventory. 140 */ 141 public String getInvName() 142 { 143 return this.isInvNameLocalized() ? this.field_94050_c : "container.dispenser"; 144 } 145 146 public void func_94049_a(String par1Str) 147 { 148 this.field_94050_c = par1Str; 149 } 150 151 /** 152 * If this returns false, the inventory name will be used as an unlocalized name, and translated into the player's 153 * language. Otherwise it will be used directly. 154 */ 155 public boolean isInvNameLocalized() 156 { 157 return this.field_94050_c != null; 158 } 159 160 /** 161 * Reads a tile entity from NBT. 162 */ 163 public void readFromNBT(NBTTagCompound par1NBTTagCompound) 164 { 165 super.readFromNBT(par1NBTTagCompound); 166 NBTTagList nbttaglist = par1NBTTagCompound.getTagList("Items"); 167 this.dispenserContents = new ItemStack[this.getSizeInventory()]; 168 169 for (int i = 0; i < nbttaglist.tagCount(); ++i) 170 { 171 NBTTagCompound nbttagcompound1 = (NBTTagCompound)nbttaglist.tagAt(i); 172 int j = nbttagcompound1.getByte("Slot") & 255; 173 174 if (j >= 0 && j < this.dispenserContents.length) 175 { 176 this.dispenserContents[j] = ItemStack.loadItemStackFromNBT(nbttagcompound1); 177 } 178 } 179 180 if (par1NBTTagCompound.hasKey("CustomName")) 181 { 182 this.field_94050_c = par1NBTTagCompound.getString("CustomName"); 183 } 184 } 185 186 /** 187 * Writes a tile entity to NBT. 188 */ 189 public void writeToNBT(NBTTagCompound par1NBTTagCompound) 190 { 191 super.writeToNBT(par1NBTTagCompound); 192 NBTTagList nbttaglist = new NBTTagList(); 193 194 for (int i = 0; i < this.dispenserContents.length; ++i) 195 { 196 if (this.dispenserContents[i] != null) 197 { 198 NBTTagCompound nbttagcompound1 = new NBTTagCompound(); 199 nbttagcompound1.setByte("Slot", (byte)i); 200 this.dispenserContents[i].writeToNBT(nbttagcompound1); 201 nbttaglist.appendTag(nbttagcompound1); 202 } 203 } 204 205 par1NBTTagCompound.setTag("Items", nbttaglist); 206 207 if (this.isInvNameLocalized()) 208 { 209 par1NBTTagCompound.setString("CustomName", this.field_94050_c); 210 } 211 } 212 213 /** 214 * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't 215 * this more of a set than a get?* 216 */ 217 public int getInventoryStackLimit() 218 { 219 return 64; 220 } 221 222 /** 223 * Do not make give this method the name canInteractWith because it clashes with Container 224 */ 225 public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) 226 { 227 return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false : par1EntityPlayer.getDistanceSq((double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D) <= 64.0D; 228 } 229 230 public void openChest() {} 231 232 public void closeChest() {} 233 234 /** 235 * Returns true if automation is allowed to insert the given stack (ignoring stack size) into the given slot. 236 */ 237 public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) 238 { 239 return true; 240 } 241}