    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;
    014import net.minecraftforge.common.MinecraftForge;
    015import net.minecraftforge.event.brewing.PotionBrewedEvent;
    016
    017public class TileEntityBrewingStand extends TileEntity implements ISidedInventory
    018{
    019    private static final int[] field_102017_a = new int[] {3};
    020    private static final int[] field_102016_b = new int[] {0, 1, 2};
    021
    022    /** The itemstacks currently placed in the slots of the brewing stand */
    023    private ItemStack[] brewingItemStacks = new ItemStack[4];
    024    private int brewTime;
    025
    026    /**
    027     * an integer with each bit specifying whether that slot of the stand contains a potion
    028     */
    029    private int filledSlots;
    030    private int ingredientID;
    031    private String field_94132_e;
    032
    033    /**
    034     * Returns the name of the inventory.
    035     */
    036    public String getInvName()
    037    {
    038        return this.isInvNameLocalized() ? this.field_94132_e : "container.brewing";
    039    }
    040
    041    /**
    042     * If this returns false, the inventory name will be used as an unlocalized name, and translated into the player's
    043     * language. Otherwise it will be used directly.
    044     */
    045    public boolean isInvNameLocalized()
    046    {
    047        return this.field_94132_e != null && this.field_94132_e.length() > 0;
    048    }
    049
    050    public void func_94131_a(String par1Str)
    051    {
    052        this.field_94132_e = par1Str;
    053    }
    054
    055    /**
    056     * Returns the number of slots in the inventory.
    057     */
    058    public int getSizeInventory()
    059    {
    060        return this.brewingItemStacks.length;
    061    }
    062
    063    /**
    064     * Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count
    065     * ticks and creates a new spawn inside its implementation.
    066     */
    067    public void updateEntity()
    068    {
    069        if (this.brewTime > 0)
    070        {
    071            --this.brewTime;
    072
    073            if (this.brewTime == 0)
    074            {
    075                this.brewPotions();
    076                this.onInventoryChanged();
    077            }
    078            else if (!this.canBrew())
    079            {
    080                this.brewTime = 0;
    081                this.onInventoryChanged();
    082            }
    083            else if (this.ingredientID != this.brewingItemStacks[3].itemID)
    084            {
    085                this.brewTime = 0;
    086                this.onInventoryChanged();
    087            }
    088        }
    089        else if (this.canBrew())
    090        {
    091            this.brewTime = 400;
    092            this.ingredientID = this.brewingItemStacks[3].itemID;
    093        }
    094
    095        int i = this.getFilledSlots();
    096
    097        if (i != this.filledSlots)
    098        {
    099            this.filledSlots = i;
    100            this.worldObj.setBlockMetadataWithNotify(this.xCoord, this.yCoord, this.zCoord, i, 2);
    101        }
    102
    103        super.updateEntity();
    104    }
    105
    106    public int getBrewTime()
    107    {
    108        return this.brewTime;
    109    }
    110
    111    private boolean canBrew()
    112    {
    113        if (this.brewingItemStacks[3] != null && this.brewingItemStacks[3].stackSize > 0)
    114        {
    115            ItemStack itemstack = this.brewingItemStacks[3];
    116
    117            if (!Item.itemsList[itemstack.itemID].isPotionIngredient())
    118            {
    119                return false;
    120            }
    121            else
    122            {
    123                boolean flag = false;
    124
    125                for (int i = 0; i < 3; ++i)
    126                {
    127                    if (this.brewingItemStacks[i] != null && this.brewingItemStacks[i].getItem() instanceof ItemPotion)
    128                    {
    129                        int j = this.brewingItemStacks[i].getItemDamage();
    130                        int k = this.getPotionResult(j, itemstack);
    131
    132                        if (!ItemPotion.isSplash(j) && ItemPotion.isSplash(k))
    133                        {
    134                            flag = true;
    135                            break;
    136                        }
    137
    138                        List list = Item.potion.getEffects(j);
    139                        List list1 = Item.potion.getEffects(k);
    140
    141                        if ((j <= 0 || list != list1) && (list == null || !list.equals(list1) && list1 != null) && j != k)
    142                        {
    143                            flag = true;
    144                            break;
    145                        }
    146                    }
    147                }
    148
    149                return flag;
    150            }
    151        }
    152        else
    153        {
    154            return false;
    155        }
    156    }
    157
    158    private void brewPotions()
    159    {
    160        if (this.canBrew())
    161        {
    162            ItemStack itemstack = this.brewingItemStacks[3];
    163
    164            for (int i = 0; i < 3; ++i)
    165            {
    166                if (this.brewingItemStacks[i] != null && this.brewingItemStacks[i].getItem() instanceof ItemPotion)
    167                {
    168                    int j = this.brewingItemStacks[i].getItemDamage();
    169                    int k = this.getPotionResult(j, itemstack);
    170                    List list = Item.potion.getEffects(j);
    171                    List list1 = Item.potion.getEffects(k);
    172
    173                    if ((j <= 0 || list != list1) && (list == null || !list.equals(list1) && list1 != null))
    174                    {
    175                        if (j != k)
    176                        {
    177                            this.brewingItemStacks[i].setItemDamage(k);
    178                        }
    179                    }
    180                    else if (!ItemPotion.isSplash(j) && ItemPotion.isSplash(k))
    181                    {
    182                        this.brewingItemStacks[i].setItemDamage(k);
    183                    }
    184                }
    185            }
    186
    187            if (Item.itemsList[itemstack.itemID].hasContainerItem())
    188            {
    189                this.brewingItemStacks[3] = Item.itemsList[itemstack.itemID].getContainerItemStack(brewingItemStacks[3]);
    190            }
    191            else
    192            {
    193                --this.brewingItemStacks[3].stackSize;
    194
    195                if (this.brewingItemStacks[3].stackSize <= 0)
    196                {
    197                    this.brewingItemStacks[3] = null;
    198                }
    199            }
    200
    201            MinecraftForge.EVENT_BUS.post(new PotionBrewedEvent(brewingItemStacks));
    202        }
    203    }
    204
    205    /**
    206     * The result of brewing a potion of the specified damage value with an ingredient itemstack.
    207     */
    208    private int getPotionResult(int par1, ItemStack par2ItemStack)
    209    {
    210        return par2ItemStack == null ? par1 : (Item.itemsList[par2ItemStack.itemID].isPotionIngredient() ? PotionHelper.applyIngredient(par1, Item.itemsList[par2ItemStack.itemID].getPotionEffect()) : par1);
    211    }
    212
    213    /**
    214     * Reads a tile entity from NBT.
    215     */
    216    public void readFromNBT(NBTTagCompound par1NBTTagCompound)
    217    {
    218        super.readFromNBT(par1NBTTagCompound);
    219        NBTTagList nbttaglist = par1NBTTagCompound.getTagList("Items");
    220        this.brewingItemStacks = new ItemStack[this.getSizeInventory()];
    221
    222        for (int i = 0; i < nbttaglist.tagCount(); ++i)
    223        {
    224            NBTTagCompound nbttagcompound1 = (NBTTagCompound)nbttaglist.tagAt(i);
    225            byte b0 = nbttagcompound1.getByte("Slot");
    226
    227            if (b0 >= 0 && b0 < this.brewingItemStacks.length)
    228            {
    229                this.brewingItemStacks[b0] = ItemStack.loadItemStackFromNBT(nbttagcompound1);
    230            }
    231        }
    232
    233        this.brewTime = par1NBTTagCompound.getShort("BrewTime");
    234
    235        if (par1NBTTagCompound.hasKey("CustomName"))
    236        {
    237            this.field_94132_e = par1NBTTagCompound.getString("CustomName");
    238        }
    239    }
    240
    241    /**
    242     * Writes a tile entity to NBT.
    243     */
    244    public void writeToNBT(NBTTagCompound par1NBTTagCompound)
    245    {
    246        super.writeToNBT(par1NBTTagCompound);
    247        par1NBTTagCompound.setShort("BrewTime", (short)this.brewTime);
    248        NBTTagList nbttaglist = new NBTTagList();
    249
    250        for (int i = 0; i < this.brewingItemStacks.length; ++i)
    251        {
    252            if (this.brewingItemStacks[i] != null)
    253            {
    254                NBTTagCompound nbttagcompound1 = new NBTTagCompound();
    255                nbttagcompound1.setByte("Slot", (byte)i);
    256                this.brewingItemStacks[i].writeToNBT(nbttagcompound1);
    257                nbttaglist.appendTag(nbttagcompound1);
    258            }
    259        }
    260
    261        par1NBTTagCompound.setTag("Items", nbttaglist);
    262
    263        if (this.isInvNameLocalized())
    264        {
    265            par1NBTTagCompound.setString("CustomName", this.field_94132_e);
    266        }
    267    }
    268
    269    /**
    270     * Returns the stack in slot i
    271     */
    272    public ItemStack getStackInSlot(int par1)
    273    {
    274        return par1 >= 0 && par1 < this.brewingItemStacks.length ? this.brewingItemStacks[par1] : null;
    275    }
    276
    277    /**
    278     * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a
    279     * new stack.
    280     */
    281    public ItemStack decrStackSize(int par1, int par2)
    282    {
    283        if (par1 >= 0 && par1 < this.brewingItemStacks.length)
    284        {
    285            ItemStack itemstack = this.brewingItemStacks[par1];
    286            this.brewingItemStacks[par1] = null;
    287            return itemstack;
    288        }
    289        else
    290        {
    291            return null;
    292        }
    293    }
    294
    295    /**
    296     * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem -
    297     * like when you close a workbench GUI.
    298     */
    299    public ItemStack getStackInSlotOnClosing(int par1)
    300    {
    301        if (par1 >= 0 && par1 < this.brewingItemStacks.length)
    302        {
    303            ItemStack itemstack = this.brewingItemStacks[par1];
    304            this.brewingItemStacks[par1] = null;
    305            return itemstack;
    306        }
    307        else
    308        {
    309            return null;
    310        }
    311    }
    312
    313    /**
    314     * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections).
    315     */
    316    public void setInventorySlotContents(int par1, ItemStack par2ItemStack)
    317    {
    318        if (par1 >= 0 && par1 < this.brewingItemStacks.length)
    319        {
    320            this.brewingItemStacks[par1] = par2ItemStack;
    321        }
    322    }
    323
    324    /**
    325     * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't
    326     * this more of a set than a get?*
    327     */
    328    public int getInventoryStackLimit()
    329    {
    330        return 64;
    331    }
    332
    333    /**
    334     * Do not make give this method the name canInteractWith because it clashes with Container
    335     */
    336    public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
    337    {
    338        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;
    339    }
    340
    341    public void openChest() {}
    342
    343    public void closeChest() {}
    344
    345    /**
    346     * Returns true if automation is allowed to insert the given stack (ignoring stack size) into the given slot.
    347     */
    348    public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack)
    349    {
    350        return par1 == 3 ? Item.itemsList[par2ItemStack.itemID].isPotionIngredient() : par2ItemStack.getItem() instanceof ItemPotion || par2ItemStack.itemID == Item.glassBottle.itemID;
    351    }
    352
    353    @SideOnly(Side.CLIENT)
    354    public void setBrewTime(int par1)
    355    {
    356        this.brewTime = par1;
    357    }
    358
    359    /**
    360     * returns an integer with each bit specifying wether that slot of the stand contains a potion
    361     */
    362    public int getFilledSlots()
    363    {
    364        int i = 0;
    365
    366        for (int j = 0; j < 3; ++j)
    367        {
    368            if (this.brewingItemStacks[j] != null)
    369            {
    370                i |= 1 << j;
    371            }
    372        }
    373
    374        return i;
    375    }
    376
    377    /**
    378     * Get the size of the side inventory.
    379     */
    380    public int[] getSizeInventorySide(int par1)
    381    {
    382        return par1 == 1 ? field_102017_a : field_102016_b;
    383    }
    384
    385    public boolean func_102007_a(int par1, ItemStack par2ItemStack, int par3)
    386    {
    387        return this.isStackValidForSlot(par1, par2ItemStack);
    388    }
    389
    390    public boolean func_102008_b(int par1, ItemStack par2ItemStack, int par3)
    391    {
    392        return true;
    393    }
    394}