package tconstruct.library.tools; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.PlayerControllerMP; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.play.server.S23PacketBlockChange; import net.minecraft.world.World; import net.minecraftforge.common.ForgeHooks; import tconstruct.TConstruct; /* Base class for tools that should be harvesting blocks */ public abstract class HarvestTool extends ToolCore { public HarvestTool(int baseDamage) { super(baseDamage); } @Override public boolean onBlockStartBreak (ItemStack stack, int x, int y, int z, EntityPlayer player) { return super.onBlockStartBreak(stack, x,y,z, player); } @Override public int getHarvestLevel(ItemStack stack, String toolClass) { // well, we can only get the harvestlevel if we have an item to get it from! if(stack == null || !(stack.getItem() instanceof HarvestTool)) return -1; // invalid query or wrong toolclass if(toolClass == null || !this.getHarvestType().equals(toolClass)) return -1; if(!stack.hasTagCompound()) return -1; NBTTagCompound tags = stack.getTagCompound().getCompoundTag("InfiTool"); // broken tools suck. if (tags.getBoolean("Broken")) return -1; // tadaaaa return tags.getInteger("HarvestLevel"); } @Override public float getDigSpeed (ItemStack stack, Block block, int meta) { if (!stack.hasTagCompound()) return 1.0f; NBTTagCompound tags = stack.getTagCompound().getCompoundTag("InfiTool"); if (tags.getBoolean("Broken")) return 0.1f; Material[] materials = getEffectiveMaterials(); for (int i = 0; i < materials.length; i++) { if (materials[i] == block.getMaterial()) { return calculateStrength(tags, block, meta); } } if (this.getHarvestType().equals(block.getHarvestTool(meta)) && block.getHarvestLevel(meta) > 0) { return calculateStrength(tags, block, meta); // No issue if the // harvest level is // too low } return super.getDigSpeed(stack, block, meta); } public float calculateStrength (NBTTagCompound tags, Block block, int meta) { int hlvl = block.getHarvestLevel(meta); if (hlvl > tags.getInteger("HarvestLevel")) return 0.1f; return AbilityHelper.calcToolSpeed(this, tags); } public float breakSpeedModifier () { return 1.0f; } public float stoneboundModifier () { return 72f; } @Override public boolean func_150897_b (Block block) { if (block.getMaterial().isToolNotRequired()) { return true; } return isEffective(block.getMaterial()); } @Override public boolean canHarvestBlock (Block block, ItemStack itemStack) { return func_150897_b(block); } @Override public String[] getTraits () { return new String[] { "harvest" }; } protected abstract Material[] getEffectiveMaterials (); protected abstract String getHarvestType (); public boolean isEffective (Material material) { for (Material m : getEffectiveMaterials()) if (m == material) return true; return false; } //Right-click @Override public boolean onItemUse (ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float clickX, float clickY, float clickZ) { /*if (world.isRemote) return true;*/ boolean used = false; int hotbarSlot = player.inventory.currentItem; int itemSlot = hotbarSlot == 0 ? 8 : hotbarSlot + 1; ItemStack nearbyStack = null; if (hotbarSlot < 8) { nearbyStack = player.inventory.getStackInSlot(itemSlot); if (nearbyStack != null) { Item item = nearbyStack.getItem(); if (item instanceof ItemBlock) { int posX = x; int posY = y; int posZ = z; int playerPosX = (int) Math.floor(player.posX); int playerPosY = (int) Math.floor(player.posY); int playerPosZ = (int) Math.floor(player.posZ); if (side == 0) { --posY; } if (side == 1) { ++posY; } if (side == 2) { --posZ; } if (side == 3) { ++posZ; } if (side == 4) { --posX; } if (side == 5) { ++posX; } if (posX == playerPosX && (posY == playerPosY || posY == playerPosY + 1 || posY == playerPosY - 1) && posZ == playerPosZ) { return false; } used = item.onItemUse(nearbyStack, player, world, x, y, z, side, clickX, clickY, clickZ); if (nearbyStack.stackSize < 1) { nearbyStack = null; player.inventory.setInventorySlotContents(itemSlot, null); } } } } /* if (used) //Update client { Packet103SetSlot packet = new Packet103SetSlot(player.openContainer.windowId, itemSlot, nearbyStack); ((EntityPlayerMP)player).playerNetServerHandler.sendPacketToPlayer(packet); } */ return used; } protected void breakExtraBlock(World world, int x, int y, int z, int sidehit, EntityPlayer player) { // prevent calling that stuff for air blocks, could lead to unexpected behaviour since it fires events if (world.isAirBlock(x, y, z)) return; // check if the block can be broken, since extra block breaks shouldn't instantly break stuff like obsidian // or precious ores you can't harvest while mining stone Block block = world.getBlock(x, y, z); int meta = world.getBlockMetadata(x, y, z); // only effective materials if (!isEffective(block.getMaterial())) return; // only harvestable blocks that aren't impossibly slow to harvest if (!ForgeHooks.canHarvestBlock(block, player, meta) || ForgeHooks.blockStrength(block, player, world, x, y, z) <= 0.0001f) return; if (player.capabilities.isCreativeMode) { block.onBlockHarvested(world, x, y, z, meta, player); if (block.removedByPlayer(world, player, x, y, z, false)) block.onBlockDestroyedByPlayer(world, x, y, z, meta); // send update to client if (!world.isRemote) { ((EntityPlayerMP)player).playerNetServerHandler.sendPacket(new S23PacketBlockChange(x, y, z, world)); } return; } // server sided handling if (!world.isRemote) { // serverside we EntityPlayerMP mpPlayer = (EntityPlayerMP) player; mpPlayer.theItemInWorldManager.tryHarvestBlock(x, y, z); // send block update to client mpPlayer.playerNetServerHandler.sendPacket(new S23PacketBlockChange(x, y, z, world)); } // client sided handling else { PlayerControllerMP pcmp = Minecraft.getMinecraft().playerController; // clientside we do a "this clock has been clicked on long enough to be broken" call. This should not send any new packets // the code above, executed on the server, sends a block-updates that give us the correct state of the block we destroy. pcmp.onPlayerDestroyBlock(x, y, z, sidehit); } } }