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 /**
258 * Called upon block activation (right click on the block.)
259 */
260 public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
261 {
262 if (this.blockMaterial == Material.iron)
263 {
264 return false; //Allow items to interact with the door
265 }
266 else
267 {
268 int var10 = this.getFullMetadata(par1World, par2, par3, par4);
269 int var11 = var10 & 7;
270 var11 ^= 4;
271
272 if ((var10 & 8) == 0)
273 {
274 par1World.setBlockMetadataWithNotify(par2, par3, par4, var11);
275 par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4);
276 }
277 else
278 {
279 par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var11);
280 par1World.markBlocksDirty(par2, par3 - 1, par4, par2, par3, par4);
281 }
282
283 par1World.playAuxSFXAtEntity(par5EntityPlayer, 1003, par2, par3, par4, 0);
284 return true;
285 }
286 }
287
288 /**
289 * A function to open a door.
290 */
291 public void onPoweredBlockChange(World par1World, int par2, int par3, int par4, boolean par5)
292 {
293 int var6 = this.getFullMetadata(par1World, par2, par3, par4);
294 boolean var7 = (var6 & 4) != 0;
295
296 if (var7 != par5)
297 {
298 int var8 = var6 & 7;
299 var8 ^= 4;
300
301 if ((var6 & 8) == 0)
302 {
303 par1World.setBlockMetadataWithNotify(par2, par3, par4, var8);
304 par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4);
305 }
306 else
307 {
308 par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var8);
309 par1World.markBlocksDirty(par2, par3 - 1, par4, par2, par3, par4);
310 }
311
312 par1World.playAuxSFXAtEntity((EntityPlayer)null, 1003, par2, par3, par4, 0);
313 }
314 }
315
316 /**
317 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
318 * their own) Args: x, y, z, neighbor blockID
319 */
320 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
321 {
322 int var6 = par1World.getBlockMetadata(par2, par3, par4);
323
324 if ((var6 & 8) == 0)
325 {
326 boolean var7 = false;
327
328 if (par1World.getBlockId(par2, par3 + 1, par4) != this.blockID)
329 {
330 par1World.setBlockWithNotify(par2, par3, par4, 0);
331 var7 = true;
332 }
333
334 if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4))
335 {
336 par1World.setBlockWithNotify(par2, par3, par4, 0);
337 var7 = true;
338
339 if (par1World.getBlockId(par2, par3 + 1, par4) == this.blockID)
340 {
341 par1World.setBlockWithNotify(par2, par3 + 1, par4, 0);
342 }
343 }
344
345 if (var7)
346 {
347 if (!par1World.isRemote)
348 {
349 this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
350 }
351 }
352 else
353 {
354 boolean var8 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4) || par1World.isBlockIndirectlyGettingPowered(par2, par3 + 1, par4);
355
356 if ((var8 || par5 > 0 && Block.blocksList[par5].canProvidePower() || par5 == 0) && par5 != this.blockID)
357 {
358 this.onPoweredBlockChange(par1World, par2, par3, par4, var8);
359 }
360 }
361 }
362 else
363 {
364 if (par1World.getBlockId(par2, par3 - 1, par4) != this.blockID)
365 {
366 par1World.setBlockWithNotify(par2, par3, par4, 0);
367 }
368
369 if (par5 > 0 && par5 != this.blockID)
370 {
371 this.onNeighborBlockChange(par1World, par2, par3 - 1, par4, par5);
372 }
373 }
374 }
375
376 /**
377 * Returns the ID of the items to drop on destruction.
378 */
379 public int idDropped(int par1, Random par2Random, int par3)
380 {
381 return (par1 & 8) != 0 ? 0 : (this.blockMaterial == Material.iron ? Item.doorSteel.shiftedIndex : Item.doorWood.shiftedIndex);
382 }
383
384 /**
385 * Ray traces through the blocks collision from start vector to end vector returning a ray trace hit. Args: world,
386 * x, y, z, startVec, endVec
387 */
388 public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3, Vec3 par6Vec3)
389 {
390 this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
391 return super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3);
392 }
393
394 /**
395 * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
396 */
397 public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
398 {
399 return par3 >= 255 ? false : par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && super.canPlaceBlockAt(par1World, par2, par3, par4) && super.canPlaceBlockAt(par1World, par2, par3 + 1, par4);
400 }
401
402 /**
403 * Returns the mobility information of the block, 0 = free, 1 = can't push but can move over, 2 = total immobility
404 * and stop pistons
405 */
406 public int getMobilityFlag()
407 {
408 return 1;
409 }
410
411 /**
412 * Returns the full metadata value created by combining the metadata of both blocks the door takes up.
413 */
414 public int getFullMetadata(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
415 {
416 int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
417 boolean var6 = (var5 & 8) != 0;
418 int var7;
419 int var8;
420
421 if (var6)
422 {
423 var7 = par1IBlockAccess.getBlockMetadata(par2, par3 - 1, par4);
424 var8 = var5;
425 }
426 else
427 {
428 var7 = var5;
429 var8 = par1IBlockAccess.getBlockMetadata(par2, par3 + 1, par4);
430 }
431
432 boolean var9 = (var8 & 1) != 0;
433 return var7 & 7 | (var6 ? 8 : 0) | (var9 ? 16 : 0);
434 }
435
436 @SideOnly(Side.CLIENT)
437
438 /**
439 * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative)
440 */
441 public int idPicked(World par1World, int par2, int par3, int par4)
442 {
443 return this.blockMaterial == Material.iron ? Item.doorSteel.shiftedIndex : Item.doorWood.shiftedIndex;
444 }
445 }