001 package net.minecraft.src; 002 003 import cpw.mods.fml.common.Side; 004 import cpw.mods.fml.common.asm.SideOnly; 005 006 import java.util.ArrayList; 007 import java.util.Random; 008 009 import net.minecraftforge.common.IShearable; 010 011 public class BlockVine extends Block implements IShearable 012 { 013 public BlockVine(int par1) 014 { 015 super(par1, 143, Material.vine); 016 this.setTickRandomly(true); 017 this.setCreativeTab(CreativeTabs.tabDecorations); 018 } 019 020 /** 021 * Sets the block's bounds for rendering it as an item 022 */ 023 public void setBlockBoundsForItemRender() 024 { 025 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); 026 } 027 028 /** 029 * The type of render function that is called for this block 030 */ 031 public int getRenderType() 032 { 033 return 20; 034 } 035 036 /** 037 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two 038 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block. 039 */ 040 public boolean isOpaqueCube() 041 { 042 return false; 043 } 044 045 /** 046 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc) 047 */ 048 public boolean renderAsNormalBlock() 049 { 050 return false; 051 } 052 053 /** 054 * Updates the blocks bounds based on its current state. Args: world, x, y, z 055 */ 056 public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 057 { 058 int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4); 059 float var7 = 1.0F; 060 float var8 = 1.0F; 061 float var9 = 1.0F; 062 float var10 = 0.0F; 063 float var11 = 0.0F; 064 float var12 = 0.0F; 065 boolean var13 = var6 > 0; 066 067 if ((var6 & 2) != 0) 068 { 069 var10 = Math.max(var10, 0.0625F); 070 var7 = 0.0F; 071 var8 = 0.0F; 072 var11 = 1.0F; 073 var9 = 0.0F; 074 var12 = 1.0F; 075 var13 = true; 076 } 077 078 if ((var6 & 8) != 0) 079 { 080 var7 = Math.min(var7, 0.9375F); 081 var10 = 1.0F; 082 var8 = 0.0F; 083 var11 = 1.0F; 084 var9 = 0.0F; 085 var12 = 1.0F; 086 var13 = true; 087 } 088 089 if ((var6 & 4) != 0) 090 { 091 var12 = Math.max(var12, 0.0625F); 092 var9 = 0.0F; 093 var7 = 0.0F; 094 var10 = 1.0F; 095 var8 = 0.0F; 096 var11 = 1.0F; 097 var13 = true; 098 } 099 100 if ((var6 & 1) != 0) 101 { 102 var9 = Math.min(var9, 0.9375F); 103 var12 = 1.0F; 104 var7 = 0.0F; 105 var10 = 1.0F; 106 var8 = 0.0F; 107 var11 = 1.0F; 108 var13 = true; 109 } 110 111 if (!var13 && this.canBePlacedOn(par1IBlockAccess.getBlockId(par2, par3 + 1, par4))) 112 { 113 var8 = Math.min(var8, 0.9375F); 114 var11 = 1.0F; 115 var7 = 0.0F; 116 var10 = 1.0F; 117 var9 = 0.0F; 118 var12 = 1.0F; 119 } 120 121 this.setBlockBounds(var7, var8, var9, var10, var11, var12); 122 } 123 124 /** 125 * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been 126 * cleared to be reused) 127 */ 128 public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) 129 { 130 return null; 131 } 132 133 /** 134 * checks to see if you can place this block can be placed on that side of a block: BlockLever overrides 135 */ 136 public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5) 137 { 138 switch (par5) 139 { 140 case 1: 141 return this.canBePlacedOn(par1World.getBlockId(par2, par3 + 1, par4)); 142 case 2: 143 return this.canBePlacedOn(par1World.getBlockId(par2, par3, par4 + 1)); 144 case 3: 145 return this.canBePlacedOn(par1World.getBlockId(par2, par3, par4 - 1)); 146 case 4: 147 return this.canBePlacedOn(par1World.getBlockId(par2 + 1, par3, par4)); 148 case 5: 149 return this.canBePlacedOn(par1World.getBlockId(par2 - 1, par3, par4)); 150 default: 151 return false; 152 } 153 } 154 155 /** 156 * returns true if a vine can be placed on that block (checks for render as normal block and if it is solid) 157 */ 158 private boolean canBePlacedOn(int par1) 159 { 160 if (par1 == 0) 161 { 162 return false; 163 } 164 else 165 { 166 Block var2 = Block.blocksList[par1]; 167 return var2.renderAsNormalBlock() && var2.blockMaterial.blocksMovement(); 168 } 169 } 170 171 /** 172 * Returns if the vine can stay in the world. It also changes the metadata according to neighboring blocks. 173 */ 174 private boolean canVineStay(World par1World, int par2, int par3, int par4) 175 { 176 int var5 = par1World.getBlockMetadata(par2, par3, par4); 177 int var6 = var5; 178 179 if (var5 > 0) 180 { 181 for (int var7 = 0; var7 <= 3; ++var7) 182 { 183 int var8 = 1 << var7; 184 185 if ((var5 & var8) != 0 && !this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var7], par3, par4 + Direction.offsetZ[var7])) && (par1World.getBlockId(par2, par3 + 1, par4) != this.blockID || (par1World.getBlockMetadata(par2, par3 + 1, par4) & var8) == 0)) 186 { 187 var6 &= ~var8; 188 } 189 } 190 } 191 192 if (var6 == 0 && !this.canBePlacedOn(par1World.getBlockId(par2, par3 + 1, par4))) 193 { 194 return false; 195 } 196 else 197 { 198 if (var6 != var5) 199 { 200 par1World.setBlockMetadataWithNotify(par2, par3, par4, var6); 201 } 202 203 return true; 204 } 205 } 206 207 @SideOnly(Side.CLIENT) 208 public int getBlockColor() 209 { 210 return ColorizerFoliage.getFoliageColorBasic(); 211 } 212 213 @SideOnly(Side.CLIENT) 214 215 /** 216 * Returns the color this block should be rendered. Used by leaves. 217 */ 218 public int getRenderColor(int par1) 219 { 220 return ColorizerFoliage.getFoliageColorBasic(); 221 } 222 223 @SideOnly(Side.CLIENT) 224 225 /** 226 * Returns a integer with hex for 0xrrggbb with this color multiplied against the blocks color. Note only called 227 * when first determining what to render. 228 */ 229 public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 230 { 231 return par1IBlockAccess.getBiomeGenForCoords(par2, par4).getBiomeFoliageColor(); 232 } 233 234 /** 235 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 236 * their own) Args: x, y, z, neighbor blockID 237 */ 238 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 239 { 240 if (!par1World.isRemote && !this.canVineStay(par1World, par2, par3, par4)) 241 { 242 this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0); 243 par1World.setBlockWithNotify(par2, par3, par4, 0); 244 } 245 } 246 247 /** 248 * Ticks the block if it's been scheduled 249 */ 250 public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) 251 { 252 if (!par1World.isRemote && par1World.rand.nextInt(4) == 0) 253 { 254 byte var6 = 4; 255 int var7 = 5; 256 boolean var8 = false; 257 int var9; 258 int var10; 259 int var11; 260 label138: 261 262 for (var9 = par2 - var6; var9 <= par2 + var6; ++var9) 263 { 264 for (var10 = par4 - var6; var10 <= par4 + var6; ++var10) 265 { 266 for (var11 = par3 - 1; var11 <= par3 + 1; ++var11) 267 { 268 if (par1World.getBlockId(var9, var11, var10) == this.blockID) 269 { 270 --var7; 271 272 if (var7 <= 0) 273 { 274 var8 = true; 275 break label138; 276 } 277 } 278 } 279 } 280 } 281 282 var9 = par1World.getBlockMetadata(par2, par3, par4); 283 var10 = par1World.rand.nextInt(6); 284 var11 = Direction.vineGrowth[var10]; 285 int var12; 286 int var13; 287 288 if (var10 == 1 && par3 < 255 && par1World.isAirBlock(par2, par3 + 1, par4)) 289 { 290 if (var8) 291 { 292 return; 293 } 294 295 var12 = par1World.rand.nextInt(16) & var9; 296 297 if (var12 > 0) 298 { 299 for (var13 = 0; var13 <= 3; ++var13) 300 { 301 if (!this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var13], par3 + 1, par4 + Direction.offsetZ[var13]))) 302 { 303 var12 &= ~(1 << var13); 304 } 305 } 306 307 if (var12 > 0) 308 { 309 par1World.setBlockAndMetadataWithNotify(par2, par3 + 1, par4, this.blockID, var12); 310 } 311 } 312 } 313 else 314 { 315 int var14; 316 317 if (var10 >= 2 && var10 <= 5 && (var9 & 1 << var11) == 0) 318 { 319 if (var8) 320 { 321 return; 322 } 323 324 var12 = par1World.getBlockId(par2 + Direction.offsetX[var11], par3, par4 + Direction.offsetZ[var11]); 325 326 if (var12 != 0 && Block.blocksList[var12] != null) 327 { 328 if (Block.blocksList[var12].blockMaterial.isOpaque() && Block.blocksList[var12].renderAsNormalBlock()) 329 { 330 par1World.setBlockMetadataWithNotify(par2, par3, par4, var9 | 1 << var11); 331 } 332 } 333 else 334 { 335 var13 = var11 + 1 & 3; 336 var14 = var11 + 3 & 3; 337 338 if ((var9 & 1 << var13) != 0 && this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var11] + Direction.offsetX[var13], par3, par4 + Direction.offsetZ[var11] + Direction.offsetZ[var13]))) 339 { 340 par1World.setBlockAndMetadataWithNotify(par2 + Direction.offsetX[var11], par3, par4 + Direction.offsetZ[var11], this.blockID, 1 << var13); 341 } 342 else if ((var9 & 1 << var14) != 0 && this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var11] + Direction.offsetX[var14], par3, par4 + Direction.offsetZ[var11] + Direction.offsetZ[var14]))) 343 { 344 par1World.setBlockAndMetadataWithNotify(par2 + Direction.offsetX[var11], par3, par4 + Direction.offsetZ[var11], this.blockID, 1 << var14); 345 } 346 else if ((var9 & 1 << var13) != 0 && par1World.isAirBlock(par2 + Direction.offsetX[var11] + Direction.offsetX[var13], par3, par4 + Direction.offsetZ[var11] + Direction.offsetZ[var13]) && this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var13], par3, par4 + Direction.offsetZ[var13]))) 347 { 348 par1World.setBlockAndMetadataWithNotify(par2 + Direction.offsetX[var11] + Direction.offsetX[var13], par3, par4 + Direction.offsetZ[var11] + Direction.offsetZ[var13], this.blockID, 1 << (var11 + 2 & 3)); 349 } 350 else if ((var9 & 1 << var14) != 0 && par1World.isAirBlock(par2 + Direction.offsetX[var11] + Direction.offsetX[var14], par3, par4 + Direction.offsetZ[var11] + Direction.offsetZ[var14]) && this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var14], par3, par4 + Direction.offsetZ[var14]))) 351 { 352 par1World.setBlockAndMetadataWithNotify(par2 + Direction.offsetX[var11] + Direction.offsetX[var14], par3, par4 + Direction.offsetZ[var11] + Direction.offsetZ[var14], this.blockID, 1 << (var11 + 2 & 3)); 353 } 354 else if (this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var11], par3 + 1, par4 + Direction.offsetZ[var11]))) 355 { 356 par1World.setBlockAndMetadataWithNotify(par2 + Direction.offsetX[var11], par3, par4 + Direction.offsetZ[var11], this.blockID, 0); 357 } 358 } 359 } 360 else if (par3 > 1) 361 { 362 var12 = par1World.getBlockId(par2, par3 - 1, par4); 363 364 if (var12 == 0) 365 { 366 var13 = par1World.rand.nextInt(16) & var9; 367 368 if (var13 > 0) 369 { 370 par1World.setBlockAndMetadataWithNotify(par2, par3 - 1, par4, this.blockID, var13); 371 } 372 } 373 else if (var12 == this.blockID) 374 { 375 var13 = par1World.rand.nextInt(16) & var9; 376 var14 = par1World.getBlockMetadata(par2, par3 - 1, par4); 377 378 if (var14 != (var14 | var13)) 379 { 380 par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var14 | var13); 381 } 382 } 383 } 384 } 385 } 386 } 387 388 public int func_85104_a(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9) 389 { 390 byte var10 = 0; 391 392 switch (par5) 393 { 394 case 2: 395 var10 = 1; 396 break; 397 case 3: 398 var10 = 4; 399 break; 400 case 4: 401 var10 = 8; 402 break; 403 case 5: 404 var10 = 2; 405 } 406 407 return var10 != 0 ? var10 : par9; 408 } 409 410 /** 411 * Returns the ID of the items to drop on destruction. 412 */ 413 public int idDropped(int par1, Random par2Random, int par3) 414 { 415 return 0; 416 } 417 418 /** 419 * Returns the quantity of items to drop on block destruction. 420 */ 421 public int quantityDropped(Random par1Random) 422 { 423 return 0; 424 } 425 426 /** 427 * Called when the player destroys a block with an item that can harvest it. (i, j, k) are the coordinates of the 428 * block and l is the block's subtype/damage. 429 */ 430 public void harvestBlock(World par1World, EntityPlayer par2EntityPlayer, int par3, int par4, int par5, int par6) 431 { 432 super.harvestBlock(par1World, par2EntityPlayer, par3, par4, par5, par6); 433 } 434 435 @Override 436 public boolean isShearable(ItemStack item, World world, int x, int y, int z) 437 { 438 return true; 439 } 440 441 @Override 442 public ArrayList<ItemStack> onSheared(ItemStack item, World world, int x, int y, int z, int fortune) 443 { 444 ArrayList<ItemStack> ret = new ArrayList<ItemStack>(); 445 ret.add(new ItemStack(this, 1, 0)); 446 return ret; 447 } 448 449 @Override 450 public boolean isLadder(World world, int x, int y, int z) 451 { 452 return true; 453 } 454 }