001package net.minecraft.tileentity;
002
003import java.util.Random;
004import net.minecraft.entity.player.EntityPlayer;
005import net.minecraft.inventory.IInventory;
006import net.minecraft.item.ItemStack;
007import net.minecraft.nbt.NBTTagCompound;
008import net.minecraft.nbt.NBTTagList;
009
010public class TileEntityDispenser extends TileEntity implements IInventory
011{
012    private ItemStack[] dispenserContents = new ItemStack[9];
013
014    /**
015     * random number generator for instance. Used in random item stack selection.
016     */
017    private Random dispenserRandom = new Random();
018    protected String field_94050_c;
019
020    /**
021     * Returns the number of slots in the inventory.
022     */
023    public int getSizeInventory()
024    {
025        return 9;
026    }
027
028    /**
029     * Returns the stack in slot i
030     */
031    public ItemStack getStackInSlot(int par1)
032    {
033        return this.dispenserContents[par1];
034    }
035
036    /**
037     * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a
038     * new stack.
039     */
040    public ItemStack decrStackSize(int par1, int par2)
041    {
042        if (this.dispenserContents[par1] != null)
043        {
044            ItemStack itemstack;
045
046            if (this.dispenserContents[par1].stackSize <= par2)
047            {
048                itemstack = this.dispenserContents[par1];
049                this.dispenserContents[par1] = null;
050                this.onInventoryChanged();
051                return itemstack;
052            }
053            else
054            {
055                itemstack = this.dispenserContents[par1].splitStack(par2);
056
057                if (this.dispenserContents[par1].stackSize == 0)
058                {
059                    this.dispenserContents[par1] = null;
060                }
061
062                this.onInventoryChanged();
063                return itemstack;
064            }
065        }
066        else
067        {
068            return null;
069        }
070    }
071
072    /**
073     * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem -
074     * like when you close a workbench GUI.
075     */
076    public ItemStack getStackInSlotOnClosing(int par1)
077    {
078        if (this.dispenserContents[par1] != null)
079        {
080            ItemStack itemstack = this.dispenserContents[par1];
081            this.dispenserContents[par1] = null;
082            return itemstack;
083        }
084        else
085        {
086            return null;
087        }
088    }
089
090    public int getRandomStackFromInventory()
091    {
092        int i = -1;
093        int j = 1;
094
095        for (int k = 0; k < this.dispenserContents.length; ++k)
096        {
097            if (this.dispenserContents[k] != null && this.dispenserRandom.nextInt(j++) == 0)
098            {
099                i = k;
100            }
101        }
102
103        return i;
104    }
105
106    /**
107     * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections).
108     */
109    public void setInventorySlotContents(int par1, ItemStack par2ItemStack)
110    {
111        this.dispenserContents[par1] = par2ItemStack;
112
113        if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit())
114        {
115            par2ItemStack.stackSize = this.getInventoryStackLimit();
116        }
117
118        this.onInventoryChanged();
119    }
120
121    /**
122     * Add item stack in first available inventory slot
123     */
124    public int addItem(ItemStack par1ItemStack)
125    {
126        for (int i = 0; i < this.dispenserContents.length; ++i)
127        {
128            if (this.dispenserContents[i] == null || this.dispenserContents[i].itemID == 0)
129            {
130                this.setInventorySlotContents(i, par1ItemStack);
131                return i;
132            }
133        }
134
135        return -1;
136    }
137
138    /**
139     * Returns the name of the inventory.
140     */
141    public String getInvName()
142    {
143        return this.isInvNameLocalized() ? this.field_94050_c : "container.dispenser";
144    }
145
146    public void func_94049_a(String par1Str)
147    {
148        this.field_94050_c = par1Str;
149    }
150
151    /**
152     * If this returns false, the inventory name will be used as an unlocalized name, and translated into the player's
153     * language. Otherwise it will be used directly.
154     */
155    public boolean isInvNameLocalized()
156    {
157        return this.field_94050_c != null;
158    }
159
160    /**
161     * Reads a tile entity from NBT.
162     */
163    public void readFromNBT(NBTTagCompound par1NBTTagCompound)
164    {
165        super.readFromNBT(par1NBTTagCompound);
166        NBTTagList nbttaglist = par1NBTTagCompound.getTagList("Items");
167        this.dispenserContents = new ItemStack[this.getSizeInventory()];
168
169        for (int i = 0; i < nbttaglist.tagCount(); ++i)
170        {
171            NBTTagCompound nbttagcompound1 = (NBTTagCompound)nbttaglist.tagAt(i);
172            int j = nbttagcompound1.getByte("Slot") & 255;
173
174            if (j >= 0 && j < this.dispenserContents.length)
175            {
176                this.dispenserContents[j] = ItemStack.loadItemStackFromNBT(nbttagcompound1);
177            }
178        }
179
180        if (par1NBTTagCompound.hasKey("CustomName"))
181        {
182            this.field_94050_c = par1NBTTagCompound.getString("CustomName");
183        }
184    }
185
186    /**
187     * Writes a tile entity to NBT.
188     */
189    public void writeToNBT(NBTTagCompound par1NBTTagCompound)
190    {
191        super.writeToNBT(par1NBTTagCompound);
192        NBTTagList nbttaglist = new NBTTagList();
193
194        for (int i = 0; i < this.dispenserContents.length; ++i)
195        {
196            if (this.dispenserContents[i] != null)
197            {
198                NBTTagCompound nbttagcompound1 = new NBTTagCompound();
199                nbttagcompound1.setByte("Slot", (byte)i);
200                this.dispenserContents[i].writeToNBT(nbttagcompound1);
201                nbttaglist.appendTag(nbttagcompound1);
202            }
203        }
204
205        par1NBTTagCompound.setTag("Items", nbttaglist);
206
207        if (this.isInvNameLocalized())
208        {
209            par1NBTTagCompound.setString("CustomName", this.field_94050_c);
210        }
211    }
212
213    /**
214     * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't
215     * this more of a set than a get?*
216     */
217    public int getInventoryStackLimit()
218    {
219        return 64;
220    }
221
222    /**
223     * Do not make give this method the name canInteractWith because it clashes with Container
224     */
225    public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
226    {
227        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;
228    }
229
230    public void openChest() {}
231
232    public void closeChest() {}
233
234    /**
235     * Returns true if automation is allowed to insert the given stack (ignoring stack size) into the given slot.
236     */
237    public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack)
238    {
239        return true;
240    }
241}