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 }