001 package net.minecraft.block;
002
003 import net.minecraft.block.material.Material;
004 import net.minecraft.creativetab.CreativeTabs;
005 import net.minecraft.entity.player.EntityPlayer;
006 import net.minecraft.util.AxisAlignedBB;
007 import net.minecraft.world.IBlockAccess;
008 import net.minecraft.world.World;
009
010 import net.minecraftforge.common.ForgeDirection;
011 import static net.minecraftforge.common.ForgeDirection.*;
012
013 public class BlockLever extends Block
014 {
015 protected BlockLever(int par1, int par2)
016 {
017 super(par1, par2, Material.circuits);
018 this.setCreativeTab(CreativeTabs.tabRedstone);
019 }
020
021 /**
022 * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
023 * cleared to be reused)
024 */
025 public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
026 {
027 return null;
028 }
029
030 /**
031 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two
032 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
033 */
034 public boolean isOpaqueCube()
035 {
036 return false;
037 }
038
039 /**
040 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
041 */
042 public boolean renderAsNormalBlock()
043 {
044 return false;
045 }
046
047 /**
048 * The type of render function that is called for this block
049 */
050 public int getRenderType()
051 {
052 return 12;
053 }
054
055 /**
056 * checks to see if you can place this block can be placed on that side of a block: BlockLever overrides
057 */
058 public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5)
059 {
060 ForgeDirection dir = ForgeDirection.getOrientation(par5);
061 return (dir == DOWN && par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN )) ||
062 (dir == UP && par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP )) ||
063 (dir == NORTH && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)) ||
064 (dir == SOUTH && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) ||
065 (dir == WEST && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST )) ||
066 (dir == EAST && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST ));
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.isBlockSolidOnSide(par2 - 1, par3, par4, EAST ) ||
075 par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST ) ||
076 par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH) ||
077 par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH) ||
078 par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP ) ||
079 par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN );
080 }
081
082 /**
083 * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z, side, hitX, hitY, hitZ, block metadata
084 */
085 public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
086 {
087 int var11 = par9 & 8;
088 int var10 = par9 & 7;
089 var10 = -1;
090
091 if (par5 == 0 && par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN))
092 {
093 var10 = par1World.rand.nextBoolean() ? 0 : 7;
094 }
095
096 if (par5 == 1 && par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP))
097 {
098 var10 = 5 + par1World.rand.nextInt(2);
099 }
100
101 if (par5 == 2 && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH))
102 {
103 var10 = 4;
104 }
105
106 if (par5 == 3 && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH))
107 {
108 var10 = 3;
109 }
110
111 if (par5 == 4 && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST))
112 {
113 var10 = 2;
114 }
115
116 if (par5 == 5 && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST))
117 {
118 var10 = 1;
119 }
120
121 return var10 + var11;
122 }
123
124 /**
125 * only used in ComponentScatteredFeatureJunglePyramid.addComponentParts"
126 */
127 public static int invertMetadata(int par0)
128 {
129 switch (par0)
130 {
131 case 0:
132 return 0;
133 case 1:
134 return 5;
135 case 2:
136 return 4;
137 case 3:
138 return 3;
139 case 4:
140 return 2;
141 case 5:
142 return 1;
143 default:
144 return -1;
145 }
146 }
147
148 /**
149 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
150 * their own) Args: x, y, z, neighbor blockID
151 */
152 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
153 {
154 if (this.checkIfAttachedToBlock(par1World, par2, par3, par4))
155 {
156 int var6 = par1World.getBlockMetadata(par2, par3, par4) & 7;
157 boolean var7 = false;
158
159 if (!par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST) && var6 == 1)
160 {
161 var7 = true;
162 }
163
164 if (!par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST) && var6 == 2)
165 {
166 var7 = true;
167 }
168
169 if (!par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH) && var6 == 3)
170 {
171 var7 = true;
172 }
173
174 if (!par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH) && var6 == 4)
175 {
176 var7 = true;
177 }
178
179 if (!par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP) && var6 == 5)
180 {
181 var7 = true;
182 }
183
184 if (!par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP) && var6 == 6)
185 {
186 var7 = true;
187 }
188
189 if (!par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN) && var6 == 0)
190 {
191 var7 = true;
192 }
193
194 if (!par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN) && var6 == 7)
195 {
196 var7 = true;
197 }
198
199 if (var7)
200 {
201 this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
202 par1World.setBlockWithNotify(par2, par3, par4, 0);
203 }
204 }
205 }
206
207 /**
208 * Checks if the block is attached to another block. If it is not, it returns false and drops the block as an item.
209 * If it is it returns true.
210 */
211 private boolean checkIfAttachedToBlock(World par1World, int par2, int par3, int par4)
212 {
213 if (!this.canPlaceBlockAt(par1World, par2, par3, par4))
214 {
215 this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
216 par1World.setBlockWithNotify(par2, par3, par4, 0);
217 return false;
218 }
219 else
220 {
221 return true;
222 }
223 }
224
225 /**
226 * Updates the blocks bounds based on its current state. Args: world, x, y, z
227 */
228 public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
229 {
230 int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 7;
231 float var6 = 0.1875F;
232
233 if (var5 == 1)
234 {
235 this.setBlockBounds(0.0F, 0.2F, 0.5F - var6, var6 * 2.0F, 0.8F, 0.5F + var6);
236 }
237 else if (var5 == 2)
238 {
239 this.setBlockBounds(1.0F - var6 * 2.0F, 0.2F, 0.5F - var6, 1.0F, 0.8F, 0.5F + var6);
240 }
241 else if (var5 == 3)
242 {
243 this.setBlockBounds(0.5F - var6, 0.2F, 0.0F, 0.5F + var6, 0.8F, var6 * 2.0F);
244 }
245 else if (var5 == 4)
246 {
247 this.setBlockBounds(0.5F - var6, 0.2F, 1.0F - var6 * 2.0F, 0.5F + var6, 0.8F, 1.0F);
248 }
249 else if (var5 != 5 && var5 != 6)
250 {
251 if (var5 == 0 || var5 == 7)
252 {
253 var6 = 0.25F;
254 this.setBlockBounds(0.5F - var6, 0.4F, 0.5F - var6, 0.5F + var6, 1.0F, 0.5F + var6);
255 }
256 }
257 else
258 {
259 var6 = 0.25F;
260 this.setBlockBounds(0.5F - var6, 0.0F, 0.5F - var6, 0.5F + var6, 0.6F, 0.5F + var6);
261 }
262 }
263
264 /**
265 * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
266 */
267 public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {}
268
269 /**
270 * Called upon block activation (right click on the block.)
271 */
272 public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
273 {
274 if (par1World.isRemote)
275 {
276 return true;
277 }
278 else
279 {
280 int var10 = par1World.getBlockMetadata(par2, par3, par4);
281 int var11 = var10 & 7;
282 int var12 = 8 - (var10 & 8);
283 par1World.setBlockMetadataWithNotify(par2, par3, par4, var11 + var12);
284 par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
285 par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "random.click", 0.3F, var12 > 0 ? 0.6F : 0.5F);
286 par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
287
288 if (var11 == 1)
289 {
290 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
291 }
292 else if (var11 == 2)
293 {
294 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
295 }
296 else if (var11 == 3)
297 {
298 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
299 }
300 else if (var11 == 4)
301 {
302 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
303 }
304 else if (var11 != 5 && var11 != 6)
305 {
306 if (var11 == 0 || var11 == 7)
307 {
308 par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
309 }
310 }
311 else
312 {
313 par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
314 }
315
316 return true;
317 }
318 }
319
320 /**
321 * ejects contained items into the world, and notifies neighbours of an update, as appropriate
322 */
323 public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
324 {
325 if ((par6 & 8) > 0)
326 {
327 par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
328 int var7 = par6 & 7;
329
330 if (var7 == 1)
331 {
332 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
333 }
334 else if (var7 == 2)
335 {
336 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
337 }
338 else if (var7 == 3)
339 {
340 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
341 }
342 else if (var7 == 4)
343 {
344 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
345 }
346 else if (var7 != 5 && var7 != 6)
347 {
348 if (var7 == 0 || var7 == 7)
349 {
350 par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
351 }
352 }
353 else
354 {
355 par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
356 }
357 }
358
359 super.breakBlock(par1World, par2, par3, par4, par5, par6);
360 }
361
362 /**
363 * Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube
364 * returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X,
365 * Y, Z, side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
366 */
367 public boolean isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
368 {
369 return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) > 0;
370 }
371
372 /**
373 * Returns true if the block is emitting direct/strong redstone power on the specified side. Args: World, X, Y, Z,
374 * side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block.
375 */
376 public boolean isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
377 {
378 int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
379
380 if ((var6 & 8) == 0)
381 {
382 return false;
383 }
384 else
385 {
386 int var7 = var6 & 7;
387 return var7 == 0 && par5 == 0 ? true : (var7 == 7 && par5 == 0 ? true : (var7 == 6 && par5 == 1 ? true : (var7 == 5 && par5 == 1 ? true : (var7 == 4 && par5 == 2 ? true : (var7 == 3 && par5 == 3 ? true : (var7 == 2 && par5 == 4 ? true : var7 == 1 && par5 == 5))))));
388 }
389 }
390
391 /**
392 * Can this block provide power. Only wire currently seems to have this change based on its state.
393 */
394 public boolean canProvidePower()
395 {
396 return true;
397 }
398 }