001 package net.minecraft.src; 002 003 import cpw.mods.fml.common.Side; 004 import cpw.mods.fml.common.asm.SideOnly; 005 import cpw.mods.fml.common.registry.GameRegistry; 006 007 import java.util.Random; 008 009 public class BlockDispenser extends BlockContainer 010 { 011 /** Registry for all dispense behaviors. */ 012 public static final IRegistry dispenseBehaviorRegistry = new RegistryDefaulted(new BehaviorDefaultDispenseItem()); 013 private Random random = new Random(); 014 015 protected BlockDispenser(int par1) 016 { 017 super(par1, Material.rock); 018 this.blockIndexInTexture = 45; 019 this.setCreativeTab(CreativeTabs.tabRedstone); 020 } 021 022 /** 023 * How many world ticks before ticking 024 */ 025 public int tickRate() 026 { 027 return 4; 028 } 029 030 /** 031 * Returns the ID of the items to drop on destruction. 032 */ 033 public int idDropped(int par1, Random par2Random, int par3) 034 { 035 return Block.dispenser.blockID; 036 } 037 038 /** 039 * Called whenever the block is added into the world. Args: world, x, y, z 040 */ 041 public void onBlockAdded(World par1World, int par2, int par3, int par4) 042 { 043 super.onBlockAdded(par1World, par2, par3, par4); 044 this.setDispenserDefaultDirection(par1World, par2, par3, par4); 045 } 046 047 /** 048 * sets Dispenser block direction so that the front faces an non-opaque block; chooses west to be direction if all 049 * surrounding blocks are opaque. 050 */ 051 private void setDispenserDefaultDirection(World par1World, int par2, int par3, int par4) 052 { 053 if (!par1World.isRemote) 054 { 055 int var5 = par1World.getBlockId(par2, par3, par4 - 1); 056 int var6 = par1World.getBlockId(par2, par3, par4 + 1); 057 int var7 = par1World.getBlockId(par2 - 1, par3, par4); 058 int var8 = par1World.getBlockId(par2 + 1, par3, par4); 059 byte var9 = 3; 060 061 if (Block.opaqueCubeLookup[var5] && !Block.opaqueCubeLookup[var6]) 062 { 063 var9 = 3; 064 } 065 066 if (Block.opaqueCubeLookup[var6] && !Block.opaqueCubeLookup[var5]) 067 { 068 var9 = 2; 069 } 070 071 if (Block.opaqueCubeLookup[var7] && !Block.opaqueCubeLookup[var8]) 072 { 073 var9 = 5; 074 } 075 076 if (Block.opaqueCubeLookup[var8] && !Block.opaqueCubeLookup[var7]) 077 { 078 var9 = 4; 079 } 080 081 par1World.setBlockMetadataWithNotify(par2, par3, par4, var9); 082 } 083 } 084 085 @SideOnly(Side.CLIENT) 086 087 /** 088 * Retrieves the block texture to use based on the display side. Args: iBlockAccess, x, y, z, side 089 */ 090 public int getBlockTexture(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 091 { 092 if (par5 == 1) 093 { 094 return this.blockIndexInTexture + 17; 095 } 096 else if (par5 == 0) 097 { 098 return this.blockIndexInTexture + 17; 099 } 100 else 101 { 102 int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4); 103 return par5 == var6 ? this.blockIndexInTexture + 1 : this.blockIndexInTexture; 104 } 105 } 106 107 /** 108 * Returns the block texture based on the side being looked at. Args: side 109 */ 110 public int getBlockTextureFromSide(int par1) 111 { 112 return par1 == 1 ? this.blockIndexInTexture + 17 : (par1 == 0 ? this.blockIndexInTexture + 17 : (par1 == 3 ? this.blockIndexInTexture + 1 : this.blockIndexInTexture)); 113 } 114 115 /** 116 * Called upon block activation (right click on the block.) 117 */ 118 public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) 119 { 120 if (par1World.isRemote) 121 { 122 return true; 123 } 124 else 125 { 126 TileEntityDispenser var10 = (TileEntityDispenser)par1World.getBlockTileEntity(par2, par3, par4); 127 128 if (var10 != null) 129 { 130 par5EntityPlayer.displayGUIDispenser(var10); 131 } 132 133 return true; 134 } 135 } 136 137 private void dispense(World par1World, int par2, int par3, int par4) 138 { 139 BlockSourceImpl var5 = new BlockSourceImpl(par1World, par2, par3, par4); 140 TileEntityDispenser var6 = (TileEntityDispenser)var5.func_82619_j(); 141 142 if (var6 != null) 143 { 144 int var7 = var6.getRandomStackFromInventory(); 145 146 if (var7 < 0) 147 { 148 par1World.playAuxSFX(1001, par2, par3, par4, 0); 149 } 150 else 151 { 152 ItemStack var8 = var6.getStackInSlot(var7); 153 IBehaviorDispenseItem var9 = (IBehaviorDispenseItem)dispenseBehaviorRegistry.func_82594_a(var8.getItem()); 154 155 if (var9 != IBehaviorDispenseItem.itemDispenseBehaviorProvider) 156 { 157 ItemStack var10 = var9.dispense(var5, var8); 158 var6.setInventorySlotContents(var7, var10.stackSize == 0 ? null : var10); 159 } 160 } 161 } 162 } 163 164 /** 165 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 166 * their own) Args: x, y, z, neighbor blockID 167 */ 168 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 169 { 170 if (par5 > 0 && Block.blocksList[par5].canProvidePower()) 171 { 172 boolean var6 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4) || par1World.isBlockIndirectlyGettingPowered(par2, par3 + 1, par4); 173 174 if (var6) 175 { 176 par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate()); 177 } 178 } 179 } 180 181 /** 182 * Ticks the block if it's been scheduled 183 */ 184 public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) 185 { 186 if (!par1World.isRemote && (par1World.isBlockIndirectlyGettingPowered(par2, par3, par4) || par1World.isBlockIndirectlyGettingPowered(par2, par3 + 1, par4))) 187 { 188 this.dispense(par1World, par2, par3, par4); 189 } 190 } 191 192 /** 193 * Returns a new instance of a block's tile entity class. Called on placing the block. 194 */ 195 public TileEntity createNewTileEntity(World par1World) 196 { 197 return new TileEntityDispenser(); 198 } 199 200 /** 201 * Called when the block is placed in the world. 202 */ 203 public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving) 204 { 205 int var6 = MathHelper.floor_double((double)(par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3; 206 207 if (var6 == 0) 208 { 209 par1World.setBlockMetadataWithNotify(par2, par3, par4, 2); 210 } 211 212 if (var6 == 1) 213 { 214 par1World.setBlockMetadataWithNotify(par2, par3, par4, 5); 215 } 216 217 if (var6 == 2) 218 { 219 par1World.setBlockMetadataWithNotify(par2, par3, par4, 3); 220 } 221 222 if (var6 == 3) 223 { 224 par1World.setBlockMetadataWithNotify(par2, par3, par4, 4); 225 } 226 } 227 228 /** 229 * ejects contained items into the world, and notifies neighbours of an update, as appropriate 230 */ 231 public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) 232 { 233 TileEntityDispenser var7 = (TileEntityDispenser)par1World.getBlockTileEntity(par2, par3, par4); 234 235 if (var7 != null) 236 { 237 for (int var8 = 0; var8 < var7.getSizeInventory(); ++var8) 238 { 239 ItemStack var9 = var7.getStackInSlot(var8); 240 241 if (var9 != null) 242 { 243 float var10 = this.random.nextFloat() * 0.8F + 0.1F; 244 float var11 = this.random.nextFloat() * 0.8F + 0.1F; 245 float var12 = this.random.nextFloat() * 0.8F + 0.1F; 246 247 while (var9.stackSize > 0) 248 { 249 int var13 = this.random.nextInt(21) + 10; 250 251 if (var13 > var9.stackSize) 252 { 253 var13 = var9.stackSize; 254 } 255 256 var9.stackSize -= var13; 257 EntityItem var14 = new EntityItem(par1World, (double)((float)par2 + var10), (double)((float)par3 + var11), (double)((float)par4 + var12), new ItemStack(var9.itemID, var13, var9.getItemDamage())); 258 259 if (var9.hasTagCompound()) 260 { 261 var14.item.setTagCompound((NBTTagCompound)var9.getTagCompound().copy()); 262 } 263 264 float var15 = 0.05F; 265 var14.motionX = (double)((float)this.random.nextGaussian() * var15); 266 var14.motionY = (double)((float)this.random.nextGaussian() * var15 + 0.2F); 267 var14.motionZ = (double)((float)this.random.nextGaussian() * var15); 268 par1World.spawnEntityInWorld(var14); 269 } 270 } 271 } 272 } 273 274 super.breakBlock(par1World, par2, par3, par4, par5, par6); 275 } 276 277 public static IPosition func_82525_a(IBlockSource par0IBlockSource) 278 { 279 EnumFacing var1 = EnumFacing.func_82600_a(par0IBlockSource.func_82620_h()); 280 double var2 = par0IBlockSource.getX() + 0.6D * (double)var1.func_82601_c(); 281 double var4 = par0IBlockSource.getY(); 282 double var6 = par0IBlockSource.getZ() + 0.6D * (double)var1.func_82599_e(); 283 return new PositionImpl(var2, var4, var6); 284 } 285 }