001 package net.minecraft.block;
002
003 import cpw.mods.fml.relauncher.Side;
004 import cpw.mods.fml.relauncher.SideOnly;
005 import java.util.Random;
006 import net.minecraft.block.material.Material;
007 import net.minecraft.entity.player.EntityPlayer;
008 import net.minecraft.item.Item;
009 import net.minecraft.util.AxisAlignedBB;
010 import net.minecraft.util.MovingObjectPosition;
011 import net.minecraft.util.Vec3;
012 import net.minecraft.world.IBlockAccess;
013 import net.minecraft.world.World;
014
015 public class BlockDoor extends Block
016 {
017 protected BlockDoor(int par1, Material par2Material)
018 {
019 super(par1, par2Material);
020 this.blockIndexInTexture = 97;
021
022 if (par2Material == Material.iron)
023 {
024 ++this.blockIndexInTexture;
025 }
026
027 float var3 = 0.5F;
028 float var4 = 1.0F;
029 this.setBlockBounds(0.5F - var3, 0.0F, 0.5F - var3, 0.5F + var3, var4, 0.5F + var3);
030 }
031
032 @SideOnly(Side.CLIENT)
033
034 /**
035 * Retrieves the block texture to use based on the display side. Args: iBlockAccess, x, y, z, side
036 */
037 public int getBlockTexture(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
038 {
039 if (par5 != 0 && par5 != 1)
040 {
041 int var6 = this.getFullMetadata(par1IBlockAccess, par2, par3, par4);
042 int var7 = this.blockIndexInTexture;
043
044 if ((var6 & 8) != 0)
045 {
046 var7 -= 16;
047 }
048
049 int var8 = var6 & 3;
050 boolean var9 = (var6 & 4) != 0;
051
052 if (var9)
053 {
054 if (var8 == 0 && par5 == 2)
055 {
056 var7 = -var7;
057 }
058 else if (var8 == 1 && par5 == 5)
059 {
060 var7 = -var7;
061 }
062 else if (var8 == 2 && par5 == 3)
063 {
064 var7 = -var7;
065 }
066 else if (var8 == 3 && par5 == 4)
067 {
068 var7 = -var7;
069 }
070 }
071 else
072 {
073 if (var8 == 0 && par5 == 5)
074 {
075 var7 = -var7;
076 }
077 else if (var8 == 1 && par5 == 3)
078 {
079 var7 = -var7;
080 }
081 else if (var8 == 2 && par5 == 4)
082 {
083 var7 = -var7;
084 }
085 else if (var8 == 3 && par5 == 2)
086 {
087 var7 = -var7;
088 }
089
090 if ((var6 & 16) != 0)
091 {
092 var7 = -var7;
093 }
094 }
095
096 return var7;
097 }
098 else
099 {
100 return this.blockIndexInTexture;
101 }
102 }
103
104 /**
105 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two
106 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
107 */
108 public boolean isOpaqueCube()
109 {
110 return false;
111 }
112
113 public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
114 {
115 int var5 = this.getFullMetadata(par1IBlockAccess, par2, par3, par4);
116 return (var5 & 4) != 0;
117 }
118
119 /**
120 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
121 */
122 public boolean renderAsNormalBlock()
123 {
124 return false;
125 }
126
127 /**
128 * The type of render function that is called for this block
129 */
130 public int getRenderType()
131 {
132 return 7;
133 }
134
135 @SideOnly(Side.CLIENT)
136
137 /**
138 * Returns the bounding box of the wired rectangular prism to render.
139 */
140 public AxisAlignedBB getSelectedBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
141 {
142 this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
143 return super.getSelectedBoundingBoxFromPool(par1World, par2, par3, par4);
144 }
145
146 /**
147 * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
148 * cleared to be reused)
149 */
150 public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
151 {
152 this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
153 return super.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4);
154 }
155
156 /**
157 * Updates the blocks bounds based on its current state. Args: world, x, y, z
158 */
159 public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
160 {
161 this.setDoorRotation(this.getFullMetadata(par1IBlockAccess, par2, par3, par4));
162 }
163
164 /**
165 * Returns 0, 1, 2 or 3 depending on where the hinge is.
166 */
167 public int getDoorOrientation(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
168 {
169 return this.getFullMetadata(par1IBlockAccess, par2, par3, par4) & 3;
170 }
171
172 public boolean isDoorOpen(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
173 {
174 return (this.getFullMetadata(par1IBlockAccess, par2, par3, par4) & 4) != 0;
175 }
176
177 private void setDoorRotation(int par1)
178 {
179 float var2 = 0.1875F;
180 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 2.0F, 1.0F);
181 int var3 = par1 & 3;
182 boolean var4 = (par1 & 4) != 0;
183 boolean var5 = (par1 & 16) != 0;
184
185 if (var3 == 0)
186 {
187 if (var4)
188 {
189 if (!var5)
190 {
191 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2);
192 }
193 else
194 {
195 this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F);
196 }
197 }
198 else
199 {
200 this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F);
201 }
202 }
203 else if (var3 == 1)
204 {
205 if (var4)
206 {
207 if (!var5)
208 {
209 this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
210 }
211 else
212 {
213 this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F);
214 }
215 }
216 else
217 {
218 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2);
219 }
220 }
221 else if (var3 == 2)
222 {
223 if (var4)
224 {
225 if (!var5)
226 {
227 this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F);
228 }
229 else
230 {
231 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2);
232 }
233 }
234 else
235 {
236 this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
237 }
238 }
239 else if (var3 == 3)
240 {
241 if (var4)
242 {
243 if (!var5)
244 {
245 this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F);
246 }
247 else
248 {
249 this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
250 }
251 }
252 else
253 {
254 this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F);
255 }
256 }
257 }
258
259 /**
260 * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
261 */
262 public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {}
263
264 /**
265 * Called upon block activation (right click on the block.)
266 */
267 public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
268 {
269 if (this.blockMaterial == Material.iron)
270 {
271 return false; //Allow items to interact with the door
272 }
273 else
274 {
275 int var10 = this.getFullMetadata(par1World, par2, par3, par4);
276 int var11 = var10 & 7;
277 var11 ^= 4;
278
279 if ((var10 & 8) == 0)
280 {
281 par1World.setBlockMetadataWithNotify(par2, par3, par4, var11);
282 par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
283 }
284 else
285 {
286 par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var11);
287 par1World.markBlockRangeForRenderUpdate(par2, par3 - 1, par4, par2, par3, par4);
288 }
289
290 par1World.playAuxSFXAtEntity(par5EntityPlayer, 1003, par2, par3, par4, 0);
291 return true;
292 }
293 }
294
295 /**
296 * A function to open a door.
297 */
298 public void onPoweredBlockChange(World par1World, int par2, int par3, int par4, boolean par5)
299 {
300 int var6 = this.getFullMetadata(par1World, par2, par3, par4);
301 boolean var7 = (var6 & 4) != 0;
302
303 if (var7 != par5)
304 {
305 int var8 = var6 & 7;
306 var8 ^= 4;
307
308 if ((var6 & 8) == 0)
309 {
310 par1World.setBlockMetadataWithNotify(par2, par3, par4, var8);
311 par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
312 }
313 else
314 {
315 par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var8);
316 par1World.markBlockRangeForRenderUpdate(par2, par3 - 1, par4, par2, par3, par4);
317 }
318
319 par1World.playAuxSFXAtEntity((EntityPlayer)null, 1003, par2, par3, par4, 0);
320 }
321 }
322
323 /**
324 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
325 * their own) Args: x, y, z, neighbor blockID
326 */
327 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
328 {
329 int var6 = par1World.getBlockMetadata(par2, par3, par4);
330
331 if ((var6 & 8) == 0)
332 {
333 boolean var7 = false;
334
335 if (par1World.getBlockId(par2, par3 + 1, par4) != this.blockID)
336 {
337 par1World.setBlockWithNotify(par2, par3, par4, 0);
338 var7 = true;
339 }
340
341 if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4))
342 {
343 par1World.setBlockWithNotify(par2, par3, par4, 0);
344 var7 = true;
345
346 if (par1World.getBlockId(par2, par3 + 1, par4) == this.blockID)
347 {
348 par1World.setBlockWithNotify(par2, par3 + 1, par4, 0);
349 }
350 }
351
352 if (var7)
353 {
354 if (!par1World.isRemote)
355 {
356 this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
357 }
358 }
359 else
360 {
361 boolean var8 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4) || par1World.isBlockIndirectlyGettingPowered(par2, par3 + 1, par4);
362
363 if ((var8 || par5 > 0 && Block.blocksList[par5].canProvidePower()) && par5 != this.blockID)
364 {
365 this.onPoweredBlockChange(par1World, par2, par3, par4, var8);
366 }
367 }
368 }
369 else
370 {
371 if (par1World.getBlockId(par2, par3 - 1, par4) != this.blockID)
372 {
373 par1World.setBlockWithNotify(par2, par3, par4, 0);
374 }
375
376 if (par5 > 0 && par5 != this.blockID)
377 {
378 this.onNeighborBlockChange(par1World, par2, par3 - 1, par4, par5);
379 }
380 }
381 }
382
383 /**
384 * Returns the ID of the items to drop on destruction.
385 */
386 public int idDropped(int par1, Random par2Random, int par3)
387 {
388 return (par1 & 8) != 0 ? 0 : (this.blockMaterial == Material.iron ? Item.doorSteel.itemID : Item.doorWood.itemID);
389 }
390
391 /**
392 * Ray traces through the blocks collision from start vector to end vector returning a ray trace hit. Args: world,
393 * x, y, z, startVec, endVec
394 */
395 public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3, Vec3 par6Vec3)
396 {
397 this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
398 return super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3);
399 }
400
401 /**
402 * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
403 */
404 public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
405 {
406 return par3 >= 255 ? false : par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && super.canPlaceBlockAt(par1World, par2, par3, par4) && super.canPlaceBlockAt(par1World, par2, par3 + 1, par4);
407 }
408
409 /**
410 * Returns the mobility information of the block, 0 = free, 1 = can't push but can move over, 2 = total immobility
411 * and stop pistons
412 */
413 public int getMobilityFlag()
414 {
415 return 1;
416 }
417
418 /**
419 * Returns the full metadata value created by combining the metadata of both blocks the door takes up.
420 */
421 public int getFullMetadata(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
422 {
423 int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
424 boolean var6 = (var5 & 8) != 0;
425 int var7;
426 int var8;
427
428 if (var6)
429 {
430 var7 = par1IBlockAccess.getBlockMetadata(par2, par3 - 1, par4);
431 var8 = var5;
432 }
433 else
434 {
435 var7 = var5;
436 var8 = par1IBlockAccess.getBlockMetadata(par2, par3 + 1, par4);
437 }
438
439 boolean var9 = (var8 & 1) != 0;
440 return var7 & 7 | (var6 ? 8 : 0) | (var9 ? 16 : 0);
441 }
442
443 @SideOnly(Side.CLIENT)
444
445 /**
446 * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative)
447 */
448 public int idPicked(World par1World, int par2, int par3, int par4)
449 {
450 return this.blockMaterial == Material.iron ? Item.doorSteel.itemID : Item.doorWood.itemID;
451 }
452
453 /**
454 * Called when the block is attempted to be harvested
455 */
456 public void onBlockHarvested(World par1World, int par2, int par3, int par4, int par5, EntityPlayer par6EntityPlayer)
457 {
458 if (par6EntityPlayer.capabilities.isCreativeMode && (par5 & 8) != 0 && par1World.getBlockId(par2, par3 - 1, par4) == this.blockID)
459 {
460 par1World.setBlockWithNotify(par2, par3 - 1, par4, 0);
461 }
462 }
463 }