001package net.minecraft.block;
002
003import java.util.Iterator;
004import java.util.List;
005import java.util.Random;
006import net.minecraft.block.material.Material;
007import net.minecraft.creativetab.CreativeTabs;
008import net.minecraft.entity.Entity;
009import net.minecraft.entity.EntityLiving;
010import net.minecraft.entity.player.EntityPlayer;
011import net.minecraft.util.AxisAlignedBB;
012import net.minecraft.world.IBlockAccess;
013import net.minecraft.world.World;
014
015public class BlockPressurePlate extends Block
016{
017    /** The mob type that can trigger this pressure plate. */
018    private EnumMobType triggerMobType;
019
020    protected BlockPressurePlate(int par1, int par2, EnumMobType par3EnumMobType, Material par4Material)
021    {
022        super(par1, par2, par4Material);
023        this.triggerMobType = par3EnumMobType;
024        this.setCreativeTab(CreativeTabs.tabRedstone);
025        this.setTickRandomly(true);
026        float var5 = 0.0625F;
027        this.setBlockBounds(var5, 0.0F, var5, 1.0F - var5, 0.03125F, 1.0F - var5);
028    }
029
030    /**
031     * How many world ticks before ticking
032     */
033    public int tickRate()
034    {
035        return 20;
036    }
037
038    /**
039     * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
040     * cleared to be reused)
041     */
042    public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
043    {
044        return null;
045    }
046
047    /**
048     * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
049     * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
050     */
051    public boolean isOpaqueCube()
052    {
053        return false;
054    }
055
056    /**
057     * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
058     */
059    public boolean renderAsNormalBlock()
060    {
061        return false;
062    }
063
064    public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
065    {
066        return true;
067    }
068
069    /**
070     * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
071     */
072    public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
073    {
074        return par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) || BlockFence.isIdAFence(par1World.getBlockId(par2, par3 - 1, par4));
075    }
076
077    /**
078     * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
079     * their own) Args: x, y, z, neighbor blockID
080     */
081    public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
082    {
083        boolean var6 = false;
084
085        if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && !BlockFence.isIdAFence(par1World.getBlockId(par2, par3 - 1, par4)))
086        {
087            var6 = true;
088        }
089
090        if (var6)
091        {
092            this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
093            par1World.setBlockWithNotify(par2, par3, par4, 0);
094        }
095    }
096
097    /**
098     * Ticks the block if it's been scheduled
099     */
100    public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
101    {
102        if (!par1World.isRemote)
103        {
104            if (par1World.getBlockMetadata(par2, par3, par4) != 0)
105            {
106                this.setStateIfMobInteractsWithPlate(par1World, par2, par3, par4);
107            }
108        }
109    }
110
111    /**
112     * Triggered whenever an entity collides with this block (enters into the block). Args: world, x, y, z, entity
113     */
114    public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity)
115    {
116        if (!par1World.isRemote)
117        {
118            if (par1World.getBlockMetadata(par2, par3, par4) != 1)
119            {
120                this.setStateIfMobInteractsWithPlate(par1World, par2, par3, par4);
121            }
122        }
123    }
124
125    /**
126     * Checks if there are mobs on the plate. If a mob is on the plate and it is off, it turns it on, and vice versa.
127     */
128    private void setStateIfMobInteractsWithPlate(World par1World, int par2, int par3, int par4)
129    {
130        boolean var5 = par1World.getBlockMetadata(par2, par3, par4) == 1;
131        boolean var6 = false;
132        float var7 = 0.125F;
133        List var8 = null;
134
135        if (this.triggerMobType == EnumMobType.everything)
136        {
137            var8 = par1World.getEntitiesWithinAABBExcludingEntity((Entity)null, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)((float)par2 + var7), (double)par3, (double)((float)par4 + var7), (double)((float)(par2 + 1) - var7), (double)par3 + 0.25D, (double)((float)(par4 + 1) - var7)));
138        }
139
140        if (this.triggerMobType == EnumMobType.mobs)
141        {
142            var8 = par1World.getEntitiesWithinAABB(EntityLiving.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)((float)par2 + var7), (double)par3, (double)((float)par4 + var7), (double)((float)(par2 + 1) - var7), (double)par3 + 0.25D, (double)((float)(par4 + 1) - var7)));
143        }
144
145        if (this.triggerMobType == EnumMobType.players)
146        {
147            var8 = par1World.getEntitiesWithinAABB(EntityPlayer.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)((float)par2 + var7), (double)par3, (double)((float)par4 + var7), (double)((float)(par2 + 1) - var7), (double)par3 + 0.25D, (double)((float)(par4 + 1) - var7)));
148        }
149
150        if (!var8.isEmpty())
151        {
152            Iterator var9 = var8.iterator();
153
154            while (var9.hasNext())
155            {
156                Entity var10 = (Entity)var9.next();
157
158                if (!var10.doesEntityNotTriggerPressurePlate())
159                {
160                    var6 = true;
161                    break;
162                }
163            }
164        }
165
166        if (var6 && !var5)
167        {
168            par1World.setBlockMetadataWithNotify(par2, par3, par4, 1);
169            par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
170            par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
171            par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
172            par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.click", 0.3F, 0.6F);
173        }
174
175        if (!var6 && var5)
176        {
177            par1World.setBlockMetadataWithNotify(par2, par3, par4, 0);
178            par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
179            par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
180            par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
181            par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.click", 0.3F, 0.5F);
182        }
183
184        if (var6)
185        {
186            par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate());
187        }
188    }
189
190    /**
191     * ejects contained items into the world, and notifies neighbours of an update, as appropriate
192     */
193    public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
194    {
195        if (par6 > 0)
196        {
197            par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
198            par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
199        }
200
201        super.breakBlock(par1World, par2, par3, par4, par5, par6);
202    }
203
204    /**
205     * Updates the blocks bounds based on its current state. Args: world, x, y, z
206     */
207    public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
208    {
209        boolean var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4) == 1;
210        float var6 = 0.0625F;
211
212        if (var5)
213        {
214            this.setBlockBounds(var6, 0.0F, var6, 1.0F - var6, 0.03125F, 1.0F - var6);
215        }
216        else
217        {
218            this.setBlockBounds(var6, 0.0F, var6, 1.0F - var6, 0.0625F, 1.0F - var6);
219        }
220    }
221
222    /**
223     * Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube
224     * returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X,
225     * Y, Z, side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
226     */
227    public boolean isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
228    {
229        return par1IBlockAccess.getBlockMetadata(par2, par3, par4) > 0;
230    }
231
232    /**
233     * Returns true if the block is emitting direct/strong redstone power on the specified side. Args: World, X, Y, Z,
234     * side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
235     */
236    public boolean isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
237    {
238        return par1IBlockAccess.getBlockMetadata(par2, par3, par4) == 0 ? false : par5 == 1;
239    }
240
241    /**
242     * Can this block provide power. Only wire currently seems to have this change based on its state.
243     */
244    public boolean canProvidePower()
245    {
246        return true;
247    }
248
249    /**
250     * Sets the block's bounds for rendering it as an item
251     */
252    public void setBlockBoundsForItemRender()
253    {
254        float var1 = 0.5F;
255        float var2 = 0.125F;
256        float var3 = 0.5F;
257        this.setBlockBounds(0.5F - var1, 0.5F - var2, 0.5F - var3, 0.5F + var1, 0.5F + var2, 0.5F + var3);
258    }
259
260    /**
261     * Returns the mobility information of the block, 0 = free, 1 = can't push but can move over, 2 = total immobility
262     * and stop pistons
263     */
264    public int getMobilityFlag()
265    {
266        return 1;
267    }
268}