package net.minecraft.item; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.network.packet.Packet53BlockChange; import net.minecraft.world.EnumGameType; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.Event; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action; public class ItemInWorldManager { /** Forge reach distance */ private double blockReachDistance = 5.0d; /** The world object that this object is connected to. */ public World theWorld; /** The EntityPlayerMP object that this object is connected to. */ public EntityPlayerMP thisPlayerMP; private EnumGameType gameType; /** True if the player is destroying a block */ private boolean isDestroyingBlock; private int initialDamage; private int partiallyDestroyedBlockX; private int partiallyDestroyedBlockY; private int partiallyDestroyedBlockZ; private int curblockDamage; /** * Set to true when the "finished destroying block" packet is received but the block wasn't fully damaged yet. The * block will not be destroyed while this is false. */ private boolean receivedFinishDiggingPacket; private int posX; private int posY; private int posZ; private int field_73093_n; private int durabilityRemainingOnBlock; public ItemInWorldManager(World par1World) { this.gameType = EnumGameType.NOT_SET; this.durabilityRemainingOnBlock = -1; this.theWorld = par1World; } public void setGameType(EnumGameType par1EnumGameType) { this.gameType = par1EnumGameType; par1EnumGameType.configurePlayerCapabilities(this.thisPlayerMP.capabilities); this.thisPlayerMP.sendPlayerAbilities(); } public EnumGameType getGameType() { return this.gameType; } /** * Get if we are in creative game mode. */ public boolean isCreative() { return this.gameType.isCreative(); } /** * if the gameType is currently NOT_SET then change it to par1 */ public void initializeGameType(EnumGameType par1EnumGameType) { if (this.gameType == EnumGameType.NOT_SET) { this.gameType = par1EnumGameType; } this.setGameType(this.gameType); } public void updateBlockRemoving() { ++this.curblockDamage; int var1; float var4; int var5; if (this.receivedFinishDiggingPacket) { var1 = this.curblockDamage - this.field_73093_n; int var2 = this.theWorld.getBlockId(this.posX, this.posY, this.posZ); if (var2 == 0) { this.receivedFinishDiggingPacket = false; } else { Block var3 = Block.blocksList[var2]; var4 = var3.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj, this.posX, this.posY, this.posZ) * (float)(var1 + 1); var5 = (int)(var4 * 10.0F); if (var5 != this.durabilityRemainingOnBlock) { this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.posX, this.posY, this.posZ, var5); this.durabilityRemainingOnBlock = var5; } if (var4 >= 1.0F) { this.receivedFinishDiggingPacket = false; this.tryHarvestBlock(this.posX, this.posY, this.posZ); } } } else if (this.isDestroyingBlock) { var1 = this.theWorld.getBlockId(this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ); Block var6 = Block.blocksList[var1]; if (var6 == null) { this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ, -1); this.durabilityRemainingOnBlock = -1; this.isDestroyingBlock = false; } else { int var7 = this.curblockDamage - this.initialDamage; var4 = var6.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ) * (float)(var7 + 1); var5 = (int)(var4 * 10.0F); if (var5 != this.durabilityRemainingOnBlock) { this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ, var5); this.durabilityRemainingOnBlock = var5; } } } } /** * if not creative, it calls destroyBlockInWorldPartially untill the block is broken first. par4 is the specific * side. tryHarvestBlock can also be the result of this call */ public void onBlockClicked(int par1, int par2, int par3, int par4) { if (!this.gameType.isAdventure() || this.thisPlayerMP.canCurrentToolHarvestBlock(par1, par2, par3)) { PlayerInteractEvent event = ForgeEventFactory.onPlayerInteract(thisPlayerMP, Action.LEFT_CLICK_BLOCK, par1, par2, par3, par4); if (event.isCanceled()) { thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par1, par2, par3, theWorld)); return; } if (this.isCreative()) { if (!this.theWorld.extinguishFire((EntityPlayer)null, par1, par2, par3, par4)) { this.tryHarvestBlock(par1, par2, par3); } } else { this.initialDamage = this.curblockDamage; float var5 = 1.0F; int var6 = this.theWorld.getBlockId(par1, par2, par3); Block block = Block.blocksList[var6]; if (block != null) { if (event.useBlock != Event.Result.DENY) { block.onBlockClicked(theWorld, par1, par2, par3, thisPlayerMP); theWorld.extinguishFire(thisPlayerMP, par1, par2, par3, par4); } else { thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par1, par2, par3, theWorld)); } var5 = block.getPlayerRelativeBlockHardness(thisPlayerMP, thisPlayerMP.worldObj, par1, par2, par3); } if (event.useItem == Event.Result.DENY) { if (var5 >= 1.0f) { thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par1, par2, par3, theWorld)); } return; } if (var6 > 0 && var5 >= 1.0F) { this.tryHarvestBlock(par1, par2, par3); } else { this.isDestroyingBlock = true; this.partiallyDestroyedBlockX = par1; this.partiallyDestroyedBlockY = par2; this.partiallyDestroyedBlockZ = par3; int var7 = (int)(var5 * 10.0F); this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, par1, par2, par3, var7); this.durabilityRemainingOnBlock = var7; } } } } public void uncheckedTryHarvestBlock(int par1, int par2, int par3) { if (par1 == this.partiallyDestroyedBlockX && par2 == this.partiallyDestroyedBlockY && par3 == this.partiallyDestroyedBlockZ) { int var4 = this.curblockDamage - this.initialDamage; int var5 = this.theWorld.getBlockId(par1, par2, par3); if (var5 != 0) { Block var6 = Block.blocksList[var5]; float var7 = var6.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj, par1, par2, par3) * (float)(var4 + 1); if (var7 >= 0.7F) { this.isDestroyingBlock = false; this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, par1, par2, par3, -1); this.tryHarvestBlock(par1, par2, par3); } else if (!this.receivedFinishDiggingPacket) { this.isDestroyingBlock = false; this.receivedFinishDiggingPacket = true; this.posX = par1; this.posY = par2; this.posZ = par3; this.field_73093_n = this.initialDamage; } } } } /** * note: this ignores the pars passed in and continues to destroy the onClickedBlock */ public void cancelDestroyingBlock(int par1, int par2, int par3) { this.isDestroyingBlock = false; this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ, -1); } /** * Removes a block and triggers the appropriate events */ private boolean removeBlock(int par1, int par2, int par3) { Block var4 = Block.blocksList[this.theWorld.getBlockId(par1, par2, par3)]; int var5 = this.theWorld.getBlockMetadata(par1, par2, par3); if (var4 != null) { var4.onBlockHarvested(this.theWorld, par1, par2, par3, var5, this.thisPlayerMP); } boolean var6 = (var4 != null && var4.removeBlockByPlayer(theWorld, thisPlayerMP, par1, par2, par3)); if (var4 != null && var6) { var4.onBlockDestroyedByPlayer(this.theWorld, par1, par2, par3, var5); } return var6; } /** * Attempts to harvest a block at the given coordinate */ public boolean tryHarvestBlock(int par1, int par2, int par3) { if (this.gameType.isAdventure() && !this.thisPlayerMP.canCurrentToolHarvestBlock(par1, par2, par3)) { return false; } else { ItemStack stack = thisPlayerMP.getCurrentEquippedItem(); if (stack != null && stack.getItem().onBlockStartBreak(stack, par1, par2, par3, thisPlayerMP)) { return false; } int var4 = this.theWorld.getBlockId(par1, par2, par3); int var5 = this.theWorld.getBlockMetadata(par1, par2, par3); this.theWorld.playAuxSFXAtEntity(this.thisPlayerMP, 2001, par1, par2, par3, var4 + (this.theWorld.getBlockMetadata(par1, par2, par3) << 12)); boolean var6 = false; if (this.isCreative()) { var6 = this.removeBlock(par1, par2, par3); this.thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par1, par2, par3, this.theWorld)); } else { ItemStack var7 = this.thisPlayerMP.getCurrentEquippedItem(); boolean var8 = false; Block block = Block.blocksList[var4]; if (block != null) { var8 = block.canHarvestBlock(thisPlayerMP, var5); } if (var7 != null) { var7.onBlockDestroyed(this.theWorld, var4, par1, par2, par3, this.thisPlayerMP); if (var7.stackSize == 0) { this.thisPlayerMP.destroyCurrentEquippedItem(); } } var6 = this.removeBlock(par1, par2, par3); if (var6 && var8) { Block.blocksList[var4].harvestBlock(this.theWorld, this.thisPlayerMP, par1, par2, par3, var5); } } return var6; } } /** * Attempts to right-click use an item by the given EntityPlayer in the given World */ public boolean tryUseItem(EntityPlayer par1EntityPlayer, World par2World, ItemStack par3ItemStack) { int var4 = par3ItemStack.stackSize; int var5 = par3ItemStack.getItemDamage(); ItemStack var6 = par3ItemStack.useItemRightClick(par2World, par1EntityPlayer); if (var6 == par3ItemStack && (var6 == null || var6.stackSize == var4 && var6.getMaxItemUseDuration() <= 0 && var6.getItemDamage() == var5)) { return false; } else { par1EntityPlayer.inventory.mainInventory[par1EntityPlayer.inventory.currentItem] = var6; if (this.isCreative()) { var6.stackSize = var4; if (var6.isItemStackDamageable()) { var6.setItemDamage(var5); } } if (var6.stackSize == 0) { par1EntityPlayer.inventory.mainInventory[par1EntityPlayer.inventory.currentItem] = null; MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(thisPlayerMP, var6)); } if (!par1EntityPlayer.isUsingItem()) { ((EntityPlayerMP)par1EntityPlayer).sendContainerToPlayer(par1EntityPlayer.inventoryContainer); } return true; } } /** * Activate the clicked on block, otherwise use the held item. Args: player, world, itemStack, x, y, z, side, * xOffset, yOffset, zOffset */ public boolean activateBlockOrUseItem(EntityPlayer par1EntityPlayer, World par2World, ItemStack par3ItemStack, int par4, int par5, int par6, int par7, float par8, float par9, float par10) { PlayerInteractEvent event = ForgeEventFactory.onPlayerInteract(par1EntityPlayer, Action.RIGHT_CLICK_BLOCK, par4, par5, par6, par7); if (event.isCanceled()) { thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par4, par5, par6, theWorld)); return false; } Item item = (par3ItemStack != null ? par3ItemStack.getItem() : null); if (item != null && item.onItemUseFirst(par3ItemStack, par1EntityPlayer, par2World, par4, par5, par6, par7, par8, par9, par10)) { if (par3ItemStack.stackSize <= 0) ForgeEventFactory.onPlayerDestroyItem(thisPlayerMP, par3ItemStack); return true; } int var11 = par2World.getBlockId(par4, par5, par6); Block block = Block.blocksList[var11]; boolean result = false; if (block != null && (!par1EntityPlayer.isSneaking() || ( par1EntityPlayer.getHeldItem() == null || par1EntityPlayer.getHeldItem().getItem().shouldPassSneakingClickToBlock(par2World, par4, par5, par6)))) { if (event.useBlock != Event.Result.DENY) { result = block.onBlockActivated(par2World, par4, par5, par6, par1EntityPlayer, par7, par8, par9, par10); } else { thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par4, par5, par6, theWorld)); result = event.useItem != Event.Result.ALLOW; } } if (par3ItemStack != null && !result && event.useItem != Event.Result.DENY) { int meta = par3ItemStack.getItemDamage(); int size = par3ItemStack.stackSize; result = par3ItemStack.tryPlaceItemIntoWorld(par1EntityPlayer, par2World, par4, par5, par6, par7, par8, par9, par10); if (isCreative()) { par3ItemStack.setItemDamage(meta); par3ItemStack.stackSize = size; } if (par3ItemStack.stackSize <= 0) ForgeEventFactory.onPlayerDestroyItem(thisPlayerMP, par3ItemStack); } /* Re-enable if this causes bukkit incompatibility, or re-write client side to only send a single packet per right click. if (par3ItemStack != null && ((!result && event.useItem != Event.Result.DENY) || event.useItem == Event.Result.ALLOW)) { this.tryUseItem(thisPlayerMP, par2World, par3ItemStack); }*/ return result; } /** * Sets the world instance. */ public void setWorld(WorldServer par1WorldServer) { this.theWorld = par1WorldServer; } public double getBlockReachDistance() { return blockReachDistance; } public void setBlockReachDistance(double distance) { blockReachDistance = distance; } }