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