    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    }