package slimeknights.tconstruct.tools.ranged.item;
import com.google.common.collect.ImmutableList;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntityEnderman;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EntityDamageSourceIndirect;
import net.minecraft.world.World;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Nonnull;
import slimeknights.tconstruct.common.config.Config;
import slimeknights.tconstruct.library.TinkerRegistry;
import slimeknights.tconstruct.library.entity.EntityProjectileBase;
import slimeknights.tconstruct.library.materials.ArrowShaftMaterialStats;
import slimeknights.tconstruct.library.materials.FletchingMaterialStats;
import slimeknights.tconstruct.library.materials.HeadMaterialStats;
import slimeknights.tconstruct.library.materials.Material;
import slimeknights.tconstruct.library.materials.MaterialTypes;
import slimeknights.tconstruct.library.tinkering.Category;
import slimeknights.tconstruct.library.tinkering.PartMaterialType;
import slimeknights.tconstruct.library.tools.IToolPart;
import slimeknights.tconstruct.library.tools.ProjectileNBT;
import slimeknights.tconstruct.library.tools.ranged.ProjectileCore;
import slimeknights.tconstruct.library.utils.TinkerUtil;
import slimeknights.tconstruct.shared.client.ParticleEffect;
import slimeknights.tconstruct.tools.TinkerMaterials;
import slimeknights.tconstruct.tools.TinkerTools;
import slimeknights.tconstruct.tools.common.entity.EntityArrow;
import slimeknights.tconstruct.tools.common.entity.EntityBolt;
import slimeknights.tconstruct.tools.melee.item.Rapier;
import slimeknights.tconstruct.tools.traits.TraitEnderference;
public class Bolt extends ProjectileCore {
protected final List<PartMaterialType> toolBuildComponents;
public Bolt() {
super(PartMaterialType.arrowShaft(TinkerTools.boltCore),
new BoltHeadPartMaterialType(TinkerTools.boltCore),
PartMaterialType.fletching(TinkerTools.fletching));
addCategory(Category.NO_MELEE, Category.PROJECTILE);
toolBuildComponents = ImmutableList.of(requiredComponents[0], requiredComponents[2]);
}
@Override
public List<PartMaterialType> getToolBuildComponents() {
return toolBuildComponents;
}
@Override
public void getSubItems(@Nonnull Item itemIn, CreativeTabs tab, List<ItemStack> subItems) {
for(Material head : TinkerRegistry.getAllMaterials()) {
List<Material> mats = new ArrayList<Material>(3);
if(head.hasStats(MaterialTypes.HEAD)) {
mats.add(TinkerMaterials.wood);
mats.add(head);
mats.add(TinkerMaterials.feather);
ItemStack tool = buildItem(mats);
// only valid ones
if(hasValidMaterials(tool)) {
subItems.add(tool);
if(!Config.listAllMaterials) {
break;
}
}
}
}
}
@Override
public Material getMaterialForPartForGuiRendering(int index) {
return super.getMaterialForPartForGuiRendering(index + 1);
}
@Override
public ItemStack buildItemForRenderingInGui() {
List<Material> materials = IntStream.range(0, getRequiredComponents().size())
.mapToObj(super::getMaterialForPartForGuiRendering)
.collect(Collectors.toList());
return buildItemForRendering(materials);
}
@Override
public float damagePotential() {
return 1f;
}
@Override
public double attackSpeed() {
return 1;
}
@Override
public ItemStack buildItemFromStacks(ItemStack[] stacks) {
if(stacks.length != 2) {
return null;
}
ItemStack boltCore = stacks[0];
ItemStack fletching = stacks[1];
// we only care about the material returned by getMaterial call
ItemStack boltCoreHead = BoltCore.getHeadStack(boltCore);
return super.buildItemFromStacks(new ItemStack[]{boltCore, boltCoreHead, fletching});
}
@Override
public boolean dealDamageRanged(ItemStack stack, Entity projectile, EntityLivingBase player, Entity target, float damage) {
// friggin vanilla hardcode 2
if(target instanceof EntityEnderman && ((EntityEnderman) target).getActivePotionEffect(TraitEnderference.Enderference) != null) {
return target.attackEntityFrom(new DamageSourceProjectileForEndermen(DAMAGE_TYPE_PROJECTILE, projectile, player), damage);
}
DamageSource damageSource = new EntityDamageSourceIndirect(DAMAGE_TYPE_PROJECTILE, projectile, player).setProjectile();
return Rapier.dealHybridDamage(damageSource, target, damage);
}
@Override
public ProjectileNBT buildTagData(List<Material> materials) {
ProjectileNBT data = new ProjectileNBT();
ArrowShaftMaterialStats shaft = materials.get(0).getStatsOrUnknown(MaterialTypes.SHAFT);
HeadMaterialStats head = materials.get(1).getStatsOrUnknown(MaterialTypes.HEAD);
FletchingMaterialStats fletching = materials.get(2).getStatsOrUnknown(MaterialTypes.FLETCHING);
data.head(head);
data.fletchings(fletching);
data.shafts(this, shaft);
data.durability *= 0.8f;
return data;
}
@Override
public EntityProjectileBase getProjectile(ItemStack stack, ItemStack bow, World world, EntityPlayer player, float speed, float inaccuracy, float power, boolean usedAmmo) {
inaccuracy -= (1f - 1f/ProjectileNBT.from(stack).accuracy) * speed/2f;
return new EntityBolt(world, player, speed, inaccuracy, power, getProjectileStack(stack, world, player, usedAmmo), bow);
}
private static class BoltHeadPartMaterialType extends PartMaterialType {
public BoltHeadPartMaterialType(IToolPart part) {
super(part, MaterialTypes.HEAD);
}
@Override
public boolean isValidMaterial(Material material) {
return material.isCastable() && super.isValidMaterial(material);
}
}
}