package joshie.harvest.tools.item; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import joshie.harvest.api.gathering.ISmashable.ToolType; import joshie.harvest.core.HFTab; import joshie.harvest.core.base.item.ItemToolSmashing; import joshie.harvest.core.helpers.TextHelper; import joshie.harvest.core.lib.HFSounds; import joshie.harvest.tools.item.TreeTasks.ChopTree; import joshie.harvest.tools.item.TreeTasks.TreeReplace; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.SoundCategory; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import javax.annotation.Nonnull; import java.util.List; import java.util.Set; import java.util.Stack; import static joshie.harvest.api.core.ITiered.ToolTier.BASIC; public class ItemAxe extends ItemToolSmashing<ItemAxe> { private static final Set<Block> EFFECTIVE_ON = Sets.newHashSet(Blocks.PLANKS, Blocks.BOOKSHELF, Blocks.LOG, Blocks.LOG2, Blocks.CHEST, Blocks.PUMPKIN, Blocks.LIT_PUMPKIN, Blocks.MELON_BLOCK, Blocks.LADDER, Blocks.WOODEN_BUTTON, Blocks.WOODEN_PRESSURE_PLATE); private static final float[] ATTACK_SPEEDS = new float[] { -3.2F, -3.1F, -3.1F, -3.0F, -3.0F, -2.9F, -2.9F, -2.8F}; public ItemAxe() { super("axe", EFFECTIVE_ON); setCreativeTab(HFTab.GATHERING); } @Override public ToolType getToolType() { return ToolType.AXE; } private boolean isWood(World world, BlockPos pos) { return world.getBlockState(pos).getBlock().isWood(world, pos); } @Override public boolean onBlockStartBreak(ItemStack stack, BlockPos pos, EntityPlayer player) { if (!player.isSneaking() && findTree(player.worldObj, pos)) { if (canChopTree(player, stack, pos)) return chopTree(pos, player, stack); else if (isWood(player.worldObj, pos)) return replaceTree(pos, player); } return false; } private int getHitsRequired(ItemStack stack) { switch (getTier(stack)) { case BASIC: return 6; case COPPER: return 5; case SILVER: return 4; case GOLD: return 3; case MYSTRIL: return 2; case CURSED: case BLESSED: return 1; case MYTHIC: return 0; default: return 7; } } private boolean canChopTree(EntityPlayer player, ItemStack stack, BlockPos pos) { NBTTagCompound tag = stack.getSubCompound("Chopping", true); if (tag.hasKey("Block")) { BlockPos internal = BlockPos.fromLong(tag.getLong("Block")); if (internal.equals(pos)) { int times = tag.getInteger("Times"); tag.setInteger("Times", times + 1); player.worldObj.playSound(null, pos, HFSounds.TREE_CHOP, SoundCategory.BLOCKS, (player.worldObj.rand.nextFloat() * 0.25F) * times * 10F, player.worldObj.rand.nextFloat() * 1.0F + 0.5F); return times >= getHitsRequired(stack); } } int times = 1; tag.setLong("Block", pos.toLong()); tag.setInteger("Times", times); player.worldObj.playSound(null, pos, HFSounds.TREE_CHOP, SoundCategory.BLOCKS, (player.worldObj.rand.nextFloat() * 0.25F) * times * 10F, player.worldObj.rand.nextFloat() * 1.0F + 0.5F); return times > getHitsRequired(stack); } private boolean chopTree(BlockPos pos, EntityPlayer player, ItemStack stack) { NBTTagCompound tag = stack.getSubCompound("Chopping", true); tag.removeTag("Block"); //Remove the data now we're chopping tag.removeTag("Times"); //Remove the data now we're chopping if(player.worldObj.isRemote) return true; MinecraftForge.EVENT_BUS.register(new ChopTree(pos, player, stack)); player.worldObj.playSound(null, pos, HFSounds.TREE_FALL, SoundCategory.BLOCKS, player.worldObj.rand.nextFloat() * 0.25F, player.worldObj.rand.nextFloat() * 1.0F + 0.5F); return true; } private boolean replaceTree(BlockPos pos, EntityPlayer player) { if(player.worldObj.isRemote) return true; MinecraftForge.EVENT_BUS.register(new TreeReplace(player.worldObj, pos, player.worldObj.getBlockState(pos))); return true; } //Borrowed from Tinkers Construct by boni private boolean findTree(World world, BlockPos origin) { BlockPos pos = null; Stack<BlockPos> candidates = new Stack<>(); candidates.add(origin); while(!candidates.isEmpty()) { BlockPos candidate = candidates.pop(); if((pos == null || candidate.getY() > pos.getY()) && world.getBlockState(candidate).getBlock().isWood(world, candidate)) { pos = candidate.up(); while(world.getBlockState(pos).getBlock().isWood(world, pos)) { pos = pos.up(); } candidates.add(pos.north()); candidates.add(pos.east()); candidates.add(pos.south()); candidates.add(pos.west()); } } if(pos == null) return false; int d = 5; int o = -1; // -(d-1)/2 int leaves = 0; for(int x = 0; x < d; x++) { for(int y = 0; y < d; y++) { for(int z = 0; z < d; z++) { BlockPos leaf = pos.add(o + x, o + y, o + z); IBlockState state = world.getBlockState(leaf); if (state.getBlock().isLeaves(state, world, leaf)) { if (++leaves >= 5) return true; } } } } return false; } @Override public void playSound(World world, BlockPos pos) { world.playSound(null, pos, HFSounds.SMASH_WOOD, SoundCategory.BLOCKS, world.rand.nextFloat() * 0.25F, world.rand.nextFloat() * 1.0F + 0.5F); } @Override public float getStrVsBlock(ItemStack stack, IBlockState state) { if (canUse(stack)) { Material material = state.getMaterial(); return material != Material.WOOD && material != Material.PLANTS && material != Material.VINE ? super.getStrVsBlock(stack, state) : this.getEffiency(stack); } else return 0.05F; } @Override @Nonnull public Multimap<String, AttributeModifier> getAttributeModifiers(@Nonnull EntityEquipmentSlot slot, ItemStack stack) { Multimap<String, AttributeModifier> multimap = super.getAttributeModifiers(slot, stack); ToolTier tier = getTier(stack); if (slot == EntityEquipmentSlot.MAINHAND) { multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getAttributeUnlocalizedName(), new AttributeModifier(ATTACK_DAMAGE_MODIFIER, "Tool modifier", (double)(tier == BASIC ? 6F : 8F), 0)); multimap.put(SharedMonsterAttributes.ATTACK_SPEED.getAttributeUnlocalizedName(), new AttributeModifier(ATTACK_SPEED_MODIFIER, "Tool modifier", (double)ATTACK_SPEEDS[tier.ordinal()], 0)); } return multimap; } @Override @SideOnly(Side.CLIENT) public void addInformation(ItemStack stack, EntityPlayer player, List<String> list, boolean flag) { super.addInformation(stack, player, list, flag); list.add(TextFormatting.AQUA + "" + TextFormatting.ITALIC + TextHelper.translate("axe.tooltip.sneak")); list.add(TextFormatting.GREEN + TextHelper.formatHF("axe.tooltip.chops", getHitsRequired(stack) + 1)); } }