001package net.minecraft.block; 002 003import cpw.mods.fml.relauncher.Side; 004import cpw.mods.fml.relauncher.SideOnly; 005import java.util.List; 006import java.util.Random; 007import net.minecraft.block.material.Material; 008import net.minecraft.client.renderer.texture.IconRegister; 009import net.minecraft.creativetab.CreativeTabs; 010import net.minecraft.entity.Entity; 011import net.minecraft.entity.EntityLiving; 012import net.minecraft.entity.item.EntityItem; 013import net.minecraft.entity.player.EntityPlayer; 014import net.minecraft.inventory.Container; 015import net.minecraft.item.ItemStack; 016import net.minecraft.nbt.NBTTagCompound; 017import net.minecraft.tileentity.TileEntity; 018import net.minecraft.tileentity.TileEntityHopper; 019import net.minecraft.util.AxisAlignedBB; 020import net.minecraft.util.Facing; 021import net.minecraft.util.Icon; 022import net.minecraft.world.IBlockAccess; 023import net.minecraft.world.World; 024 025public class BlockHopper extends BlockContainer 026{ 027 private final Random field_94457_a = new Random(); 028 @SideOnly(Side.CLIENT) 029 private Icon field_94455_b; 030 @SideOnly(Side.CLIENT) 031 private Icon field_94456_c; 032 @SideOnly(Side.CLIENT) 033 private Icon field_94454_cO; 034 035 public BlockHopper(int par1) 036 { 037 super(par1, Material.iron); 038 this.setCreativeTab(CreativeTabs.tabRedstone); 039 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); 040 } 041 042 /** 043 * Updates the blocks bounds based on its current state. Args: world, x, y, z 044 */ 045 public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 046 { 047 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); 048 } 049 050 /** 051 * Adds all intersecting collision boxes to a list. (Be sure to only add boxes to the list if they intersect the 052 * mask.) Parameters: World, X, Y, Z, mask, list, colliding entity 053 */ 054 public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB, List par6List, Entity par7Entity) 055 { 056 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.625F, 1.0F); 057 super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity); 058 float f = 0.125F; 059 this.setBlockBounds(0.0F, 0.0F, 0.0F, f, 1.0F, 1.0F); 060 super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity); 061 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, f); 062 super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity); 063 this.setBlockBounds(1.0F - f, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); 064 super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity); 065 this.setBlockBounds(0.0F, 0.0F, 1.0F - f, 1.0F, 1.0F, 1.0F); 066 super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity); 067 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); 068 } 069 070 /** 071 * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z, side, hitX, hitY, hitZ, block metadata 072 */ 073 public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9) 074 { 075 int j1 = Facing.faceToSide[par5]; 076 077 if (j1 == 1) 078 { 079 j1 = 0; 080 } 081 082 return j1; 083 } 084 085 /** 086 * Returns a new instance of a block's tile entity class. Called on placing the block. 087 */ 088 public TileEntity createNewTileEntity(World par1World) 089 { 090 return new TileEntityHopper(); 091 } 092 093 /** 094 * Called when the block is placed in the world. 095 */ 096 public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving, ItemStack par6ItemStack) 097 { 098 super.onBlockPlacedBy(par1World, par2, par3, par4, par5EntityLiving, par6ItemStack); 099 100 if (par6ItemStack.hasDisplayName()) 101 { 102 TileEntityHopper tileentityhopper = func_98213_d(par1World, par2, par3, par4); 103 tileentityhopper.func_96115_a(par6ItemStack.getDisplayName()); 104 } 105 } 106 107 /** 108 * Called whenever the block is added into the world. Args: world, x, y, z 109 */ 110 public void onBlockAdded(World par1World, int par2, int par3, int par4) 111 { 112 super.onBlockAdded(par1World, par2, par3, par4); 113 this.func_96471_k(par1World, par2, par3, par4); 114 } 115 116 /** 117 * Called upon block activation (right click on the block.) 118 */ 119 public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) 120 { 121 if (par1World.isRemote) 122 { 123 return true; 124 } 125 else 126 { 127 TileEntityHopper tileentityhopper = func_98213_d(par1World, par2, par3, par4); 128 129 if (tileentityhopper != null) 130 { 131 par5EntityPlayer.func_94064_a(tileentityhopper); 132 } 133 134 return true; 135 } 136 } 137 138 /** 139 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 140 * their own) Args: x, y, z, neighbor blockID 141 */ 142 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 143 { 144 this.func_96471_k(par1World, par2, par3, par4); 145 } 146 147 private void func_96471_k(World par1World, int par2, int par3, int par4) 148 { 149 int l = par1World.getBlockMetadata(par2, par3, par4); 150 int i1 = func_94451_c(l); 151 boolean flag = !par1World.isBlockIndirectlyGettingPowered(par2, par3, par4); 152 boolean flag1 = func_94452_d(l); 153 154 if (flag != flag1) 155 { 156 par1World.setBlockMetadataWithNotify(par2, par3, par4, i1 | (flag ? 0 : 8), 4); 157 } 158 } 159 160 /** 161 * ejects contained items into the world, and notifies neighbours of an update, as appropriate 162 */ 163 public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) 164 { 165 TileEntityHopper tileentityhopper = (TileEntityHopper)par1World.getBlockTileEntity(par2, par3, par4); 166 167 if (tileentityhopper != null) 168 { 169 for (int j1 = 0; j1 < tileentityhopper.getSizeInventory(); ++j1) 170 { 171 ItemStack itemstack = tileentityhopper.getStackInSlot(j1); 172 173 if (itemstack != null) 174 { 175 float f = this.field_94457_a.nextFloat() * 0.8F + 0.1F; 176 float f1 = this.field_94457_a.nextFloat() * 0.8F + 0.1F; 177 float f2 = this.field_94457_a.nextFloat() * 0.8F + 0.1F; 178 179 while (itemstack.stackSize > 0) 180 { 181 int k1 = this.field_94457_a.nextInt(21) + 10; 182 183 if (k1 > itemstack.stackSize) 184 { 185 k1 = itemstack.stackSize; 186 } 187 188 itemstack.stackSize -= k1; 189 EntityItem entityitem = new EntityItem(par1World, (double)((float)par2 + f), (double)((float)par3 + f1), (double)((float)par4 + f2), new ItemStack(itemstack.itemID, k1, itemstack.getItemDamage())); 190 191 if (itemstack.hasTagCompound()) 192 { 193 entityitem.getEntityItem().setTagCompound((NBTTagCompound)itemstack.getTagCompound().copy()); 194 } 195 196 float f3 = 0.05F; 197 entityitem.motionX = (double)((float)this.field_94457_a.nextGaussian() * f3); 198 entityitem.motionY = (double)((float)this.field_94457_a.nextGaussian() * f3 + 0.2F); 199 entityitem.motionZ = (double)((float)this.field_94457_a.nextGaussian() * f3); 200 par1World.spawnEntityInWorld(entityitem); 201 } 202 } 203 } 204 } 205 206 super.breakBlock(par1World, par2, par3, par4, par5, par6); 207 } 208 209 /** 210 * The type of render function that is called for this block 211 */ 212 public int getRenderType() 213 { 214 return 38; 215 } 216 217 /** 218 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc) 219 */ 220 public boolean renderAsNormalBlock() 221 { 222 return false; 223 } 224 225 /** 226 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two 227 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block. 228 */ 229 public boolean isOpaqueCube() 230 { 231 return false; 232 } 233 234 public static int func_94451_c(int par0) 235 { 236 return par0 & 7; 237 } 238 239 @SideOnly(Side.CLIENT) 240 241 /** 242 * Returns true if the given side of this block type should be rendered, if the adjacent block is at the given 243 * coordinates. Args: blockAccess, x, y, z, side 244 */ 245 public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 246 { 247 return true; 248 } 249 250 @SideOnly(Side.CLIENT) 251 252 /** 253 * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata 254 */ 255 public Icon getBlockTextureFromSideAndMetadata(int par1, int par2) 256 { 257 return par1 == 1 ? this.field_94456_c : this.field_94455_b; 258 } 259 260 public static boolean func_94452_d(int par0) 261 { 262 return (par0 & 8) != 8; 263 } 264 265 public boolean func_96468_q_() 266 { 267 return true; 268 } 269 270 public int func_94328_b_(World par1World, int par2, int par3, int par4, int par5) 271 { 272 return Container.func_94526_b(func_98213_d(par1World, par2, par3, par4)); 273 } 274 275 @SideOnly(Side.CLIENT) 276 public void func_94332_a(IconRegister par1IconRegister) 277 { 278 this.field_94455_b = par1IconRegister.func_94245_a("hopper"); 279 this.field_94456_c = par1IconRegister.func_94245_a("hopper_top"); 280 this.field_94454_cO = par1IconRegister.func_94245_a("hopper_inside"); 281 } 282 283 @SideOnly(Side.CLIENT) 284 public static Icon func_94453_b(String par0Str) 285 { 286 return par0Str == "hopper" ? Block.field_94340_cs.field_94455_b : (par0Str == "hopper_inside" ? Block.field_94340_cs.field_94454_cO : null); 287 } 288 289 @SideOnly(Side.CLIENT) 290 public String func_94327_t_() 291 { 292 return "hopper"; 293 } 294 295 public static TileEntityHopper func_98213_d(IBlockAccess par0IBlockAccess, int par1, int par2, int par3) 296 { 297 return (TileEntityHopper)par0IBlockAccess.getBlockTileEntity(par1, par2, par3); 298 } 299}