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 public int func_85104_a(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
083 {
084 int var11 = par9 & 8;
085 int var10 = par9 & 7;
086 var10 = -1;
087
088 if (par5 == 0 && par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN))
089 {
090 var10 = par1World.rand.nextBoolean() ? 0 : 7;
091 }
092
093 if (par5 == 1 && par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP))
094 {
095 var10 = 5 + par1World.rand.nextInt(2);
096 }
097
098 if (par5 == 2 && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH))
099 {
100 var10 = 4;
101 }
102
103 if (par5 == 3 && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH))
104 {
105 var10 = 3;
106 }
107
108 if (par5 == 4 && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST))
109 {
110 var10 = 2;
111 }
112
113 if (par5 == 5 && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST))
114 {
115 var10 = 1;
116 }
117
118 return var10 + var11;
119 }
120
121 /**
122 * only used in ComponentScatteredFeatureJunglePyramid.addComponentParts"
123 */
124 public static int invertMetadata(int par0)
125 {
126 switch (par0)
127 {
128 case 0:
129 return 0;
130 case 1:
131 return 5;
132 case 2:
133 return 4;
134 case 3:
135 return 3;
136 case 4:
137 return 2;
138 case 5:
139 return 1;
140 default:
141 return -1;
142 }
143 }
144
145 /**
146 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
147 * their own) Args: x, y, z, neighbor blockID
148 */
149 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
150 {
151 if (this.checkIfAttachedToBlock(par1World, par2, par3, par4))
152 {
153 int var6 = par1World.getBlockMetadata(par2, par3, par4) & 7;
154 boolean var7 = false;
155
156 if (!par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST) && var6 == 1)
157 {
158 var7 = true;
159 }
160
161 if (!par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST) && var6 == 2)
162 {
163 var7 = true;
164 }
165
166 if (!par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH) && var6 == 3)
167 {
168 var7 = true;
169 }
170
171 if (!par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH) && var6 == 4)
172 {
173 var7 = true;
174 }
175
176 if (!par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP) && var6 == 5)
177 {
178 var7 = true;
179 }
180
181 if (!par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP) && var6 == 6)
182 {
183 var7 = true;
184 }
185
186 if (!par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN) && var6 == 0)
187 {
188 var7 = true;
189 }
190
191 if (!par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN) && var6 == 7)
192 {
193 var7 = true;
194 }
195
196 if (var7)
197 {
198 this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
199 par1World.setBlockWithNotify(par2, par3, par4, 0);
200 }
201 }
202 }
203
204 /**
205 * Checks if the block is attached to another block. If it is not, it returns false and drops the block as an item.
206 * If it is it returns true.
207 */
208 private boolean checkIfAttachedToBlock(World par1World, int par2, int par3, int par4)
209 {
210 if (!this.canPlaceBlockAt(par1World, par2, par3, par4))
211 {
212 this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
213 par1World.setBlockWithNotify(par2, par3, par4, 0);
214 return false;
215 }
216 else
217 {
218 return true;
219 }
220 }
221
222 /**
223 * Updates the blocks bounds based on its current state. Args: world, x, y, z
224 */
225 public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
226 {
227 int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 7;
228 float var6 = 0.1875F;
229
230 if (var5 == 1)
231 {
232 this.setBlockBounds(0.0F, 0.2F, 0.5F - var6, var6 * 2.0F, 0.8F, 0.5F + var6);
233 }
234 else if (var5 == 2)
235 {
236 this.setBlockBounds(1.0F - var6 * 2.0F, 0.2F, 0.5F - var6, 1.0F, 0.8F, 0.5F + var6);
237 }
238 else if (var5 == 3)
239 {
240 this.setBlockBounds(0.5F - var6, 0.2F, 0.0F, 0.5F + var6, 0.8F, var6 * 2.0F);
241 }
242 else if (var5 == 4)
243 {
244 this.setBlockBounds(0.5F - var6, 0.2F, 1.0F - var6 * 2.0F, 0.5F + var6, 0.8F, 1.0F);
245 }
246 else if (var5 != 5 && var5 != 6)
247 {
248 if (var5 == 0 || var5 == 7)
249 {
250 var6 = 0.25F;
251 this.setBlockBounds(0.5F - var6, 0.4F, 0.5F - var6, 0.5F + var6, 1.0F, 0.5F + var6);
252 }
253 }
254 else
255 {
256 var6 = 0.25F;
257 this.setBlockBounds(0.5F - var6, 0.0F, 0.5F - var6, 0.5F + var6, 0.6F, 0.5F + var6);
258 }
259 }
260
261 /**
262 * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
263 */
264 public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {}
265
266 /**
267 * Called upon block activation (right click on the block.)
268 */
269 public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
270 {
271 if (par1World.isRemote)
272 {
273 return true;
274 }
275 else
276 {
277 int var10 = par1World.getBlockMetadata(par2, par3, par4);
278 int var11 = var10 & 7;
279 int var12 = 8 - (var10 & 8);
280 par1World.setBlockMetadataWithNotify(par2, par3, par4, var11 + var12);
281 par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
282 par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "random.click", 0.3F, var12 > 0 ? 0.6F : 0.5F);
283 par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
284
285 if (var11 == 1)
286 {
287 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
288 }
289 else if (var11 == 2)
290 {
291 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
292 }
293 else if (var11 == 3)
294 {
295 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
296 }
297 else if (var11 == 4)
298 {
299 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
300 }
301 else if (var11 != 5 && var11 != 6)
302 {
303 if (var11 == 0 || var11 == 7)
304 {
305 par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
306 }
307 }
308 else
309 {
310 par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
311 }
312
313 return true;
314 }
315 }
316
317 /**
318 * ejects contained items into the world, and notifies neighbours of an update, as appropriate
319 */
320 public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
321 {
322 if ((par6 & 8) > 0)
323 {
324 par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
325 int var7 = par6 & 7;
326
327 if (var7 == 1)
328 {
329 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
330 }
331 else if (var7 == 2)
332 {
333 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
334 }
335 else if (var7 == 3)
336 {
337 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
338 }
339 else if (var7 == 4)
340 {
341 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
342 }
343 else if (var7 != 5 && var7 != 6)
344 {
345 if (var7 == 0 || var7 == 7)
346 {
347 par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
348 }
349 }
350 else
351 {
352 par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
353 }
354 }
355
356 super.breakBlock(par1World, par2, par3, par4, par5, par6);
357 }
358
359 /**
360 * Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube
361 * returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X,
362 * Y, Z, side
363 */
364 public boolean isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
365 {
366 return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) > 0;
367 }
368
369 /**
370 * Returns true if the block is emitting direct/strong redstone power on the specified side. Args: World, X, Y, Z,
371 * side
372 */
373 public boolean isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
374 {
375 int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
376
377 if ((var6 & 8) == 0)
378 {
379 return false;
380 }
381 else
382 {
383 int var7 = var6 & 7;
384 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))))));
385 }
386 }
387
388 /**
389 * Can this block provide power. Only wire currently seems to have this change based on its state.
390 */
391 public boolean canProvidePower()
392 {
393 return true;
394 }
395 }