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 i; float f; int j; if (this.receivedFinishDiggingPacket) { i = this.curblockDamage - this.field_73093_n; int k = this.theWorld.getBlockId(this.posX, this.posY, this.posZ); if (k == 0) { this.receivedFinishDiggingPacket = false; } else { Block block = Block.blocksList[k]; f = block.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj, this.posX, this.posY, this.posZ) * (float)(i + 1); j = (int)(f * 10.0F); if (j != this.durabilityRemainingOnBlock) { this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.posX, this.posY, this.posZ, j); this.durabilityRemainingOnBlock = j; } if (f >= 1.0F) { this.receivedFinishDiggingPacket = false; this.tryHarvestBlock(this.posX, this.posY, this.posZ); } } } else if (this.isDestroyingBlock) { i = this.theWorld.getBlockId(this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ); Block block1 = Block.blocksList[i]; if (block1 == null) { this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ, -1); this.durabilityRemainingOnBlock = -1; this.isDestroyingBlock = false; } else { int l = this.curblockDamage - this.initialDamage; f = block1.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ) * (float)(l + 1); j = (int)(f * 10.0F); if (j != this.durabilityRemainingOnBlock) { this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ, j); this.durabilityRemainingOnBlock = j; } } } } /** * 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 f = 1.0F; int i1 = this.theWorld.getBlockId(par1, par2, par3); Block block = Block.blocksList[i1]; 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)); } f = block.getPlayerRelativeBlockHardness(thisPlayerMP, thisPlayerMP.worldObj, par1, par2, par3); } if (event.useItem == Event.Result.DENY) { if (f >= 1.0f) { thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par1, par2, par3, theWorld)); } return; } if (i1 > 0 && f >= 1.0F) { this.tryHarvestBlock(par1, par2, par3); } else { this.isDestroyingBlock = true; this.partiallyDestroyedBlockX = par1; this.partiallyDestroyedBlockY = par2; this.partiallyDestroyedBlockZ = par3; int j1 = (int)(f * 10.0F); this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, par1, par2, par3, j1); this.durabilityRemainingOnBlock = j1; } } } } public void uncheckedTryHarvestBlock(int par1, int par2, int par3) { if (par1 == this.partiallyDestroyedBlockX && par2 == this.partiallyDestroyedBlockY && par3 == this.partiallyDestroyedBlockZ) { int l = this.curblockDamage - this.initialDamage; int i1 = this.theWorld.getBlockId(par1, par2, par3); if (i1 != 0) { Block block = Block.blocksList[i1]; float f = block.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj, par1, par2, par3) * (float)(l + 1); if (f >= 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 block = Block.blocksList[this.theWorld.getBlockId(par1, par2, par3)]; int l = this.theWorld.getBlockMetadata(par1, par2, par3); if (block != null) { block.onBlockHarvested(this.theWorld, par1, par2, par3, l, this.thisPlayerMP); } boolean flag = (block != null && block.removeBlockByPlayer(theWorld, thisPlayerMP, par1, par2, par3)); if (block != null && flag) { block.onBlockDestroyedByPlayer(this.theWorld, par1, par2, par3, l); } return flag; } /** * 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 l = this.theWorld.getBlockId(par1, par2, par3); int i1 = this.theWorld.getBlockMetadata(par1, par2, par3); this.theWorld.playAuxSFXAtEntity(this.thisPlayerMP, 2001, par1, par2, par3, l + (this.theWorld.getBlockMetadata(par1, par2, par3) << 12)); boolean flag = false; if (this.isCreative()) { flag = this.removeBlock(par1, par2, par3); this.thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par1, par2, par3, this.theWorld)); } else { ItemStack itemstack = this.thisPlayerMP.getCurrentEquippedItem(); boolean flag1 = false; Block block = Block.blocksList[l]; if (block != null) { flag1 = block.canHarvestBlock(thisPlayerMP, i1); } if (itemstack != null) { itemstack.onBlockDestroyed(this.theWorld, l, par1, par2, par3, this.thisPlayerMP); if (itemstack.stackSize == 0) { this.thisPlayerMP.destroyCurrentEquippedItem(); } } flag = this.removeBlock(par1, par2, par3); if (flag && flag1) { Block.blocksList[l].harvestBlock(this.theWorld, this.thisPlayerMP, par1, par2, par3, i1); } } return flag; } } /** * 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 i = par3ItemStack.stackSize; int j = par3ItemStack.getItemDamage(); ItemStack itemstack1 = par3ItemStack.useItemRightClick(par2World, par1EntityPlayer); if (itemstack1 == par3ItemStack && (itemstack1 == null || itemstack1.stackSize == i && itemstack1.getMaxItemUseDuration() <= 0 && itemstack1.getItemDamage() == j)) { return false; } else { par1EntityPlayer.inventory.mainInventory[par1EntityPlayer.inventory.currentItem] = itemstack1; if (this.isCreative()) { itemstack1.stackSize = i; if (itemstack1.isItemStackDamageable()) { itemstack1.setItemDamage(j); } } if (itemstack1.stackSize == 0) { par1EntityPlayer.inventory.mainInventory[par1EntityPlayer.inventory.currentItem] = null; MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(thisPlayerMP, itemstack1)); } 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 i1 = par2World.getBlockId(par4, par5, par6); Block block = Block.blocksList[i1]; 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; } }