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