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.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.EnumAction;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundCategory;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import slimeknights.tconstruct.common.Sounds;
import slimeknights.tconstruct.library.client.BooleanItemPropertyGetter;
import slimeknights.tconstruct.library.client.crosshair.Crosshairs;
import slimeknights.tconstruct.library.client.crosshair.ICrosshair;
import slimeknights.tconstruct.library.client.crosshair.ICustomCrosshairUser;
import slimeknights.tconstruct.library.materials.BowMaterialStats;
import slimeknights.tconstruct.library.materials.BowStringMaterialStats;
import slimeknights.tconstruct.library.materials.ExtraMaterialStats;
import slimeknights.tconstruct.library.materials.HandleMaterialStats;
import slimeknights.tconstruct.library.materials.HeadMaterialStats;
import slimeknights.tconstruct.library.materials.Material;
import slimeknights.tconstruct.library.materials.MaterialTypes;
import slimeknights.tconstruct.library.tinkering.PartMaterialType;
import slimeknights.tconstruct.library.tools.ProjectileLauncherNBT;
import slimeknights.tconstruct.library.tools.ranged.BowCore;
import slimeknights.tconstruct.library.utils.TagUtil;
import slimeknights.tconstruct.library.utils.ToolHelper;
import slimeknights.tconstruct.tools.TinkerMaterials;
import slimeknights.tconstruct.tools.TinkerTools;
import slimeknights.tconstruct.tools.ranged.TinkerRangedWeapons;
public class CrossBow extends BowCore implements ICustomCrosshairUser {
private static final String TAG_Loaded = "Loaded";
protected static final ResourceLocation PROPERTY_IS_LOADED = new ResourceLocation("loaded");
public CrossBow() {
super(PartMaterialType.crossbow(TinkerTools.toughToolRod),
PartMaterialType.bow(TinkerTools.bowLimb),
PartMaterialType.extra(TinkerTools.toughBinding),
PartMaterialType.bowstring(TinkerTools.bowString));
this.addPropertyOverride(PROPERTY_PULL_PROGRESS, pullProgressPropertyGetter);
this.addPropertyOverride(PROPERTY_IS_PULLING, isPullingPropertyGetter);
this.addPropertyOverride(PROPERTY_IS_LOADED, new BooleanItemPropertyGetter() {
@Override
public boolean applyIf(ItemStack stack, @Nullable World worldIn, @Nullable EntityLivingBase entityIn) {
return entityIn != null && isLoaded(stack);
}
});
}
@Override
public void getSubItems(@Nonnull Item itemIn, CreativeTabs tab, List<ItemStack> subItems) {
addDefaultSubItems(subItems, null, null, null, TinkerMaterials.string);
}
@Override
public float damagePotential() {
return 1f;
}
@Override
public double attackSpeed() {
return 2;
}
@Override
public float baseProjectileDamage() {
return 3f;
}
@Override
protected float baseProjectileSpeed() {
return 7f;
}
@Override
public float projectileDamageModifier() {
return 1.3f;
}
@Override
public int getDrawTime() {
return 45;
}
public boolean isLoaded(ItemStack stack) {
return TagUtil.getTagSafe(stack).getBoolean(TAG_Loaded);
}
public void setLoaded(ItemStack stack, boolean isLoaded) {
NBTTagCompound tag = TagUtil.getTagSafe(stack);
tag.setBoolean(TAG_Loaded, isLoaded);
stack.setTagCompound(tag);
}
@Override
public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) {
// has to be done in onUpdate because onTickUsing is too early and gets overwritten. bleh.
preventSlowDown(entityIn, 0.195f);
super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected);
}
@Nonnull
@Override
public EnumAction getItemUseAction(ItemStack stack) {
return EnumAction.NONE;
}
@Nonnull
@Override
public ActionResult<ItemStack> onItemRightClick(@Nonnull ItemStack itemStackIn, World worldIn, EntityPlayer playerIn, EnumHand hand) {
if(isLoaded(itemStackIn) && !ToolHelper.isBroken(itemStackIn)) {
super.onPlayerStoppedUsing(itemStackIn, worldIn, playerIn, 0);
setLoaded(itemStackIn, false);
}
else {
return super.onItemRightClick(itemStackIn, worldIn, playerIn, hand);
}
return ActionResult.newResult(EnumActionResult.SUCCESS, itemStackIn);
}
@Override
public void onPlayerStoppedUsing(ItemStack stack, World worldIn, EntityLivingBase entityLiving, int timeLeft) {
if(!ToolHelper.isBroken(stack) && (entityLiving instanceof EntityPlayer)) {
int useTime = this.getMaxItemUseDuration(stack) - timeLeft;
if(getDrawbackProgress(stack, useTime) >= 1f) {
Sounds.PlaySoundForPlayer(entityLiving, Sounds.crossbow_reload, 1.5f, 0.9f + itemRand.nextFloat()*0.1f);
setLoaded(stack, true);
}
}
}
@Override
public void playShootSound(float power, World world, EntityPlayer entityPlayer) {
world.playSound(null, entityPlayer.posX, entityPlayer.posY, entityPlayer.posZ, SoundEvents.ENTITY_ARROW_SHOOT, SoundCategory.NEUTRAL, 1.0F, 0.5f + itemRand.nextFloat()*0.1f);
}
@Override
public ItemStack getAmmoToRender(ItemStack weapon, EntityLivingBase player) {
if(!isLoaded(weapon)) {
return null;
}
return super.getAmmoToRender(weapon, player);
}
private ImmutableList<Item> boltMatches = null;
@Override
protected List<Item> getAmmoItems() {
if(boltMatches == null) {
ImmutableList.Builder<Item> builder = ImmutableList.builder();
if(TinkerRangedWeapons.bolt != null) {
builder.add(TinkerRangedWeapons.bolt);
}
boltMatches = builder.build();
}
return boltMatches;
}
@Override
public ProjectileLauncherNBT buildTagData(List<Material> materials) {
ProjectileLauncherNBT data = new ProjectileLauncherNBT();
HandleMaterialStats body = materials.get(0).getStatsOrUnknown(MaterialTypes.HANDLE);
ExtraMaterialStats bodyExtra = materials.get(0).getStatsOrUnknown(MaterialTypes.EXTRA);
HeadMaterialStats head = materials.get(1).getStatsOrUnknown(MaterialTypes.HEAD);
BowMaterialStats limb = materials.get(1).getStatsOrUnknown(MaterialTypes.BOW);
ExtraMaterialStats binding = materials.get(2).getStatsOrUnknown(MaterialTypes.EXTRA);
BowStringMaterialStats bowstring = materials.get(3).getStatsOrUnknown(MaterialTypes.BOWSTRING);
data.head(head);
data.limb(limb);
data.extra(binding, bodyExtra);
data.handle(body);
data.bowstring(bowstring);
data.bonusDamage *= 1.5f;
return data;
}
@SideOnly(Side.CLIENT)
@Override
public ICrosshair getCrosshair(ItemStack itemStack, EntityPlayer player) {
return Crosshairs.T;
}
@SideOnly(Side.CLIENT)
@Override
public float getCrosshairState(ItemStack itemStack, EntityPlayer player) {
if(isLoaded(itemStack)) {
return 1f;
}
else if(player.getActiveItemStack() != itemStack) {
return 0f;
}
return getDrawbackProgress(itemStack, player);
}
}