package eiteam.esteemedinnovation.firearms.flintlock;
import eiteam.esteemedinnovation.api.ChargableUtility;
import eiteam.esteemedinnovation.api.Constants;
import eiteam.esteemedinnovation.api.Engineerable;
import eiteam.esteemedinnovation.api.enhancement.Enhancement;
import eiteam.esteemedinnovation.api.enhancement.EnhancementFirearm;
import eiteam.esteemedinnovation.api.enhancement.UtilEnhancements;
import eiteam.esteemedinnovation.api.entity.EntityMusketBall;
import eiteam.esteemedinnovation.api.util.ItemStackUtility;
import eiteam.esteemedinnovation.armor.ArmorModule;
import eiteam.esteemedinnovation.armor.exosuit.steam.ItemSteamExosuitArmor;
import eiteam.esteemedinnovation.commons.Config;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Enchantments;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.EnumAction;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.*;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.ArrowLooseEvent;
import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import static eiteam.esteemedinnovation.firearms.FirearmModule.*;
public class ItemFirearm extends Item implements Engineerable {
public float damage;
public int reloadTime;
public int shellCount;
public float accuracy;
public float knockback;
public boolean shotgun;
public Object repairMaterial;
/**
* Used only for the Reloading Holsters, hence why it is private. Don't make it public, as that
* could confuse other developers into thinking they should use it for things.
*/
private int ticksSinceReload;
public ItemFirearm(float damage, int reloadTime, float accuracy, float knockback, boolean shotgun, int shellCount) {
this(damage, reloadTime, accuracy, knockback, shotgun, shellCount, null);
}
public ItemFirearm(float damage, int reloadTime, float accuracy, float knockback, boolean shotgun, int shellCount, Object repair) {
maxStackSize = 1;
setMaxDamage(384);
this.damage = damage;
this.reloadTime = reloadTime;
this.accuracy = accuracy;
this.knockback = knockback;
this.shotgun = shotgun;
this.shellCount = shellCount;
this.repairMaterial = repair;
}
public static void initializeNBT(ItemStack stack) {
if (!stack.hasTagCompound()) {
stack.setTagCompound(new NBTTagCompound());
NBTTagCompound nbt = stack.getTagCompound();
nbt.setInteger("loaded", 0);
nbt.setInteger("numloaded", 0);
}
}
@Override
public void addInformation(ItemStack stack, EntityPlayer player, List<String> list, boolean advanced) {
if (UtilEnhancements.hasEnhancement(stack)) {
list.add(UtilEnhancements.getEnhancementDisplayText(stack));
}
super.addInformation(stack, player, list, advanced);
}
@Override
public void onUpdate(ItemStack stack, World world, Entity entity, int itemSlot, boolean isCurrentItem) {
super.onUpdate(stack, world, entity, itemSlot, isCurrentItem);
if (UtilEnhancements.hasEnhancement(stack)) {
UtilEnhancements.getEnhancementFromItem(stack).onWeaponUpdate(stack, world, entity, itemSlot, isCurrentItem);
}
// TODO: Move this out of ItemFirearm.
// Reloading Holster code.
if (!isCurrentItem && entity instanceof EntityPlayer && stack.hasTagCompound()) {
ticksSinceReload += 1;
NBTTagCompound nbt = stack.getTagCompound();
EntityPlayer player = (EntityPlayer) entity;
ItemStack legs = player.getItemStackFromSlot(EntityEquipmentSlot.LEGS);
if (legs != null && nbt.getInteger("loaded") < 1 && ticksSinceReload >= (reloadTime + 10)) {
Item legsItem = legs.getItem();
if (legsItem instanceof ItemSteamExosuitArmor) {
ItemSteamExosuitArmor legsArmor = (ItemSteamExosuitArmor) legsItem;
if (legsArmor.hasUpgrade(legs, ArmorModule.RELOADING_HOLSTERS) &&
ChargableUtility.hasPower(player, Config.reloadingConsumption) &&
ItemStackUtility.inventoryHasItem(player.inventory, MUSKET_CARTRIDGE)) {
onItemUseFinish(stack, world, player);
onItemRightClick(stack, world, player, player.getActiveHand());
ChargableUtility.drainSteam(player.getItemStackFromSlot(EntityEquipmentSlot.CHEST),
Config.reloadingConsumption, player);
ticksSinceReload = 0;
// TODO: Reload sound
// TODO: Out of ammo- cannot reload sound
}
}
}
}
}
@Override
public String getUnlocalizedName(ItemStack stack) {
if (UtilEnhancements.hasEnhancement(stack)) {
return UtilEnhancements.getNameFromEnhancement(stack);
} else {
return super.getUnlocalizedName(stack);
}
}
@Override
public void onPlayerStoppedUsing(ItemStack itemstack, World world, EntityLivingBase entity, int timeLeft) {
NBTTagCompound nbt = itemstack.getTagCompound();
boolean crouched = entity.isSneaking();
if (nbt.getInteger("loaded") > 0) {
float enhancementAccuracy = 0.0F;
float enhancementDamage = 0;
float enhancementKnockback = 0;
float crouchingBonus = crouched ? 0.10F : 0;
if (UtilEnhancements.hasEnhancement(itemstack)) {
Enhancement enhancement = UtilEnhancements.getEnhancementFromItem(itemstack);
if (UtilEnhancements.getEnhancementFromItem(itemstack) instanceof EnhancementFirearm) {
EnhancementFirearm enhancementFirearm = (EnhancementFirearm) enhancement;
enhancementAccuracy = enhancementFirearm.getAccuracyChange(this);
enhancementDamage = enhancementFirearm.getDamageChange(this);
enhancementKnockback = enhancementFirearm.getKnockbackChange(this);
}
}
int timeUsed = getMaxItemUseDuration(itemstack) - timeLeft;
if (entity instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) entity;
ArrowLooseEvent event = new ArrowLooseEvent(player, itemstack, world, timeUsed,
ItemStackUtility.inventoryHasItem(player.inventory, MUSKET_CARTRIDGE));
MinecraftForge.EVENT_BUS.post(event);
if (event.isCanceled()) {
return;
}
timeUsed = event.getCharge();
float timeUsedSecs = timeUsed / 20.0F;
timeUsedSecs = (timeUsedSecs * timeUsedSecs + timeUsedSecs * 2.0F) / 3.0F;
if (timeUsedSecs < 0.1D) {
return;
}
if (timeUsedSecs > 1.0F) {
timeUsedSecs = 1.0F;
}
EntityMusketBall musketBall = new EntityMusketBall(world, player, 2.0F, ((1.0F + accuracy + enhancementAccuracy - crouchingBonus) - timeUsedSecs), (damage + enhancementDamage), true);
if (UtilEnhancements.hasEnhancement(itemstack)) {
if (UtilEnhancements.getEnhancementFromItem(itemstack) instanceof EnhancementFirearm) {
musketBall = ((EnhancementFirearm) UtilEnhancements.getEnhancementFromItem(itemstack)).changeBullet(musketBall);
}
}
itemstack.damageItem(1, entity);
float vol = ((knockback + enhancementKnockback) * (2F / 5F)) * (UtilEnhancements.hasEnhancement(itemstack) ? UtilEnhancements.getEnhancementFromItem(itemstack).getVolume(itemstack, world, entity) : 1.0F);
float pitch = 1.0F / (itemRand.nextFloat() * 0.4F + 1.2F) + timeUsedSecs * 0.5F;
world.playSound(player, player.getPosition(), SoundEvents.ENTITY_GENERIC_EXPLODE, SoundCategory.PLAYERS, vol, pitch);
for (int i = 1; i < 16; i++) {
world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, entity.posX + itemRand.nextFloat() - 0.5F,
entity.posY + (itemRand.nextFloat() / 2) - 0.25F,
entity.posZ + itemRand.nextFloat() - 0.5F, 0D, 0.01D, 0D);
}
if (!world.isRemote) {
if (shotgun) {
for (int i = 1; i < 21; i++) {
EntityMusketBall shotgunRound = new EntityMusketBall(world, player, 2.0F,
(1.0F + accuracy + enhancementAccuracy - crouchingBonus) - timeUsedSecs,
(damage + enhancementDamage), false);
if (UtilEnhancements.hasEnhancement(itemstack)) {
if (UtilEnhancements.getEnhancementFromItem(itemstack) instanceof EnhancementFirearm) {
shotgunRound = ((EnhancementFirearm) UtilEnhancements.getEnhancementFromItem(itemstack)).changeBullet(shotgunRound);
}
}
world.spawnEntityInWorld(shotgunRound);
}
} else {
world.spawnEntityInWorld(musketBall);
}
}
nbt.setInteger("loaded", nbt.getInteger("loaded") - 1);
if (UtilEnhancements.hasEnhancement(itemstack)) {
UtilEnhancements.getEnhancementFromItem(itemstack).afterRoundFired(itemstack, world, player);
}
if (world.isRemote && !player.capabilities.isCreativeMode) {
float thiskb = this.knockback + enhancementKnockback;
boolean crouching = entity.isSneaking();
if (crouching) {
thiskb = thiskb / 2;
}
entity.rotationPitch = entity.rotationPitch - (thiskb * 3F);
entity.motionZ = -MathHelper.cos((entity.rotationYaw) * (float) Math.PI / 180.0F) * (thiskb * (4F / 50F));
entity.motionX = MathHelper.sin((entity.rotationYaw) * (float) Math.PI / 180.0F) * (thiskb * (4F / 50F));
}
}
} else if (nbt.getBoolean("done")) {
nbt.setInteger("loaded", nbt.getInteger("numloaded"));
nbt.setBoolean("done", false);
}
}
private int getEnhancementShells(ItemStack self) {
if (UtilEnhancements.hasEnhancement(self)) {
Enhancement enhancement = UtilEnhancements.getEnhancementFromItem(self);
if (enhancement instanceof EnhancementFirearm) {
EnhancementFirearm enhancementFirearm = (EnhancementFirearm) enhancement;
return enhancementFirearm.getClipSizeChange(this);
}
}
return 0;
}
@Override
public ItemStack onItemUseFinish(ItemStack stack, World world, EntityLivingBase entity) {
NBTTagCompound nbt = stack.getTagCompound();
if (!(entity instanceof EntityPlayer)) {
// ? Not sure what else to return here. Null?
return stack;
}
EntityPlayer player = (EntityPlayer) entity;
boolean infiniteShots = player.capabilities.isCreativeMode || EnchantmentHelper.getEnchantmentLevel(Enchantments.INFINITY, stack) > 0;
int enhancementShells = getEnhancementShells(stack);
if (infiniteShots || ItemStackUtility.inventoryHasItem(player.inventory, MUSKET_CARTRIDGE)) {
if (!nbt.getBoolean("done")) {
nbt.setInteger("numloaded", 1);
if (infiniteShots) {
nbt.setInteger("numloaded", shellCount + enhancementShells);
} else {
ItemStackUtility.consumePlayerInventoryItem(player.inventory, MUSKET_CARTRIDGE);
int totalShells = shellCount + enhancementShells;
if (totalShells > 1) {
for (int i = 1; i < totalShells; i++) {
if (ItemStackUtility.inventoryHasItem(player.inventory, MUSKET_CARTRIDGE)) {
ItemStackUtility.consumePlayerInventoryItem(player.inventory, MUSKET_CARTRIDGE);
nbt.setInteger("numloaded", nbt.getInteger("numloaded") + 1);
}
}
}
}
nbt.setBoolean("done", true);
float vol = UtilEnhancements.hasEnhancement(stack) ? UtilEnhancements.getEnhancementFromItem(stack).getVolume(stack, world, entity) : 1.0F;
float pitch = world.rand.nextFloat() * 0.1F + 0.9F;
world.playSound(player, player.getPosition(), SoundEvents.BLOCK_LEVER_CLICK, SoundCategory.PLAYERS, vol, pitch);
}
}
return stack;
}
@Override
public boolean isFull3D() {
return true;
}
@Override
public int getMaxItemUseDuration(ItemStack stack) {
initializeNBT(stack);
NBTTagCompound nbt = stack.getTagCompound();
int enhancementReload = 0;
if (UtilEnhancements.hasEnhancement(stack)) {
Enhancement enhancement = UtilEnhancements.getEnhancementFromItem(stack);
if (enhancement instanceof EnhancementFirearm) {
EnhancementFirearm enhancementFirearm = (EnhancementFirearm) enhancement;
enhancementReload = enhancementFirearm.getReloadChange(this);
}
}
if ((nbt.getInteger("loaded") > 0) || (nbt.getBoolean("done"))) {
return 72000;
} else {
return reloadTime + enhancementReload;
}
}
@Override
public EnumAction getItemUseAction(ItemStack stack) {
initializeNBT(stack);
NBTTagCompound nbt = stack.getTagCompound();
if (nbt.getInteger("loaded") > 0) {
return EnumAction.BOW;
} else {
return EnumAction.BLOCK;
}
}
@Override
public ActionResult<ItemStack> onItemRightClick(ItemStack itemStack, World world, EntityPlayer player, EnumHand hand) {
initializeNBT(itemStack);
NBTTagCompound nbt = itemStack.getTagCompound();
if (player.capabilities.isCreativeMode) {
int enhancementShells = getEnhancementShells(itemStack);
nbt.setInteger("loaded", 1);
nbt.setInteger("numloaded", shellCount + enhancementShells);
}
player.setActiveHand(hand);
return ActionResult.newResult(EnumActionResult.SUCCESS, itemStack);
}
// Note: The alternative to this warning is pretty horrible and like 3 lines longer, because generics are not invariant.
@SuppressWarnings("unchecked")
@Override
public Pair<Integer, Integer>[] engineerCoordinates() {
return new Pair[] { Pair.of(53, 29) };
}
@Override
public ItemStack getStackInSlot(ItemStack me, int var1) {
if (UtilEnhancements.hasEnhancement(me)) {
Item item = (Item) UtilEnhancements.getEnhancementFromItem(me);
return new ItemStack(item);
}
return null;
}
public static void initializeEnhancementsNBT(ItemStack me, ItemStack stack) {
if (!me.hasTagCompound()) {
me.setTagCompound(new NBTTagCompound());
}
if (stack != null) {
Enhancement enhancement = (Enhancement) stack.getItem();
NBTTagCompound enhancements = new NBTTagCompound();
enhancements.setString("id", enhancement.getID());
me.getTagCompound().setTag("enhancements", enhancements);
}
}
@Override
public void setInventorySlotContents(ItemStack me, int var1, ItemStack stack) {
initializeEnhancementsNBT(me, stack);
}
@Override
public boolean isItemValidForSlot(ItemStack me, int var1, ItemStack var2) {
return true;
}
@Override
public ItemStack decrStackSize(ItemStack me, int var1, int var2) {
if (UtilEnhancements.hasEnhancement(me)) {
Item item = (Item) UtilEnhancements.getEnhancementFromItem(me);
UtilEnhancements.removeEnhancement(me);
return new ItemStack(item);
}
return null;
}
@Override
public void drawSlot(GuiContainer guiEngineeringTable, int slotnum, int i, int j) {
guiEngineeringTable.mc.getTextureManager().bindTexture(Constants.ENG_GUI_TEXTURES);
guiEngineeringTable.drawTexturedModalRect(i, j, 176, 0, 18, 18);
}
@Override
public boolean canPutInSlot(ItemStack me, int slotNum, ItemStack upgrade) {
return upgrade.getItem() instanceof Enhancement && ((Enhancement) upgrade.getItem()).canApplyTo(me);
}
@Override
public boolean getIsRepairable(ItemStack toRepair, ItemStack repair) {
if (repairMaterial != null) {
if (repairMaterial instanceof ItemStack) {
return repair.isItemEqual((ItemStack) repairMaterial) || super.getIsRepairable(toRepair, repair);
}
if (repairMaterial instanceof String) {
return ItemStackUtility.isItemOreDictedAs(repair, (String) repairMaterial) || super.getIsRepairable(toRepair, repair);
}
}
return super.getIsRepairable(toRepair, repair);
}
@Override
public void drawBackground(GuiContainer guiEngineeringTable, int i, int j, int k) {
guiEngineeringTable.mc.getTextureManager().bindTexture(Constants.ENG_ARMOR_TEXTURES);
int textureX = 0;
if (this == MUSKET) {
textureX = 0;
} else if (this == BLUNDERBUSS) {
textureX = 64;
} else if (this == PISTOL) {
textureX = 128;
}
guiEngineeringTable.drawTexturedModalRect(j + 26, k + 3, textureX, 64, 64, 64);
}
}