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.IInventory;
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
015import net.minecraftforge.common.ISidedInventory;
016import net.minecraftforge.common.ForgeDirection;
017
018public 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(var1))
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(par2ItemStack) ? PotionHelper.applyIngredient(par1, Item.itemsList[par2ItemStack.itemID].getPotionEffect(par2ItemStack)) : 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}