    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}