package joshie.harvest.core.base.item;
import joshie.harvest.api.core.ITiered;
import joshie.harvest.core.HFCore;
import joshie.harvest.core.helpers.InventoryHelper;
import joshie.harvest.core.helpers.TextHelper;
import joshie.harvest.core.lib.CreativeSort;
import joshie.harvest.core.util.interfaces.ICreativeSorted;
import joshie.harvest.mining.HFMining;
import joshie.harvest.mining.item.ItemMaterial.Material;
import joshie.harvest.tools.ToolHelper;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.EnumAction;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.Locale;
import java.util.Set;
public abstract class ItemTool<I extends ItemTool> extends ItemHFBase<I> implements ITiered, ICreativeSorted {
private final Set<Block> effectiveBlocks;
final String toolClass;
/**
* Create a tool
*/
public ItemTool(String toolClass, Set<Block> effective) {
setMaxStackSize(1);
setHasSubtypes(true);
this.effectiveBlocks = effective;
this.toolClass = toolClass;
}
public ItemStack getStack(ToolTier tier) {
return new ItemStack(this, 1, tier.ordinal());
}
@Override
public int getSortValue(ItemStack stack) {
return CreativeSort.TOOLS + getTier(stack).ordinal();
}
@Override
@Nonnull
public String getUnlocalizedName(ItemStack stack) {
return super.getUnlocalizedName(stack) + "_" + getTier(stack).name().toLowerCase(Locale.ENGLISH);
}
@Override
public String getItemStackDisplayName(ItemStack stack) {
String text = TextHelper.localize(super.getUnlocalizedName().replace("item.", "") + "." + getTier(stack).name().toLowerCase(Locale.ENGLISH));
return !canUse(stack) ? TextHelper.translate("tool.broken") + " " + text : text;
}
@Override
public double getLevel(ItemStack stack) {
return stack.getSubCompound("Data", true).getDouble("Level");
}
@Override
public void levelTool(ItemStack stack) {
double level = stack.getSubCompound("Data", true).getDouble("Level");
double increase = getLevelIncrease(stack);
double newLevel = Math.min(100D, level + increase);
stack.getSubCompound("Data", true).setDouble("Level", newLevel);
}
@Override
public boolean setLevel(ItemStack stack, double newLevel) {
if (newLevel < 0D || newLevel > 100D) return false;
else {
stack.getSubCompound("Data", true).setDouble("Level", newLevel);
return true;
}
}
@Override
public ToolTier getTier(ItemStack stack) {
int safe = Math.min(Math.max(0, stack.getItemDamage()), (ToolTier.values().length - 1));
return ToolTier.values()[safe];
}
@Override
public boolean showDurabilityBar(ItemStack stack) {
return getDurabilityForDisplay(stack) > 0D;
}
@Override
public double getDurabilityForDisplay(ItemStack stack) {
return (double) getDamageForDisplay(stack) / (double)getMaximumToolDamage(stack);
}
public boolean canBeDamaged() {
return true;
}
public int getDamageForDisplay(ItemStack stack) {
int display = stack.getSubCompound("Data", true).getInteger("Damage");
int max = getMaximumToolDamage(stack);
if (display > max) {
stack.getSubCompound("Data", true).setInteger("Damage", max);
return max;
} else return display;
}
public boolean canUse(ItemStack stack) {
return getDamageForDisplay(stack) + 1 <= getMaximumToolDamage(stack) || !canBeDamaged();
}
public boolean canLevel(ItemStack stack, IBlockState state) {
for (String type : getToolClasses(stack)) {
if (state.getBlock().isToolEffective(type, state))
return true;
}
return effectiveBlocks.contains(state.getBlock());
}
@Override
public boolean onBlockDestroyed(ItemStack stack, World worldIn, IBlockState state, BlockPos pos, EntityLivingBase entityLiving) {
if (canUse(stack) && canBeDamaged()) {
if (canLevel(stack, state)) {
ToolHelper.levelTool(stack);
}
stack.getSubCompound("Data", true).setInteger("Damage", getDamageForDisplay(stack) + 1);
}
return true;
}
@Override
@Nonnull
public EnumAction getItemUseAction(ItemStack stack) {
return EnumAction.BOW;
}
@Override
public int getMaxItemUseDuration(ItemStack stack) {
return 32000;
}
public int getFront(ToolTier tier) {
return 0;
}
public int getSides(ToolTier tier) {
return 0;
}
public float getExhaustionRate(ItemStack stack) {
ToolTier tier = getTier(stack);
switch (tier) {
case BASIC:
return 3F;
case COPPER:
return 2.5F;
case SILVER:
case GOLD:
return 2F;
case MYSTRIL:
return 1.5F;
case CURSED:
return 25F;
case BLESSED:
return 1F;
case MYTHIC:
return 0.5F;
default:
return 1F;
}
}
private double getLevelIncrease(ItemStack stack) {
ToolTier tier = getTier(stack);
switch (tier) {
case BASIC:
return 0.39215682745098D;
case COPPER:
return 0.196078431372549D;
case SILVER:
case GOLD:
return 0.130718954248366D;
case MYSTRIL:
return 0.0980392156862745D;
case CURSED:
case BLESSED:
return 0.0784313725490196D;
case MYTHIC:
return 0.0392156862745098D;
default:
return 0;
}
}
public int getMaximumToolDamage(ItemStack stack) {
ToolTier tier = getTier(stack);
switch (tier) {
case BASIC:
return 128;
case COPPER:
return 256;
case SILVER:
return 768;
case GOLD:
return 1152;
case MYSTRIL:
return 3456;
case CURSED:
case BLESSED:
return 6912;
case MYTHIC:
return 13824;
default:
return 0;
}
}
protected float getEffiency(ItemStack stack) {
ToolTier tier = getTier(stack);
float effiency = 0F;
switch (tier) {
case BASIC:
effiency = 1.5F;
break;
case COPPER:
effiency = 2.5F;
break;
case SILVER:
effiency = 4F;
break;
case GOLD:
effiency = 7F;
break;
case MYSTRIL:
effiency = 10F;
break;
case CURSED:
case BLESSED:
effiency = 15F;
break;
case MYTHIC:
effiency = 20F;
break;
}
return (float) Math.max(effiency, ((getLevel(stack) + 1) /50F) * effiency);
}
@Override
@SuppressWarnings("deprecation")
public int getHarvestLevel(ItemStack stack, @Nonnull String toolClass) {
if (!toolClass.equals(this.toolClass)) return 0;
if (!canUse(stack)) return 0;
ToolTier tier = getTier(stack);
switch (tier) {
case BASIC:
return 1;
case COPPER:
return 2;
case SILVER:
return 3;
case GOLD:
return 4;
case MYSTRIL:
return 5;
case CURSED:
case BLESSED:
return 6;
case MYTHIC:
return 7;
default:
return 0;
}
}
protected int getXMinus(ToolTier tier, EnumFacing facing, int x) {
if (facing == EnumFacing.NORTH) {
return x - getSides(tier);
} else if (facing == EnumFacing.SOUTH) {
return x - getSides(tier);
} else if (facing == EnumFacing.EAST) {
return x - getFront(tier);
} else return x;
}
protected int getXPlus(ToolTier tier, EnumFacing facing, int x) {
if (facing == EnumFacing.NORTH) {
return x + getSides(tier);
} else if (facing == EnumFacing.SOUTH) {
return x + getSides(tier);
} else if (facing == EnumFacing.WEST) {
return x + getFront(tier);
} else return x;
}
protected int getZMinus(ToolTier tier, EnumFacing facing, int z) {
if (facing == EnumFacing.SOUTH) {
return z - getFront(tier);
} else if (facing == EnumFacing.WEST) {
return z - getSides(tier);
} else if (facing == EnumFacing.EAST) {
return z - getSides(tier);
} else return z;
}
protected int getZPlus(ToolTier tier, EnumFacing facing, int z) {
if (facing == EnumFacing.NORTH) {
return z + getFront(tier);
} else if (facing == EnumFacing.WEST) {
return z + getSides(tier);
} else if (facing == EnumFacing.EAST) {
return z + getSides(tier);
} else return z;
}
protected void displayParticle(World world, BlockPos pos, EnumParticleTypes particle, IBlockState state) {
for (int j = 0; j < 60D; j++) {
double d8 = (pos.getX()) + world.rand.nextFloat();
double d9 = (pos.getZ()) + world.rand.nextFloat();
world.spawnParticle(particle, d8, pos.getY() + 1.0D - 0.125D, d9, 0, 0, 0, Block.getStateId(state));
}
}
protected void playSound(World world, BlockPos pos, SoundEvent sound, SoundCategory category) {
world.playSound(null, pos, sound, category, world.rand.nextFloat() * 0.25F + 0.75F, world.rand.nextFloat() * 1.0F + 0.5F);
}
@Override
@SideOnly(Side.CLIENT)
public void getSubItems(@Nonnull Item item, CreativeTabs tab, List<ItemStack> list) {
for (int i = 0; i < ToolTier.values().length; i++) {
ItemStack stack = new ItemStack(item, 1, i);
stack.getSubCompound("Data", true).setInteger("Damage", 0);
list.add(stack);
}
}
@SideOnly(Side.CLIENT)
public boolean isFull3D() {
return true;
}
protected RayTraceResult getMovingObjectPositionFromPlayer(World world, EntityLivingBase entity) {
float f = entity.rotationPitch;
float f1 = entity.rotationYaw;
double d0 = entity.posX;
double d1 = entity.posY + (double)entity.getEyeHeight();
double d2 = entity.posZ;
Vec3d vec3 = new Vec3d(d0, d1, d2);
float f2 = MathHelper.cos(-f1 * 0.017453292F - (float)Math.PI);
float f3 = MathHelper.sin(-f1 * 0.017453292F - (float)Math.PI);
float f4 = -MathHelper.cos(-f * 0.017453292F);
float f5 = MathHelper.sin(-f * 0.017453292F);
float f6 = f3 * f4;
float f7 = f2 * f4;
double d3 = 5.0D;
if (entity instanceof EntityPlayerMP) {
d3 = ((EntityPlayerMP) entity).interactionManager.getBlockReachDistance();
}
Vec3d vec31 = vec3.addVector((double)f6 * d3, (double)f5 * d3, (double)f7 * d3);
return world.rayTraceBlocks(vec3, vec31, false, false, false);
}
//Tools
@Override
public boolean getIsRepairable(ItemStack toRepair, ItemStack repair) {
switch(getTier(toRepair)) {
case BASIC: return InventoryHelper.ORE_DICTIONARY.matches(repair, "stone");
case COPPER: return InventoryHelper.ITEM_STACK.matches(repair, HFMining.MATERIALS.getStackFromEnum(Material.COPPER));
case SILVER: return InventoryHelper.ITEM_STACK.matches(repair, HFMining.MATERIALS.getStackFromEnum(Material.SILVER));
case GOLD: return InventoryHelper.ITEM_STACK.matches(repair, HFMining.MATERIALS.getStackFromEnum(Material.GOLD));
case MYSTRIL: return InventoryHelper.ITEM_STACK.matches(repair, HFMining.MATERIALS.getStackFromEnum(Material.MYSTRIL));
case MYTHIC: return InventoryHelper.ITEM_STACK.matches(repair, HFMining.MATERIALS.getStackFromEnum(Material.MYTHIC));
default: return false;
}
}
@Override
@Nonnull
public Set<String> getToolClasses(ItemStack stack) {
return toolClass != null ? com.google.common.collect.ImmutableSet.of(toolClass) : super.getToolClasses(stack);
}
@Override
public float getStrVsBlock(ItemStack stack, IBlockState state) {
for (String type : getToolClasses(stack)) {
if (state.getBlock().isToolEffective(type, state))
return getEffiency(stack);
}
return this.effectiveBlocks.contains(state.getBlock()) ? getEffiency(stack) : 1.0F;
}
@SideOnly(Side.CLIENT)
@Override
public void addInformation(ItemStack stack, EntityPlayer playerIn, List<String> tooltip, boolean advanced) {
if (HFCore.DEBUG_MODE && advanced) {
tooltip.add("Damage: " + getDamageForDisplay(stack) + "/" + getMaximumToolDamage(stack));
tooltip.add("Level: " + getLevel(stack));
}
}
}