001    package net.minecraft.block;
002    
003    import java.util.Iterator;
004    import java.util.List;
005    import java.util.Random;
006    import net.minecraft.block.material.Material;
007    import net.minecraft.creativetab.CreativeTabs;
008    import net.minecraft.entity.Entity;
009    import net.minecraft.entity.EntityLiving;
010    import net.minecraft.entity.player.EntityPlayer;
011    import net.minecraft.util.AxisAlignedBB;
012    import net.minecraft.world.IBlockAccess;
013    import net.minecraft.world.World;
014    
015    public 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    }