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    }