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 /**
389 * called before onBlockPlacedBy by ItemBlock and ItemReed
390 */
391 public void updateBlockMetadata(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8)
392 {
393 byte var9 = 0;
394
395 switch (par5)
396 {
397 case 2:
398 var9 = 1;
399 break;
400 case 3:
401 var9 = 4;
402 break;
403 case 4:
404 var9 = 8;
405 break;
406 case 5:
407 var9 = 2;
408 }
409
410 if (var9 != 0)
411 {
412 par1World.setBlockMetadataWithNotify(par2, par3, par4, var9);
413 }
414 }
415
416 /**
417 * Returns the ID of the items to drop on destruction.
418 */
419 public int idDropped(int par1, Random par2Random, int par3)
420 {
421 return 0;
422 }
423
424 /**
425 * Returns the quantity of items to drop on block destruction.
426 */
427 public int quantityDropped(Random par1Random)
428 {
429 return 0;
430 }
431
432 /**
433 * Called when the player destroys a block with an item that can harvest it. (i, j, k) are the coordinates of the
434 * block and l is the block's subtype/damage.
435 */
436 public void harvestBlock(World par1World, EntityPlayer par2EntityPlayer, int par3, int par4, int par5, int par6)
437 {
438 super.harvestBlock(par1World, par2EntityPlayer, par3, par4, par5, par6);
439 }
440
441 @Override
442 public boolean isShearable(ItemStack item, World world, int x, int y, int z)
443 {
444 return true;
445 }
446
447 @Override
448 public ArrayList<ItemStack> onSheared(ItemStack item, World world, int x, int y, int z, int fortune)
449 {
450 ArrayList<ItemStack> ret = new ArrayList<ItemStack>();
451 ret.add(new ItemStack(this, 1, 0));
452 return ret;
453 }
454
455 @Override
456 public boolean isLadder(World world, int x, int y, int z)
457 {
458 return true;
459 }
460 }