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