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.getRandomStackFromInventory();
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 * Returns a new instance of a block's tile entity class. Called on placing the block.
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, par4, par5, par6, 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 }