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 func_82526_n(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.func_82526_n(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 }