001package net.minecraft.tileentity; 002 003import cpw.mods.fml.relauncher.Side; 004import cpw.mods.fml.relauncher.SideOnly; 005import java.util.List; 006import net.minecraft.entity.player.EntityPlayer; 007import net.minecraft.inventory.ISidedInventory; 008import net.minecraft.item.Item; 009import net.minecraft.item.ItemPotion; 010import net.minecraft.item.ItemStack; 011import net.minecraft.nbt.NBTTagCompound; 012import net.minecraft.nbt.NBTTagList; 013import net.minecraft.potion.PotionHelper; 014 015public class TileEntityBrewingStand extends TileEntity implements ISidedInventory 016{ 017 /** The itemstacks currently placed in the slots of the brewing stand */ 018 private ItemStack[] brewingItemStacks = new ItemStack[4]; 019 private int brewTime; 020 021 /** 022 * an integer with each bit specifying whether that slot of the stand contains a potion 023 */ 024 private int filledSlots; 025 private int ingredientID; 026 private String field_94132_e; 027 028 /** 029 * Returns the name of the inventory. 030 */ 031 public String getInvName() 032 { 033 return this.func_94042_c() ? this.field_94132_e : "container.brewing"; 034 } 035 036 public boolean func_94042_c() 037 { 038 return this.field_94132_e != null && this.field_94132_e.length() > 0; 039 } 040 041 public void func_94131_a(String par1Str) 042 { 043 this.field_94132_e = par1Str; 044 } 045 046 /** 047 * Returns the number of slots in the inventory. 048 */ 049 public int getSizeInventory() 050 { 051 return this.brewingItemStacks.length; 052 } 053 054 /** 055 * Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count 056 * ticks and creates a new spawn inside its implementation. 057 */ 058 public void updateEntity() 059 { 060 if (this.brewTime > 0) 061 { 062 --this.brewTime; 063 064 if (this.brewTime == 0) 065 { 066 this.brewPotions(); 067 this.onInventoryChanged(); 068 } 069 else if (!this.canBrew()) 070 { 071 this.brewTime = 0; 072 this.onInventoryChanged(); 073 } 074 else if (this.ingredientID != this.brewingItemStacks[3].itemID) 075 { 076 this.brewTime = 0; 077 this.onInventoryChanged(); 078 } 079 } 080 else if (this.canBrew()) 081 { 082 this.brewTime = 400; 083 this.ingredientID = this.brewingItemStacks[3].itemID; 084 } 085 086 int i = this.getFilledSlots(); 087 088 if (i != this.filledSlots) 089 { 090 this.filledSlots = i; 091 this.worldObj.setBlockMetadataWithNotify(this.xCoord, this.yCoord, this.zCoord, i, 2); 092 } 093 094 super.updateEntity(); 095 } 096 097 public int getBrewTime() 098 { 099 return this.brewTime; 100 } 101 102 private boolean canBrew() 103 { 104 if (this.brewingItemStacks[3] != null && this.brewingItemStacks[3].stackSize > 0) 105 { 106 ItemStack itemstack = this.brewingItemStacks[3]; 107 108 if (!Item.itemsList[itemstack.itemID].isPotionIngredient()) 109 { 110 return false; 111 } 112 else 113 { 114 boolean flag = false; 115 116 for (int i = 0; i < 3; ++i) 117 { 118 if (this.brewingItemStacks[i] != null && this.brewingItemStacks[i].itemID == Item.potion.itemID) 119 { 120 int j = this.brewingItemStacks[i].getItemDamage(); 121 int k = this.getPotionResult(j, itemstack); 122 123 if (!ItemPotion.isSplash(j) && ItemPotion.isSplash(k)) 124 { 125 flag = true; 126 break; 127 } 128 129 List list = Item.potion.getEffects(j); 130 List list1 = Item.potion.getEffects(k); 131 132 if ((j <= 0 || list != list1) && (list == null || !list.equals(list1) && list1 != null) && j != k) 133 { 134 flag = true; 135 break; 136 } 137 } 138 } 139 140 return flag; 141 } 142 } 143 else 144 { 145 return false; 146 } 147 } 148 149 private void brewPotions() 150 { 151 if (this.canBrew()) 152 { 153 ItemStack itemstack = this.brewingItemStacks[3]; 154 155 for (int i = 0; i < 3; ++i) 156 { 157 if (this.brewingItemStacks[i] != null && this.brewingItemStacks[i].itemID == Item.potion.itemID) 158 { 159 int j = this.brewingItemStacks[i].getItemDamage(); 160 int k = this.getPotionResult(j, itemstack); 161 List list = Item.potion.getEffects(j); 162 List list1 = Item.potion.getEffects(k); 163 164 if ((j <= 0 || list != list1) && (list == null || !list.equals(list1) && list1 != null)) 165 { 166 if (j != k) 167 { 168 this.brewingItemStacks[i].setItemDamage(k); 169 } 170 } 171 else if (!ItemPotion.isSplash(j) && ItemPotion.isSplash(k)) 172 { 173 this.brewingItemStacks[i].setItemDamage(k); 174 } 175 } 176 } 177 178 if (Item.itemsList[itemstack.itemID].hasContainerItem()) 179 { 180 this.brewingItemStacks[3] = Item.itemsList[itemstack.itemID].getContainerItemStack(brewingItemStacks[3]); 181 } 182 else 183 { 184 --this.brewingItemStacks[3].stackSize; 185 186 if (this.brewingItemStacks[3].stackSize <= 0) 187 { 188 this.brewingItemStacks[3] = null; 189 } 190 } 191 } 192 } 193 194 /** 195 * The result of brewing a potion of the specified damage value with an ingredient itemstack. 196 */ 197 private int getPotionResult(int par1, ItemStack par2ItemStack) 198 { 199 return par2ItemStack == null ? par1 : (Item.itemsList[par2ItemStack.itemID].isPotionIngredient() ? PotionHelper.applyIngredient(par1, Item.itemsList[par2ItemStack.itemID].getPotionEffect()) : par1); 200 } 201 202 /** 203 * Reads a tile entity from NBT. 204 */ 205 public void readFromNBT(NBTTagCompound par1NBTTagCompound) 206 { 207 super.readFromNBT(par1NBTTagCompound); 208 NBTTagList nbttaglist = par1NBTTagCompound.getTagList("Items"); 209 this.brewingItemStacks = new ItemStack[this.getSizeInventory()]; 210 211 for (int i = 0; i < nbttaglist.tagCount(); ++i) 212 { 213 NBTTagCompound nbttagcompound1 = (NBTTagCompound)nbttaglist.tagAt(i); 214 byte b0 = nbttagcompound1.getByte("Slot"); 215 216 if (b0 >= 0 && b0 < this.brewingItemStacks.length) 217 { 218 this.brewingItemStacks[b0] = ItemStack.loadItemStackFromNBT(nbttagcompound1); 219 } 220 } 221 222 this.brewTime = par1NBTTagCompound.getShort("BrewTime"); 223 224 if (par1NBTTagCompound.hasKey("CustomName")) 225 { 226 this.field_94132_e = par1NBTTagCompound.getString("CustomName"); 227 } 228 } 229 230 /** 231 * Writes a tile entity to NBT. 232 */ 233 public void writeToNBT(NBTTagCompound par1NBTTagCompound) 234 { 235 super.writeToNBT(par1NBTTagCompound); 236 par1NBTTagCompound.setShort("BrewTime", (short)this.brewTime); 237 NBTTagList nbttaglist = new NBTTagList(); 238 239 for (int i = 0; i < this.brewingItemStacks.length; ++i) 240 { 241 if (this.brewingItemStacks[i] != null) 242 { 243 NBTTagCompound nbttagcompound1 = new NBTTagCompound(); 244 nbttagcompound1.setByte("Slot", (byte)i); 245 this.brewingItemStacks[i].writeToNBT(nbttagcompound1); 246 nbttaglist.appendTag(nbttagcompound1); 247 } 248 } 249 250 par1NBTTagCompound.setTag("Items", nbttaglist); 251 252 if (this.func_94042_c()) 253 { 254 par1NBTTagCompound.setString("CustomName", this.field_94132_e); 255 } 256 } 257 258 /** 259 * Returns the stack in slot i 260 */ 261 public ItemStack getStackInSlot(int par1) 262 { 263 return par1 >= 0 && par1 < this.brewingItemStacks.length ? this.brewingItemStacks[par1] : null; 264 } 265 266 /** 267 * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a 268 * new stack. 269 */ 270 public ItemStack decrStackSize(int par1, int par2) 271 { 272 if (par1 >= 0 && par1 < this.brewingItemStacks.length) 273 { 274 ItemStack itemstack = this.brewingItemStacks[par1]; 275 this.brewingItemStacks[par1] = null; 276 return itemstack; 277 } 278 else 279 { 280 return null; 281 } 282 } 283 284 /** 285 * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem - 286 * like when you close a workbench GUI. 287 */ 288 public ItemStack getStackInSlotOnClosing(int par1) 289 { 290 if (par1 >= 0 && par1 < this.brewingItemStacks.length) 291 { 292 ItemStack itemstack = this.brewingItemStacks[par1]; 293 this.brewingItemStacks[par1] = null; 294 return itemstack; 295 } 296 else 297 { 298 return null; 299 } 300 } 301 302 /** 303 * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections). 304 */ 305 public void setInventorySlotContents(int par1, ItemStack par2ItemStack) 306 { 307 if (par1 >= 0 && par1 < this.brewingItemStacks.length) 308 { 309 this.brewingItemStacks[par1] = par2ItemStack; 310 } 311 } 312 313 /** 314 * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't 315 * this more of a set than a get?* 316 */ 317 public int getInventoryStackLimit() 318 { 319 return 64; 320 } 321 322 /** 323 * Do not make give this method the name canInteractWith because it clashes with Container 324 */ 325 public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) 326 { 327 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; 328 } 329 330 public void openChest() {} 331 332 public void closeChest() {} 333 334 public boolean func_94041_b(int par1, ItemStack par2ItemStack) 335 { 336 return par1 == 3 ? Item.itemsList[par2ItemStack.itemID].isPotionIngredient() : par2ItemStack.itemID == Item.potion.itemID || par2ItemStack.itemID == Item.glassBottle.itemID; 337 } 338 339 @SideOnly(Side.CLIENT) 340 public void setBrewTime(int par1) 341 { 342 this.brewTime = par1; 343 } 344 345 /** 346 * returns an integer with each bit specifying wether that slot of the stand contains a potion 347 */ 348 public int getFilledSlots() 349 { 350 int i = 0; 351 352 for (int j = 0; j < 3; ++j) 353 { 354 if (this.brewingItemStacks[j] != null) 355 { 356 i |= 1 << j; 357 } 358 } 359 360 return i; 361 } 362 363 public int func_94127_c(int par1) 364 { 365 return par1 == 1 ? 3 : 0; 366 } 367 368 public int func_94128_d(int par1) 369 { 370 return par1 == 1 ? 1 : 3; 371 } 372}