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