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.creativetab.CreativeTabs; 008 import net.minecraft.entity.Entity; 009 import net.minecraft.util.AxisAlignedBB; 010 import net.minecraft.util.DamageSource; 011 import net.minecraft.world.World; 012 013 import net.minecraftforge.common.EnumPlantType; 014 import net.minecraftforge.common.ForgeDirection; 015 import net.minecraftforge.common.IPlantable; 016 017 public class BlockCactus extends Block implements IPlantable 018 { 019 protected BlockCactus(int par1, int par2) 020 { 021 super(par1, par2, Material.cactus); 022 this.setTickRandomly(true); 023 this.setCreativeTab(CreativeTabs.tabDecorations); 024 } 025 026 /** 027 * Ticks the block if it's been scheduled 028 */ 029 public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) 030 { 031 if (par1World.isAirBlock(par2, par3 + 1, par4)) 032 { 033 int var6; 034 035 for (var6 = 1; par1World.getBlockId(par2, par3 - var6, par4) == this.blockID; ++var6) 036 { 037 ; 038 } 039 040 if (var6 < 3) 041 { 042 int var7 = par1World.getBlockMetadata(par2, par3, par4); 043 044 if (var7 == 15) 045 { 046 par1World.setBlockWithNotify(par2, par3 + 1, par4, this.blockID); 047 par1World.setBlockMetadataWithNotify(par2, par3, par4, 0); 048 } 049 else 050 { 051 par1World.setBlockMetadataWithNotify(par2, par3, par4, var7 + 1); 052 } 053 } 054 } 055 } 056 057 /** 058 * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been 059 * cleared to be reused) 060 */ 061 public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) 062 { 063 float var5 = 0.0625F; 064 return AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)((float)par2 + var5), (double)par3, (double)((float)par4 + var5), (double)((float)(par2 + 1) - var5), (double)((float)(par3 + 1) - var5), (double)((float)(par4 + 1) - var5)); 065 } 066 067 @SideOnly(Side.CLIENT) 068 069 /** 070 * Returns the bounding box of the wired rectangular prism to render. 071 */ 072 public AxisAlignedBB getSelectedBoundingBoxFromPool(World par1World, int par2, int par3, int par4) 073 { 074 float var5 = 0.0625F; 075 return AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)((float)par2 + var5), (double)par3, (double)((float)par4 + var5), (double)((float)(par2 + 1) - var5), (double)(par3 + 1), (double)((float)(par4 + 1) - var5)); 076 } 077 078 /** 079 * Returns the block texture based on the side being looked at. Args: side 080 */ 081 public int getBlockTextureFromSide(int par1) 082 { 083 return par1 == 1 ? this.blockIndexInTexture - 1 : (par1 == 0 ? this.blockIndexInTexture + 1 : this.blockIndexInTexture); 084 } 085 086 /** 087 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc) 088 */ 089 public boolean renderAsNormalBlock() 090 { 091 return false; 092 } 093 094 /** 095 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two 096 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block. 097 */ 098 public boolean isOpaqueCube() 099 { 100 return false; 101 } 102 103 /** 104 * The type of render function that is called for this block 105 */ 106 public int getRenderType() 107 { 108 return 13; 109 } 110 111 /** 112 * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z 113 */ 114 public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) 115 { 116 return !super.canPlaceBlockAt(par1World, par2, par3, par4) ? false : this.canBlockStay(par1World, par2, par3, par4); 117 } 118 119 /** 120 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 121 * their own) Args: x, y, z, neighbor blockID 122 */ 123 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 124 { 125 if (!this.canBlockStay(par1World, par2, par3, par4)) 126 { 127 this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0); 128 par1World.setBlockWithNotify(par2, par3, par4, 0); 129 } 130 } 131 132 /** 133 * Can this block stay at this position. Similar to canPlaceBlockAt except gets checked often with plants. 134 */ 135 public boolean canBlockStay(World par1World, int par2, int par3, int par4) 136 { 137 if (par1World.getBlockMaterial(par2 - 1, par3, par4).isSolid()) 138 { 139 return false; 140 } 141 else if (par1World.getBlockMaterial(par2 + 1, par3, par4).isSolid()) 142 { 143 return false; 144 } 145 else if (par1World.getBlockMaterial(par2, par3, par4 - 1).isSolid()) 146 { 147 return false; 148 } 149 else if (par1World.getBlockMaterial(par2, par3, par4 + 1).isSolid()) 150 { 151 return false; 152 } 153 else 154 { 155 int var5 = par1World.getBlockId(par2, par3 - 1, par4); 156 return blocksList[var5] != null && blocksList[var5].canSustainPlant(par1World, par2, par3 - 1, par4, ForgeDirection.UP, this); 157 } 158 } 159 160 /** 161 * Triggered whenever an entity collides with this block (enters into the block). Args: world, x, y, z, entity 162 */ 163 public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) 164 { 165 par5Entity.attackEntityFrom(DamageSource.cactus, 1); 166 } 167 168 @Override 169 public EnumPlantType getPlantType(World world, int x, int y, int z) 170 { 171 return EnumPlantType.Desert; 172 } 173 174 @Override 175 public int getPlantID(World world, int x, int y, int z) 176 { 177 return blockID; 178 } 179 180 @Override 181 public int getPlantMetadata(World world, int x, int y, int z) 182 { 183 return -1; 184 } 185 }