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