package joshie.harvest.tools.item;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import joshie.harvest.api.core.Ore;
import joshie.harvest.api.crops.WateringHandler;
import joshie.harvest.api.gathering.ISmashable.ToolType;
import joshie.harvest.core.HFTab;
import joshie.harvest.core.base.item.ItemToolSmashing;
import joshie.harvest.core.helpers.EntityHelper;
import joshie.harvest.core.helpers.TextHelper;
import joshie.harvest.core.lib.HFSounds;
import joshie.harvest.core.util.holders.HolderRegistrySet;
import joshie.harvest.crops.CropHelper;
import joshie.harvest.tools.ToolHelper;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.EntityLivingBase;
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.util.EnumFacing;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import static net.minecraft.block.Block.spawnAsEntity;
public class ItemHammer extends ItemToolSmashing<ItemHammer> {
private static final Set<Block> EFFECTIVE_ON = Sets.newHashSet(Blocks.ACTIVATOR_RAIL, Blocks.COAL_ORE, Blocks.COBBLESTONE, Blocks.DETECTOR_RAIL, Blocks.DIAMOND_BLOCK, Blocks.DIAMOND_ORE, Blocks.DOUBLE_STONE_SLAB, Blocks.GOLDEN_RAIL, Blocks.GOLD_BLOCK, Blocks.GOLD_ORE, Blocks.ICE, Blocks.IRON_BLOCK, Blocks.IRON_ORE, Blocks.LAPIS_BLOCK, Blocks.LAPIS_ORE, Blocks.LIT_REDSTONE_ORE, Blocks.MOSSY_COBBLESTONE, Blocks.NETHERRACK, Blocks.PACKED_ICE, Blocks.RAIL, Blocks.REDSTONE_ORE, Blocks.SANDSTONE, Blocks.RED_SANDSTONE, Blocks.STONE, Blocks.STONE_SLAB, Blocks.STONE_BUTTON, Blocks.STONE_PRESSURE_PLATE);
private static final double[] ATTACK_DAMAGES = new double[] { 3D, 3.5D, 4D, 4.5D, 5D, 5.5D, 5.5D, 6D};
private final HolderRegistrySet blocks = new HolderRegistrySet();
public ItemHammer() {
super("pickaxe", EFFECTIVE_ON);
setCreativeTab(HFTab.MINING);
blocks.register(Ore.of("stone"));
blocks.register(Ore.of("blockLimestone"));
blocks.register(Ore.of("blockMarble"));
}
@Override
public ToolType getToolType() {
return ToolType.HAMMER;
}
private int getWidthAndHeight(ToolTier tier) {
switch (tier) {
case COPPER:
case SILVER:
return 0;
case GOLD:
case MYSTRIL:
case CURSED:
case BLESSED:
case MYTHIC:
return 1;
default: return 0;
}
}
private int getDepth(ToolTier tier) {
switch (tier) {
case SILVER:
case MYSTRIL:
return 2;
case CURSED:
case BLESSED:
return 5;
case MYTHIC:
return 11;
default: return 0;
}
}
@Override
public boolean onBlockDestroyed(ItemStack stack, World worldIn, IBlockState state, BlockPos position, EntityLivingBase entityLiving) {
if (entityLiving instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) entityLiving;
if (canUse(stack) && canBeDamaged()) {
if (canLevel(stack, state)) ToolHelper.levelTool(stack);
ArrayList<ItemStack> drops = new ArrayList<>();
for (BlockPos pos : getBlocks(worldIn, position, player, stack)) {
if (canUse(stack) && canBeDamaged()) {
ToolHelper.performTask(player, stack, this);
ToolHelper.collectDrops(worldIn, pos, worldIn.getBlockState(pos), player, drops);
worldIn.setBlockToAir(pos); //No particles
} else break; //Exist since we can't damage anymore
}
drops.stream().forEach(item -> spawnAsEntity(worldIn, new BlockPos(player), item));
}
return true;
} else return false;
}
@SuppressWarnings("ConstantConditions")
public ImmutableList<BlockPos> getBlocks(World world, BlockPos position, EntityPlayer player, ItemStack tool) {
ToolTier tier = getTier(tool);
IBlockState state = world.getBlockState(position);
ItemStack stackState = ToolHelper.getStackFromBlockState(state);
if (stackState == null) return ImmutableList.of();
if (!blocks.contains(stackState)) return ImmutableList.of();
if (tier == ToolTier.BASIC || player.isSneaking()) return ImmutableList.of(position);
RayTraceResult rt = rayTrace(world, player, true);
if (rt == null || !position.equals(rt.getBlockPos())) {
rt = rayTrace(world, player, false);
if (rt == null || !position.equals(rt.getBlockPos())) {
return ImmutableList.of();
}
}
EnumFacing front = rt.sideHit;
ImmutableList.Builder<BlockPos> builder = ImmutableList.builder();
for (int horizontal = -getWidthAndHeight(tier); horizontal <= getWidthAndHeight(tier); horizontal++) {
for (int vertical = -1; vertical <= getWidthAndHeight(tier); vertical++) {
for (int depth = 0; depth <= getDepth(tier); depth++) {
BlockPos pos = front == EnumFacing.EAST || front == EnumFacing.WEST ?
new BlockPos(position.getX() + ((front == EnumFacing.WEST) ? depth : -depth), position.getY() + vertical, position.getZ() + horizontal) :
new BlockPos(position.getX() + horizontal, position.getY() + vertical, position.getZ() + + ((front == EnumFacing.NORTH) ? depth : -depth));
if (front == EnumFacing.DOWN || front == EnumFacing.UP) {
EnumFacing playerFacing = EntityHelper.getFacingFromEntity(player);
if (playerFacing == EnumFacing.EAST) {
pos = new BlockPos(position.getX() - vertical, position.getY() + (front == EnumFacing.UP ? -depth: depth), position.getZ() + horizontal);
} else if (playerFacing == EnumFacing.WEST) {
pos = new BlockPos(position.getX() + vertical, position.getY() + (front == EnumFacing.UP ? -depth: depth), position.getZ() + horizontal);
} else if (playerFacing == EnumFacing.SOUTH) {
pos = new BlockPos(position.getX() + horizontal, position.getY() + (front == EnumFacing.UP ? -depth: depth), position.getZ() - vertical);
} else if (playerFacing == EnumFacing.NORTH) {
pos = new BlockPos(position.getX() + horizontal, position.getY() + (front == EnumFacing.UP ? -depth: depth), position.getZ() + vertical);
}
}
if (world.getBlockState(pos).getBlock() == Blocks.STONE) {
builder.add(pos);
}
}
}
}
return builder.build();
}
@Override
public void playSound(World world, BlockPos pos) {
world.playSound(null, pos, HFSounds.SMASH_ROCK, SoundCategory.BLOCKS, world.rand.nextFloat() * 0.45F, 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.IRON && material != Material.ANVIL && material != Material.ROCK ? super.getStrVsBlock(stack, state) : this.getEffiency(stack);
} else return 0.05F;
}
@Override
public boolean onSmashed(EntityPlayer player, ItemStack stack, ToolTier tier, int harvestLevel, World world, BlockPos pos, IBlockState state) {
if (canUse(stack) && !world.isRemote) {
WateringHandler handler = CropHelper.getWateringHandler(world, pos, state);
if (handler != null) {
ToolHelper.performTask(player, stack, this);
handler.dehydrate(world, pos, state, true);
return true;
}
}
return super.onSmashed(player, stack, tier, harvestLevel, world, pos, state);
}
@Override
@Nonnull
public CreativeTabs[] getCreativeTabs() {
return new CreativeTabs[]{ getCreativeTab(), HFTab.GATHERING };
}
@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", ATTACK_DAMAGES[tier.ordinal()], 0));
multimap.put(SharedMonsterAttributes.ATTACK_SPEED.getAttributeUnlocalizedName(), new AttributeModifier(ATTACK_SPEED_MODIFIER, "Tool modifier", -3.0D, 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);
ToolTier tier = getTier(stack);
if (getFront(tier) > 0) {
int area = (1 + (getFront(tier) * 2));
list.add(TextFormatting.DARK_GREEN + TextHelper.formatHF("hammer.tooltip.smash", area, area));
}
int width = getWidthAndHeight(tier) == 0 ? 1 : 3;
int height = tier == ToolTier.BASIC ? 1: getWidthAndHeight(tier) == 0 ? 2 : 3;
int depth = getDepth(tier) + 1;
list.add(TextFormatting.GOLD + TextHelper.formatHF("hammer.tooltip.dimensions", width, height, depth));
list.add(TextFormatting.AQUA + "" + TextFormatting.ITALIC + TextHelper.translate("hammer.tooltip.titles"));
}
}