    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    }