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    }