    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}