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