    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}