001package net.minecraft.tileentity;
002
003import cpw.mods.fml.relauncher.Side;
004import cpw.mods.fml.relauncher.SideOnly;
005import java.util.Iterator;
006import java.util.List;
007import net.minecraft.block.Block;
008import net.minecraft.entity.player.EntityPlayer;
009import net.minecraft.inventory.IInventory;
010import net.minecraft.item.ItemStack;
011import net.minecraft.nbt.NBTTagCompound;
012import net.minecraft.network.packet.Packet;
013import net.minecraft.network.packet.Packet132TileEntityData;
014import net.minecraft.potion.Potion;
015import net.minecraft.potion.PotionEffect;
016import net.minecraft.util.AxisAlignedBB;
017
018public class TileEntityBeacon extends TileEntity implements IInventory
019{
020    /** List of effects that Beacon can apply */
021    public static final Potion[][] effectsList = new Potion[][] {{Potion.moveSpeed, Potion.digSpeed}, {Potion.resistance, Potion.jump}, {Potion.damageBoost}, {Potion.regeneration}};
022    @SideOnly(Side.CLIENT)
023    private long field_82137_b;
024    @SideOnly(Side.CLIENT)
025    private float field_82138_c;
026    private boolean field_82135_d;
027
028    /** Level of this beacon's pyramid. */
029    private int levels = -1;
030
031    /** Primary potion effect given by this beacon. */
032    private int primaryEffect;
033
034    /** Secondary potion effect given by this beacon. */
035    private int secondaryEffect;
036
037    /** Item given to this beacon as payment. */
038    private ItemStack payment;
039
040    /**
041     * Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count
042     * ticks and creates a new spawn inside its implementation.
043     */
044    public void updateEntity()
045    {
046        if (this.worldObj.getTotalWorldTime() % 80L == 0L)
047        {
048            this.func_82131_u();
049            this.func_82124_t();
050        }
051    }
052
053    private void func_82124_t()
054    {
055        if (this.field_82135_d && this.levels > 0 && !this.worldObj.isRemote && this.primaryEffect > 0)
056        {
057            double var1 = (double)(this.levels * 8 + 8);
058            byte var3 = 0;
059
060            if (this.levels >= 4 && this.primaryEffect == this.secondaryEffect)
061            {
062                var3 = 1;
063            }
064
065            AxisAlignedBB var4 = AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)this.xCoord, (double)this.yCoord, (double)this.zCoord, (double)(this.xCoord + 1), (double)(this.yCoord + 1), (double)(this.zCoord + 1)).expand(var1, var1, var1);
066            List var5 = this.worldObj.getEntitiesWithinAABB(EntityPlayer.class, var4);
067            Iterator var6 = var5.iterator();
068            EntityPlayer var7;
069
070            while (var6.hasNext())
071            {
072                var7 = (EntityPlayer)var6.next();
073                var7.addPotionEffect(new PotionEffect(this.primaryEffect, 180, var3, true));
074            }
075
076            if (this.levels >= 4 && this.primaryEffect != this.secondaryEffect && this.secondaryEffect > 0)
077            {
078                var6 = var5.iterator();
079
080                while (var6.hasNext())
081                {
082                    var7 = (EntityPlayer)var6.next();
083                    var7.addPotionEffect(new PotionEffect(this.secondaryEffect, 180, 0, true));
084                }
085            }
086        }
087    }
088
089    private void func_82131_u()
090    {
091        if (!this.worldObj.canBlockSeeTheSky(this.xCoord, this.yCoord + 1, this.zCoord))
092        {
093            this.field_82135_d = false;
094            this.levels = 0;
095        }
096        else
097        {
098            this.field_82135_d = true;
099            this.levels = 0;
100
101            for (int var1 = 1; var1 <= 4; this.levels = var1++)
102            {
103                int var2 = this.yCoord - var1;
104
105                if (var2 < 0)
106                {
107                    break;
108                }
109
110                boolean var3 = true;
111
112                for (int var4 = this.xCoord - var1; var4 <= this.xCoord + var1 && var3; ++var4)
113                {
114                    for (int var5 = this.zCoord - var1; var5 <= this.zCoord + var1; ++var5)
115                    {
116                        int var6 = this.worldObj.getBlockId(var4, var2, var5);
117                        Block block = Block.blocksList[var6];
118
119                        if (block == null || !block.isBeaconBase(worldObj, var4, var2, var5, xCoord, yCoord, zCoord))
120                        {
121                            var3 = false;
122                            break;
123                        }
124                    }
125                }
126
127                if (!var3)
128                {
129                    break;
130                }
131            }
132
133            if (this.levels == 0)
134            {
135                this.field_82135_d = false;
136            }
137        }
138    }
139
140    @SideOnly(Side.CLIENT)
141    public float func_82125_v_()
142    {
143        if (!this.field_82135_d)
144        {
145            return 0.0F;
146        }
147        else
148        {
149            int var1 = (int)(this.worldObj.getTotalWorldTime() - this.field_82137_b);
150            this.field_82137_b = this.worldObj.getTotalWorldTime();
151
152            if (var1 > 1)
153            {
154                this.field_82138_c -= (float)var1 / 40.0F;
155
156                if (this.field_82138_c < 0.0F)
157                {
158                    this.field_82138_c = 0.0F;
159                }
160            }
161
162            this.field_82138_c += 0.025F;
163
164            if (this.field_82138_c > 1.0F)
165            {
166                this.field_82138_c = 1.0F;
167            }
168
169            return this.field_82138_c;
170        }
171    }
172
173    /**
174     * Return the primary potion effect given by this beacon.
175     */
176    public int getPrimaryEffect()
177    {
178        return this.primaryEffect;
179    }
180
181    /**
182     * Return the secondary potion effect given by this beacon.
183     */
184    public int getSecondaryEffect()
185    {
186        return this.secondaryEffect;
187    }
188
189    /**
190     * Return the levels of this beacon's pyramid.
191     */
192    public int getLevels()
193    {
194        return this.levels;
195    }
196
197    @SideOnly(Side.CLIENT)
198
199    /**
200     * Set the levels of this beacon's pyramid.
201     */
202    public void setLevels(int par1)
203    {
204        this.levels = par1;
205    }
206
207    public void func_82128_d(int par1)
208    {
209        this.primaryEffect = 0;
210
211        for (int var2 = 0; var2 < this.levels && var2 < 3; ++var2)
212        {
213            Potion[] var3 = effectsList[var2];
214            int var4 = var3.length;
215
216            for (int var5 = 0; var5 < var4; ++var5)
217            {
218                Potion var6 = var3[var5];
219
220                if (var6.id == par1)
221                {
222                    this.primaryEffect = par1;
223                    return;
224                }
225            }
226        }
227    }
228
229    public void func_82127_e(int par1)
230    {
231        this.secondaryEffect = 0;
232
233        if (this.levels >= 4)
234        {
235            for (int var2 = 0; var2 < 4; ++var2)
236            {
237                Potion[] var3 = effectsList[var2];
238                int var4 = var3.length;
239
240                for (int var5 = 0; var5 < var4; ++var5)
241                {
242                    Potion var6 = var3[var5];
243
244                    if (var6.id == par1)
245                    {
246                        this.secondaryEffect = par1;
247                        return;
248                    }
249                }
250            }
251        }
252    }
253
254    /**
255     * Overriden in a sign to provide the text.
256     */
257    public Packet getDescriptionPacket()
258    {
259        NBTTagCompound var1 = new NBTTagCompound();
260        this.writeToNBT(var1);
261        return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 3, var1);
262    }
263
264    @SideOnly(Side.CLIENT)
265    public double func_82115_m()
266    {
267        return 65536.0D;
268    }
269
270    /**
271     * Reads a tile entity from NBT.
272     */
273    public void readFromNBT(NBTTagCompound par1NBTTagCompound)
274    {
275        super.readFromNBT(par1NBTTagCompound);
276        this.primaryEffect = par1NBTTagCompound.getInteger("Primary");
277        this.secondaryEffect = par1NBTTagCompound.getInteger("Secondary");
278        this.levels = par1NBTTagCompound.getInteger("Levels");
279    }
280
281    /**
282     * Writes a tile entity to NBT.
283     */
284    public void writeToNBT(NBTTagCompound par1NBTTagCompound)
285    {
286        super.writeToNBT(par1NBTTagCompound);
287        par1NBTTagCompound.setInteger("Primary", this.primaryEffect);
288        par1NBTTagCompound.setInteger("Secondary", this.secondaryEffect);
289        par1NBTTagCompound.setInteger("Levels", this.levels);
290    }
291
292    /**
293     * Returns the number of slots in the inventory.
294     */
295    public int getSizeInventory()
296    {
297        return 1;
298    }
299
300    /**
301     * Returns the stack in slot i
302     */
303    public ItemStack getStackInSlot(int par1)
304    {
305        return par1 == 0 ? this.payment : null;
306    }
307
308    /**
309     * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a
310     * new stack.
311     */
312    public ItemStack decrStackSize(int par1, int par2)
313    {
314        if (par1 == 0 && this.payment != null)
315        {
316            if (par2 >= this.payment.stackSize)
317            {
318                ItemStack var3 = this.payment;
319                this.payment = null;
320                return var3;
321            }
322            else
323            {
324                this.payment.stackSize -= par2;
325                return new ItemStack(this.payment.itemID, par2, this.payment.getItemDamage());
326            }
327        }
328        else
329        {
330            return null;
331        }
332    }
333
334    /**
335     * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem -
336     * like when you close a workbench GUI.
337     */
338    public ItemStack getStackInSlotOnClosing(int par1)
339    {
340        if (par1 == 0 && this.payment != null)
341        {
342            ItemStack var2 = this.payment;
343            this.payment = null;
344            return var2;
345        }
346        else
347        {
348            return null;
349        }
350    }
351
352    /**
353     * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections).
354     */
355    public void setInventorySlotContents(int par1, ItemStack par2ItemStack)
356    {
357        if (par1 == 0)
358        {
359            this.payment = par2ItemStack;
360        }
361    }
362
363    /**
364     * Returns the name of the inventory.
365     */
366    public String getInvName()
367    {
368        return "container.beacon";
369    }
370
371    /**
372     * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't
373     * this more of a set than a get?*
374     */
375    public int getInventoryStackLimit()
376    {
377        return 1;
378    }
379
380    /**
381     * Do not make give this method the name canInteractWith because it clashes with Container
382     */
383    public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
384    {
385        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;
386    }
387
388    public void openChest() {}
389
390    public void closeChest() {}
391}