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 }