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 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 /** 136 * dispenses an item from a randomly selected item stack from the blocks inventory into the game world. 137 */ 138 private void dispenseItem(World par1World, int par2, int par3, int par4, Random par5Random) 139 { 140 int var6 = par1World.getBlockMetadata(par2, par3, par4); 141 byte var9 = 0; 142 byte var10 = 0; 143 144 if (var6 == 3) 145 { 146 var10 = 1; 147 } 148 else if (var6 == 2) 149 { 150 var10 = -1; 151 } 152 else if (var6 == 5) 153 { 154 var9 = 1; 155 } 156 else 157 { 158 var9 = -1; 159 } 160 161 TileEntityDispenser var11 = (TileEntityDispenser)par1World.getBlockTileEntity(par2, par3, par4); 162 163 if (var11 != null) 164 { 165 int var12 = var11.func_70361_i(); 166 167 if (var12 < 0) 168 { 169 par1World.playAuxSFX(1001, par2, par3, par4, 0); 170 } 171 else 172 { 173 double var13 = (double)par2 + (double)var9 * 0.6D + 0.5D; 174 double var15 = (double)par3 + 0.5D; 175 double var17 = (double)par4 + (double)var10 * 0.6D + 0.5D; 176 ItemStack var19 = var11.getStackInSlot(var12); 177 int var20 = spawnEntityWithAction(var11, par1World, var19, par5Random, par2, par3, par4, var9, var10, var13, var15, var17); 178 179 if (var20 == 1) 180 { 181 var11.decrStackSize(var12, 1); 182 } 183 else if (var20 == 0) 184 { 185 var19 = var11.decrStackSize(var12, 1); 186 dispenseEntityFromStack(par1World, var19, par5Random, 6, var9, var10, var13, var15, var17); 187 par1World.playAuxSFX(1000, par2, par3, par4, 0); 188 } 189 190 par1World.playAuxSFX(2000, par2, par3, par4, var9 + 1 + (var10 + 1) * 3); 191 } 192 } 193 } 194 195 /** 196 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 197 * their own) Args: x, y, z, neighbor blockID 198 */ 199 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 200 { 201 if (par5 > 0 && Block.blocksList[par5].canProvidePower()) 202 { 203 boolean var6 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4) || par1World.isBlockIndirectlyGettingPowered(par2, par3 + 1, par4); 204 205 if (var6) 206 { 207 par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate()); 208 } 209 } 210 } 211 212 /** 213 * Ticks the block if it's been scheduled 214 */ 215 public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) 216 { 217 if (!par1World.isRemote && (par1World.isBlockIndirectlyGettingPowered(par2, par3, par4) || par1World.isBlockIndirectlyGettingPowered(par2, par3 + 1, par4))) 218 { 219 this.dispenseItem(par1World, par2, par3, par4, par5Random); 220 } 221 } 222 223 /** 224 * each class overrdies this to return a new <className> 225 */ 226 public TileEntity createNewTileEntity(World par1World) 227 { 228 return new TileEntityDispenser(); 229 } 230 231 /** 232 * Called when the block is placed in the world. 233 */ 234 public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving) 235 { 236 int var6 = MathHelper.floor_double((double)(par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3; 237 238 if (var6 == 0) 239 { 240 par1World.setBlockMetadataWithNotify(par2, par3, par4, 2); 241 } 242 243 if (var6 == 1) 244 { 245 par1World.setBlockMetadataWithNotify(par2, par3, par4, 5); 246 } 247 248 if (var6 == 2) 249 { 250 par1World.setBlockMetadataWithNotify(par2, par3, par4, 3); 251 } 252 253 if (var6 == 3) 254 { 255 par1World.setBlockMetadataWithNotify(par2, par3, par4, 4); 256 } 257 } 258 259 /** 260 * ejects contained items into the world, and notifies neighbours of an update, as appropriate 261 */ 262 public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) 263 { 264 TileEntityDispenser var7 = (TileEntityDispenser)par1World.getBlockTileEntity(par2, par3, par4); 265 266 if (var7 != null) 267 { 268 for (int var8 = 0; var8 < var7.getSizeInventory(); ++var8) 269 { 270 ItemStack var9 = var7.getStackInSlot(var8); 271 272 if (var9 != null) 273 { 274 float var10 = this.random.nextFloat() * 0.8F + 0.1F; 275 float var11 = this.random.nextFloat() * 0.8F + 0.1F; 276 float var12 = this.random.nextFloat() * 0.8F + 0.1F; 277 278 while (var9.stackSize > 0) 279 { 280 int var13 = this.random.nextInt(21) + 10; 281 282 if (var13 > var9.stackSize) 283 { 284 var13 = var9.stackSize; 285 } 286 287 var9.stackSize -= var13; 288 EntityItem var14 = new EntityItem(par1World, (double)((float)par2 + var10), (double)((float)par3 + var11), (double)((float)par4 + var12), new ItemStack(var9.itemID, var13, var9.getItemDamage())); 289 290 if (var9.hasTagCompound()) 291 { 292 var14.item.setTagCompound((NBTTagCompound)var9.getTagCompound().copy()); 293 } 294 295 float var15 = 0.05F; 296 var14.motionX = (double)((float)this.random.nextGaussian() * var15); 297 var14.motionY = (double)((float)this.random.nextGaussian() * var15 + 0.2F); 298 var14.motionZ = (double)((float)this.random.nextGaussian() * var15); 299 par1World.spawnEntityInWorld(var14); 300 } 301 } 302 } 303 } 304 305 super.breakBlock(par1World, par2, par3, par4, par5, par6); 306 } 307 308 private static void dispenseEntityFromStack(World par0World, ItemStack par1ItemStack, Random par2Random, int par3, int par4, int par5, double par6, double par8, double par10) 309 { 310 EntityItem var12 = new EntityItem(par0World, par6, par8 - 0.3D, par10, par1ItemStack); 311 double var13 = par2Random.nextDouble() * 0.1D + 0.2D; 312 var12.motionX = (double)par4 * var13; 313 var12.motionY = 0.20000000298023224D; 314 var12.motionZ = (double)par5 * var13; 315 var12.motionX += par2Random.nextGaussian() * 0.007499999832361937D * (double)par3; 316 var12.motionY += par2Random.nextGaussian() * 0.007499999832361937D * (double)par3; 317 var12.motionZ += par2Random.nextGaussian() * 0.007499999832361937D * (double)par3; 318 par0World.spawnEntityInWorld(var12); 319 } 320 321 /** 322 * arrows are fired, eggs are thrown, buckets create liquid blocks ... 323 */ 324 private static int spawnEntityWithAction(TileEntityDispenser par0TileEntityDispenser, World par1World, ItemStack par2ItemStack, Random par3Random, int par4, int par5, int par6, int par7, int par8, double par9, double par11, double par13) 325 { 326 float var15 = 1.1F; 327 byte var16 = 6; 328 int modDispense = GameRegistry.tryDispense(par1World, par9, par11, par13, par7, par8, par2ItemStack, par3Random, par9, par11, par13); 329 if (modDispense > -1) 330 { 331 return modDispense; 332 } 333 if (par2ItemStack.itemID == Item.arrow.shiftedIndex) 334 { 335 EntityArrow var28 = new EntityArrow(par1World, par9, par11, par13); 336 var28.setArrowHeading((double)par7, 0.10000000149011612D, (double)par8, var15, (float)var16); 337 var28.canBePickedUp = 1; 338 par1World.spawnEntityInWorld(var28); 339 par1World.playAuxSFX(1002, par4, par5, par6, 0); 340 return 1; 341 } 342 else if (par2ItemStack.itemID == Item.egg.shiftedIndex) 343 { 344 EntityEgg var29 = new EntityEgg(par1World, par9, par11, par13); 345 var29.setThrowableHeading((double)par7, 0.10000000149011612D, (double)par8, var15, (float)var16); 346 par1World.spawnEntityInWorld(var29); 347 par1World.playAuxSFX(1002, par4, par5, par6, 0); 348 return 1; 349 } 350 else if (par2ItemStack.itemID == Item.snowball.shiftedIndex) 351 { 352 EntitySnowball var24 = new EntitySnowball(par1World, par9, par11, par13); 353 var24.setThrowableHeading((double)par7, 0.10000000149011612D, (double)par8, var15, (float)var16); 354 par1World.spawnEntityInWorld(var24); 355 par1World.playAuxSFX(1002, par4, par5, par6, 0); 356 return 1; 357 } 358 else if (par2ItemStack.itemID == Item.potion.shiftedIndex && ItemPotion.isSplash(par2ItemStack.getItemDamage())) 359 { 360 EntityPotion var25 = new EntityPotion(par1World, par9, par11, par13, par2ItemStack.getItemDamage()); 361 var25.setThrowableHeading((double)par7, 0.10000000149011612D, (double)par8, var15 * 1.25F, (float)var16 * 0.5F); 362 par1World.spawnEntityInWorld(var25); 363 par1World.playAuxSFX(1002, par4, par5, par6, 0); 364 return 1; 365 } 366 else if (par2ItemStack.itemID == Item.expBottle.shiftedIndex) 367 { 368 EntityExpBottle var26 = new EntityExpBottle(par1World, par9, par11, par13); 369 var26.setThrowableHeading((double)par7, 0.10000000149011612D, (double)par8, var15 * 1.25F, (float)var16 * 0.5F); 370 par1World.spawnEntityInWorld(var26); 371 par1World.playAuxSFX(1002, par4, par5, par6, 0); 372 return 1; 373 } 374 else if (par2ItemStack.itemID == Item.monsterPlacer.shiftedIndex) 375 { 376 ItemMonsterPlacer.spawnCreature(par1World, par2ItemStack.getItemDamage(), par9 + (double)par7 * 0.3D, par11 - 0.3D, par13 + (double)par8 * 0.3D); 377 par1World.playAuxSFX(1002, par4, par5, par6, 0); 378 return 1; 379 } 380 else if (par2ItemStack.itemID == Item.fireballCharge.shiftedIndex) 381 { 382 EntitySmallFireball var27 = new EntitySmallFireball(par1World, par9 + (double)par7 * 0.3D, par11, par13 + (double)par8 * 0.3D, (double)par7 + par3Random.nextGaussian() * 0.05D, par3Random.nextGaussian() * 0.05D, (double)par8 + par3Random.nextGaussian() * 0.05D); 383 par1World.spawnEntityInWorld(var27); 384 par1World.playAuxSFX(1009, par4, par5, par6, 0); 385 return 1; 386 } 387 else if (par2ItemStack.itemID != Item.bucketLava.shiftedIndex && par2ItemStack.itemID != Item.bucketWater.shiftedIndex) 388 { 389 if (par2ItemStack.itemID == Item.bucketEmpty.shiftedIndex) 390 { 391 int var21 = par4 + par7; 392 int var18 = par6 + par8; 393 Material var19 = par1World.getBlockMaterial(var21, par5, var18); 394 int var20 = par1World.getBlockMetadata(var21, par5, var18); 395 396 if (var19 == Material.water && var20 == 0) 397 { 398 par1World.setBlockWithNotify(var21, par5, var18, 0); 399 400 if (--par2ItemStack.stackSize == 0) 401 { 402 par2ItemStack.itemID = Item.bucketWater.shiftedIndex; 403 par2ItemStack.stackSize = 1; 404 } 405 else if (par0TileEntityDispenser.func_70360_a(new ItemStack(Item.bucketWater)) < 0) 406 { 407 dispenseEntityFromStack(par1World, new ItemStack(Item.bucketWater), par3Random, 6, par7, par8, par9, par11, par13); 408 } 409 410 return 2; 411 } 412 else if (var19 == Material.lava && var20 == 0) 413 { 414 par1World.setBlockWithNotify(var21, par5, var18, 0); 415 416 if (--par2ItemStack.stackSize == 0) 417 { 418 par2ItemStack.itemID = Item.bucketLava.shiftedIndex; 419 par2ItemStack.stackSize = 1; 420 } 421 else if (par0TileEntityDispenser.func_70360_a(new ItemStack(Item.bucketLava)) < 0) 422 { 423 dispenseEntityFromStack(par1World, new ItemStack(Item.bucketLava), par3Random, 6, par7, par8, par9, par11, par13); 424 } 425 426 return 2; 427 } 428 else 429 { 430 return 0; 431 } 432 } 433 else if (par2ItemStack.getItem() instanceof ItemMinecart) 434 { 435 par9 = (double)par4 + (par7 < 0 ? (double)par7 * 0.8D : (double)((float)par7 * 1.8F)) + (double)((float)Math.abs(par8) * 0.5F); 436 par13 = (double)par6 + (par8 < 0 ? (double)par8 * 0.8D : (double)((float)par8 * 1.8F)) + (double)((float)Math.abs(par7) * 0.5F); 437 438 if (BlockRail.isRailBlockAt(par1World, par4 + par7, par5, par6 + par8)) 439 { 440 par11 = (double)((float)par5 + 0.5F); 441 } 442 else 443 { 444 if (!par1World.isAirBlock(par4 + par7, par5, par6 + par8) || !BlockRail.isRailBlockAt(par1World, par4 + par7, par5 - 1, par6 + par8)) 445 { 446 return 0; 447 } 448 449 par11 = (double)((float)par5 - 0.5F); 450 } 451 452 EntityMinecart var22 = new EntityMinecart(par1World, par9, par11, par13, ((ItemMinecart)par2ItemStack.getItem()).minecartType); 453 par1World.spawnEntityInWorld(var22); 454 par1World.playAuxSFX(1000, par4, par5, par6, 0); 455 return 1; 456 } 457 else if (par2ItemStack.itemID == Item.boat.shiftedIndex) 458 { 459 par9 = (double)par4 + (par7 < 0 ? (double)par7 * 0.8D : (double)((float)par7 * 1.8F)) + (double)((float)Math.abs(par8) * 0.5F); 460 par13 = (double)par6 + (par8 < 0 ? (double)par8 * 0.8D : (double)((float)par8 * 1.8F)) + (double)((float)Math.abs(par7) * 0.5F); 461 462 if (par1World.getBlockMaterial(par4 + par7, par5, par6 + par8) == Material.water) 463 { 464 par11 = (double)((float)par5 + 1.0F); 465 } 466 else 467 { 468 if (!par1World.isAirBlock(par4 + par7, par5, par6 + par8) || par1World.getBlockMaterial(par4 + par7, par5 - 1, par6 + par8) != Material.water) 469 { 470 return 0; 471 } 472 473 par11 = (double)par5; 474 } 475 476 EntityBoat var23 = new EntityBoat(par1World, par9, par11, par13); 477 par1World.spawnEntityInWorld(var23); 478 par1World.playAuxSFX(1000, par4, par5, par6, 0); 479 return 1; 480 } 481 else 482 { 483 return 0; 484 } 485 } 486 else 487 { 488 ItemBucket var17 = (ItemBucket)par2ItemStack.getItem(); 489 490 if (var17.func_77875_a(par1World, (double)par4, (double)par5, (double)par6, par4 + par7, par5, par6 + par8)) 491 { 492 par2ItemStack.itemID = Item.bucketEmpty.shiftedIndex; 493 par2ItemStack.stackSize = 1; 494 return 2; 495 } 496 else 497 { 498 return 0; 499 } 500 } 501 } 502 }