    001    package net.minecraft.src;
    002
    003    import net.minecraftforge.common.ForgeHooks;
    004    import net.minecraftforge.common.MinecraftForge;
    005    import net.minecraftforge.event.Event;
    006    import net.minecraftforge.event.ForgeEventFactory;
    007    import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent;
    008    import net.minecraftforge.event.entity.player.PlayerInteractEvent;
    009    import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action;
    010
    011    public class ItemInWorldManager
    012    {
    013        /** Forge reach distance */
    014        private double blockReachDistance = 5.0d;
    015        /** The world object that this object is connected to. */
    016        public World theWorld;
    017
    018        /** The EntityPlayerMP object that this object is connected to. */
    019        public EntityPlayerMP thisPlayerMP;
    020        private EnumGameType gameType;
    021
    022        /**
    023         * set to true on first call of destroyBlockInWorldPartially, false before any further calls
    024         */
    025        private boolean isPartiallyDestroyedBlockWhole;
    026        private int initialDamage;
    027        private int partiallyDestroyedBlockX;
    028        private int partiallyDestroyedBlockY;
    029        private int partiallyDestroyedBlockZ;
    030        private int curblockDamage;
    031        private boolean field_73097_j;
    032        private int posX;
    033        private int posY;
    034        private int posZ;
    035        private int field_73093_n;
    036        private int durabilityRemainingOnBlock;
    037
    038        public ItemInWorldManager(World par1World)
    039        {
    040            this.gameType = EnumGameType.NOT_SET;
    041            this.durabilityRemainingOnBlock = -1;
    042            this.theWorld = par1World;
    043        }
    044
    045        public void setGameType(EnumGameType par1EnumGameType)
    046        {
    047            this.gameType = par1EnumGameType;
    048            par1EnumGameType.configurePlayerCapabilities(this.thisPlayerMP.capabilities);
    049            this.thisPlayerMP.sendPlayerAbilities();
    050        }
    051
    052        public EnumGameType getGameType()
    053        {
    054            return this.gameType;
    055        }
    056
    057        /**
    058         * Get if we are in creative game mode.
    059         */
    060        public boolean isCreative()
    061        {
    062            return this.gameType.isCreative();
    063        }
    064
    065        /**
    066         * if the gameType is currently NOT_SET then change it to par1
    067         */
    068        public void initializeGameType(EnumGameType par1EnumGameType)
    069        {
    070            if (this.gameType == EnumGameType.NOT_SET)
    071            {
    072                this.gameType = par1EnumGameType;
    073            }
    074
    075            this.setGameType(this.gameType);
    076        }
    077
    078        public void updateBlockRemoving()
    079        {
    080            ++this.curblockDamage;
    081            int var1;
    082            float var4;
    083            int var5;
    084
    085            if (this.field_73097_j)
    086            {
    087                var1 = this.curblockDamage - this.field_73093_n;
    088                int var2 = this.theWorld.getBlockId(this.posX, this.posY, this.posZ);
    089
    090                if (var2 == 0)
    091                {
    092                    this.field_73097_j = false;
    093                }
    094                else
    095                {
    096                    Block var3 = Block.blocksList[var2];
    097                    var4 = var3.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj, this.posX, this.posY, this.posZ) * (float)(var1 + 1);
    098                    var5 = (int)(var4 * 10.0F);
    099
    100                    if (var5 != this.durabilityRemainingOnBlock)
    101                    {
    102                        this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.posX, this.posY, this.posZ, var5);
    103                        this.durabilityRemainingOnBlock = var5;
    104                    }
    105
    106                    if (var4 >= 1.0F)
    107                    {
    108                        this.field_73097_j = false;
    109                        this.tryHarvestBlock(this.posX, this.posY, this.posZ);
    110                    }
    111                }
    112            }
    113            else if (this.isPartiallyDestroyedBlockWhole)
    114            {
    115                var1 = this.theWorld.getBlockId(this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ);
    116                Block var6 = Block.blocksList[var1];
    117
    118                if (var6 == null)
    119                {
    120                    this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ, -1);
    121                    this.durabilityRemainingOnBlock = -1;
    122                    this.isPartiallyDestroyedBlockWhole = false;
    123                }
    124                else
    125                {
    126                    int var7 = this.curblockDamage - this.initialDamage;
    127                    var4 = var6.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ) * (float)(var7 + 1);
    128                    var5 = (int)(var4 * 10.0F);
    129
    130                    if (var5 != this.durabilityRemainingOnBlock)
    131                    {
    132                        this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ, var5);
    133                        this.durabilityRemainingOnBlock = var5;
    134                    }
    135                }
    136            }
    137        }
    138
    139        /**
    140         * if not creative, it calls destroyBlockInWorldPartially untill the block is broken first. par4 is the specific
    141         * side. tryHarvestBlock can also be the result of this call
    142         */
    143        public void onBlockClicked(int par1, int par2, int par3, int par4)
    144        {
    145            if (!this.gameType.func_82752_c() || this.thisPlayerMP.func_82246_f(par1, par2, par3))
    146            {
    147                PlayerInteractEvent event = ForgeEventFactory.onPlayerInteract(thisPlayerMP, Action.LEFT_CLICK_BLOCK, par1, par2, par3, par4);
    148                if (event.isCanceled())
    149                {
    150                    thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par1, par2, par3, theWorld));
    151                    return;
    152                }
    153
    154                if (this.isCreative())
    155                {
    156                    if (!this.theWorld.extinguishFire((EntityPlayer)null, par1, par2, par3, par4))
    157                    {
    158                        this.tryHarvestBlock(par1, par2, par3);
    159                    }
    160                }
    161                else
    162                {
    163                    this.initialDamage = this.curblockDamage;
    164                    float var5 = 1.0F;
    165                    int var6 = this.theWorld.getBlockId(par1, par2, par3);
    166                    Block block = Block.blocksList[var6];
    167
    168                    if (block != null)
    169                    {
    170                        if (event.useBlock != Event.Result.DENY)
    171                        {
    172                            block.onBlockClicked(theWorld, par1, par2, par3, thisPlayerMP);
    173                            theWorld.extinguishFire(thisPlayerMP, par1, par2, par3, par4);
    174                        }
    175                        else
    176                        {
    177                            thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par1, par2, par3, theWorld));
    178                        }
    179                        var5 = block.getPlayerRelativeBlockHardness(thisPlayerMP, thisPlayerMP.worldObj, par1, par2, par3);
    180                    }
    181
    182                    if (event.useItem == Event.Result.DENY)
    183                    {
    184                        if (var5 >= 1.0f)
    185                        {
    186                            thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par1, par2, par3, theWorld));
    187                        }
    188                        return;
    189                    }
    190
    191                    if (var6 > 0 && var5 >= 1.0F)
    192                    {
    193                        this.tryHarvestBlock(par1, par2, par3);
    194                    }
    195                    else
    196                    {
    197                        this.isPartiallyDestroyedBlockWhole = true;
    198                        this.partiallyDestroyedBlockX = par1;
    199                        this.partiallyDestroyedBlockY = par2;
    200                        this.partiallyDestroyedBlockZ = par3;
    201                        int var7 = (int)(var5 * 10.0F);
    202                        this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, par1, par2, par3, var7);
    203                        this.durabilityRemainingOnBlock = var7;
    204                    }
    205                }
    206            }
    207        }
    208
    209        public void uncheckedTryHarvestBlock(int par1, int par2, int par3)
    210        {
    211            if (par1 == this.partiallyDestroyedBlockX && par2 == this.partiallyDestroyedBlockY && par3 == this.partiallyDestroyedBlockZ)
    212            {
    213                int var4 = this.curblockDamage - this.initialDamage;
    214                int var5 = this.theWorld.getBlockId(par1, par2, par3);
    215
    216                if (var5 != 0)
    217                {
    218                    Block var6 = Block.blocksList[var5];
    219                    float var7 = var6.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj, par1, par2, par3) * (float)(var4 + 1);
    220
    221                    if (var7 >= 0.7F)
    222                    {
    223                        this.isPartiallyDestroyedBlockWhole = false;
    224                        this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, par1, par2, par3, -1);
    225                        this.tryHarvestBlock(par1, par2, par3);
    226                    }
    227                    else if (!this.field_73097_j)
    228                    {
    229                        this.isPartiallyDestroyedBlockWhole = false;
    230                        this.field_73097_j = true;
    231                        this.posX = par1;
    232                        this.posY = par2;
    233                        this.posZ = par3;
    234                        this.field_73093_n = this.initialDamage;
    235                    }
    236                }
    237            }
    238        }
    239
    240        /**
    241         * note: this ignores the pars passed in and continues to destroy the onClickedBlock
    242         */
    243        public void destroyBlockInWorldPartially(int par1, int par2, int par3)
    244        {
    245            this.isPartiallyDestroyedBlockWhole = false;
    246            this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ, -1);
    247        }
    248
    249        /**
    250         * Removes a block and triggers the appropriate  events
    251         */
    252        private boolean removeBlock(int par1, int par2, int par3)
    253        {
    254            Block var4 = Block.blocksList[this.theWorld.getBlockId(par1, par2, par3)];
    255            int var5 = this.theWorld.getBlockMetadata(par1, par2, par3);
    256
    257            if (var4 != null)
    258            {
    259                var4.onBlockHarvested(this.theWorld, par1, par2, par3, var5, this.thisPlayerMP);
    260            }
    261
    262            boolean var6 = (var4 != null && var4.removeBlockByPlayer(theWorld, thisPlayerMP, par1, par2, par3));
    263
    264            if (var4 != null && var6)
    265            {
    266                var4.onBlockDestroyedByPlayer(this.theWorld, par1, par2, par3, var5);
    267            }
    268
    269            return var6;
    270        }
    271
    272        /**
    273         * Attempts to harvest a block at the given coordinate
    274         */
    275        public boolean tryHarvestBlock(int par1, int par2, int par3)
    276        {
    277            if (this.gameType.func_82752_c() && !this.thisPlayerMP.func_82246_f(par1, par2, par3))
    278            {
    279                return false;
    280            }
    281            else
    282            {
    283                ItemStack stack = thisPlayerMP.getCurrentEquippedItem();
    284                if (stack != null && stack.getItem().onBlockStartBreak(stack, par1, par2, par3, thisPlayerMP))
    285                {
    286                    return false;
    287                }
    288                int var4 = this.theWorld.getBlockId(par1, par2, par3);
    289                int var5 = this.theWorld.getBlockMetadata(par1, par2, par3);
    290                this.theWorld.playAuxSFXAtEntity(this.thisPlayerMP, 2001, par1, par2, par3, var4 + (this.theWorld.getBlockMetadata(par1, par2, par3) << 12));
    291                boolean var6 = false;
    292
    293                if (this.isCreative())
    294                {
    295                    var6 = this.removeBlock(par1, par2, par3);
    296                    this.thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par1, par2, par3, this.theWorld));
    297                }
    298                else
    299                {
    300                    ItemStack var7 = this.thisPlayerMP.getCurrentEquippedItem();
    301                    boolean var8 = false;
    302                    Block block = Block.blocksList[var4];
    303                    if (block != null)
    304                    {
    305                        var8 = block.canHarvestBlock(thisPlayerMP, var5);
    306                    }
    307
    308                    if (var7 != null)
    309                    {
    310                        var7.onBlockDestroyed(this.theWorld, var4, par1, par2, par3, this.thisPlayerMP);
    311
    312                        if (var7.stackSize == 0)
    313                        {
    314                            this.thisPlayerMP.destroyCurrentEquippedItem();
    315                            MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(thisPlayerMP, var7));
    316                        }
    317                    }
    318
    319                    var6 = this.removeBlock(par1, par2, par3);
    320                    if (var6 && var8)
    321                    {
    322                        Block.blocksList[var4].harvestBlock(this.theWorld, this.thisPlayerMP, par1, par2, par3, var5);
    323                    }
    324                }
    325
    326                return var6;
    327            }
    328        }
    329
    330        /**
    331         * Attempts to right-click use an item by the given EntityPlayer in the given World
    332         */
    333        public boolean tryUseItem(EntityPlayer par1EntityPlayer, World par2World, ItemStack par3ItemStack)
    334        {
    335            int var4 = par3ItemStack.stackSize;
    336            int var5 = par3ItemStack.getItemDamage();
    337            ItemStack var6 = par3ItemStack.useItemRightClick(par2World, par1EntityPlayer);
    338
    339            if (var6 == par3ItemStack && (var6 == null || var6.stackSize == var4 && var6.getMaxItemUseDuration() <= 0 && var6.getItemDamage() == var5))
    340            {
    341                return false;
    342            }
    343            else
    344            {
    345                par1EntityPlayer.inventory.mainInventory[par1EntityPlayer.inventory.currentItem] = var6;
    346
    347                if (this.isCreative())
    348                {
    349                    var6.stackSize = var4;
    350
    351                    if (var6.isItemStackDamageable())
    352                    {
    353                        var6.setItemDamage(var5);
    354                    }
    355                }
    356
    357                if (var6.stackSize == 0)
    358                {
    359                    par1EntityPlayer.inventory.mainInventory[par1EntityPlayer.inventory.currentItem] = null;
    360                    MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(thisPlayerMP, var6));
    361                }
    362
    363                if (!par1EntityPlayer.isUsingItem())
    364                {
    365                    ((EntityPlayerMP)par1EntityPlayer).sendContainerToPlayer(par1EntityPlayer.inventorySlots);
    366                }
    367
    368                return true;
    369            }
    370        }
    371
    372        /**
    373         * Activate the clicked on block, otherwise use the held item. Args: player, world, itemStack, x, y, z, side,
    374         * xOffset, yOffset, zOffset
    375         */
    376        public boolean activateBlockOrUseItem(EntityPlayer par1EntityPlayer, World par2World, ItemStack par3ItemStack, int par4, int par5, int par6, int par7, float par8, float par9, float par10)
    377        {
    378            PlayerInteractEvent event = ForgeEventFactory.onPlayerInteract(par1EntityPlayer, Action.RIGHT_CLICK_BLOCK, par4, par5, par6, par7);
    379            if (event.isCanceled())
    380            {
    381                thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par4, par5, par6, theWorld));
    382                return false;
    383            }
    384
    385            Item item = (par3ItemStack != null ? par3ItemStack.getItem() : null);
    386            if (item != null && item.onItemUseFirst(par3ItemStack, par1EntityPlayer, par2World, par4, par5, par6, par7, par8, par9, par10))
    387            {
    388                if (par3ItemStack.stackSize <= 0) ForgeEventFactory.onPlayerDestroyItem(thisPlayerMP, par3ItemStack);
    389                return true;
    390            }
    391
    392            int var11 = par2World.getBlockId(par4, par5, par6);
    393            Block block = Block.blocksList[var11];
    394            boolean result = false;
    395
    396            if (block != null)
    397            {
    398                if (event.useBlock != Event.Result.DENY)
    399                {
    400                    result = block.onBlockActivated(par2World, par4, par5, par6, par1EntityPlayer, par7, par8, par9, par10);
    401                }
    402                else
    403                {
    404                    thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par4, par5, par6, theWorld));
    405                    result = event.useItem != Event.Result.ALLOW;
    406                }
    407            }
    408
    409            if (par3ItemStack != null && !result)
    410            {
    411                int meta = par3ItemStack.getItemDamage();
    412                int size = par3ItemStack.stackSize;
    413                result = par3ItemStack.tryPlaceItemIntoWorld(par1EntityPlayer, par2World, par4, par5, par6, par7, par8, par9, par10);
    414                if (isCreative())
    415                {
    416                    par3ItemStack.setItemDamage(meta);
    417                    par3ItemStack.stackSize = size;
    418                }
    419                if (par3ItemStack.stackSize <= 0) ForgeEventFactory.onPlayerDestroyItem(thisPlayerMP, par3ItemStack);
    420            }
    421
    422            /* Re-enable if this causes bukkit incompatibility, or re-write client side to only send a single packet per right click.
    423            if (par3ItemStack != null && ((!result && event.useItem != Event.Result.DENY) || event.useItem == Event.Result.ALLOW))
    424            {
    425                this.tryUseItem(thisPlayerMP, par2World, par3ItemStack);
    426            }*/
    427            return result;
    428        }
    429
    430        /**
    431         * Sets the world instance.
    432         */
    433        public void setWorld(WorldServer par1WorldServer)
    434        {
    435            this.theWorld = par1WorldServer;
    436        }
    437
    438        public double getBlockReachDistance()
    439        {
    440            return blockReachDistance;
    441        }
    442        public void setBlockReachDistance(double distance)
    443        {
    444            blockReachDistance = distance;
    445        }
    446    }