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}