package blusunrize.immersiveengineering.common.items;
import blusunrize.immersiveengineering.api.Lib;
import blusunrize.immersiveengineering.api.energy.immersiveflux.IFluxContainerItem;
import blusunrize.immersiveengineering.api.shader.CapabilityShader;
import blusunrize.immersiveengineering.api.shader.CapabilityShader.ShaderWrapper;
import blusunrize.immersiveengineering.api.shader.CapabilityShader.ShaderWrapper_Item;
import blusunrize.immersiveengineering.api.tool.ITool;
import blusunrize.immersiveengineering.api.tool.RailgunHandler;
import blusunrize.immersiveengineering.api.tool.ZoomHandler.IZoomTool;
import blusunrize.immersiveengineering.client.models.IOBJModelCallback;
import blusunrize.immersiveengineering.common.Config.IEConfig;
import blusunrize.immersiveengineering.common.entities.EntityRailgunShot;
import blusunrize.immersiveengineering.common.gui.IESlot;
import blusunrize.immersiveengineering.common.util.IEAchievements;
import blusunrize.immersiveengineering.common.util.IESounds;
import blusunrize.immersiveengineering.common.util.ItemNBTHelper;
import blusunrize.immersiveengineering.common.util.Utils;
import blusunrize.immersiveengineering.common.util.chickenbones.Matrix4;
import cofh.api.energy.IEnergyContainerItem;
import com.google.common.base.Optional;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.EnumAction;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.model.TRSRTransformation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import java.util.HashSet;
import java.util.List;
public class ItemRailgun extends ItemUpgradeableTool implements IFluxContainerItem,IEnergyContainerItem, IZoomTool, ITool, IOBJModelCallback<ItemStack>
{
public ItemRailgun()
{
super("railgun", 1, "RAILGUN");
}
@Override
public int getInternalSlots(ItemStack stack)
{
return 2+1;
}
@Override
public Slot[] getWorkbenchSlots(Container container, ItemStack stack, IInventory invItem)
{
return new Slot[]
{
new IESlot.Upgrades(container, invItem,0, 80,32, "RAILGUN", stack, true),
new IESlot.Upgrades(container, invItem,1,100,32, "RAILGUN", stack, true)
};
}
@Override
public boolean canModify(ItemStack stack)
{
return true;
}
@Override
public void recalculateUpgrades(ItemStack stack)
{
super.recalculateUpgrades(stack);
if(this.getEnergyStored(stack)>this.getMaxEnergyStored(stack))
ItemNBTHelper.setInt(stack, "energy", this.getMaxEnergyStored(stack));
}
@Override
public void clearUpgrades(ItemStack stack)
{
super.clearUpgrades(stack);
if(this.getEnergyStored(stack)>this.getMaxEnergyStored(stack))
ItemNBTHelper.setInt(stack, "energy", this.getMaxEnergyStored(stack));
}
@Override
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged)
{
if(slotChanged)
return true;
if(oldStack.hasCapability(CapabilityShader.SHADER_CAPABILITY,null) && newStack.hasCapability(CapabilityShader.SHADER_CAPABILITY,null))
{
ShaderWrapper wrapperOld = oldStack.getCapability(CapabilityShader.SHADER_CAPABILITY,null);
ShaderWrapper wrapperNew = newStack.getCapability(CapabilityShader.SHADER_CAPABILITY,null);
if(!ItemStack.areItemStacksEqual(wrapperOld.getShaderItem(), wrapperNew.getShaderItem()))
return true;
}
return super.shouldCauseReequipAnimation(oldStack,newStack,slotChanged);
}
@Override
public ICapabilityProvider initCapabilities(ItemStack stack, NBTTagCompound nbt)
{
return new ICapabilityProvider()
{
ShaderWrapper_Item shaders = new ShaderWrapper_Item("immersiveengineering:railgun", stack);
@Override
public boolean hasCapability(Capability<?> capability, EnumFacing facing)
{
return capability== CapabilityShader.SHADER_CAPABILITY;
}
@Override
public <T> T getCapability(Capability<T> capability, EnumFacing facing)
{
if(capability==CapabilityShader.SHADER_CAPABILITY)
return (T)shaders;
return null;
}
};
}
@Override
public void addInformation(ItemStack stack, EntityPlayer player, List list, boolean adv)
{
String stored = this.getEnergyStored(stack)+"/"+this.getMaxEnergyStored(stack);
list.add(I18n.format(Lib.DESC+"info.energyStored", stored));
}
@Override
public String getUnlocalizedName(ItemStack stack)
{
// if(stack.getItemDamage()!=1)
// {
// String tag = getRevolverDisplayTag(stack);
// if(!tag.isEmpty())
// return this.getUnlocalizedName()+"."+tag;
// }
return super.getUnlocalizedName(stack);
}
@Override
public boolean isFull3D()
{
return true;
}
// @Override
// public Multimap getAttributeModifiers(ItemStack stack)
// {
// Multimap multimap = super.getAttributeModifiers(stack);
// double melee = getUpgrades(stack).getDouble("melee");
// if(melee!=0)
// multimap.put(SharedMonsterAttributes.attackDamage.getAttributeUnlocalizedName(), new AttributeModifier(field_111210_e, "Weapon modifier", melee, 0));
// double speed = getUpgrades(stack).getDouble("speed");
// if(speed!=0)
// multimap.put(SharedMonsterAttributes.movementSpeed.getAttributeUnlocalizedName(), new AttributeModifier(field_111210_e, "Weapon modifier", speed, 1));
// return multimap;
// }
@Override
public EnumAction getItemUseAction(ItemStack p_77661_1_)
{
return EnumAction.NONE;
}
@Override
public void onUpdate(ItemStack stack, World world, Entity ent, int slot, boolean inHand)
{
// if(!world.isRemote && stack.getItemDamage()!=1 && ent!=null && ItemNBTHelper.hasKey(stack, "blocked"))
// {
// int l = ItemNBTHelper.handleDelayedSoundsForStack(stack, "casings", ent);
// if(l==0)
// ItemNBTHelper.setDelayedSoundsForStack(stack, "cylinderFill", "tile.piston.in",.3f,3, 1,6,1);
// l = ItemNBTHelper.handleDelayedSoundsForStack(stack, "cylinderFill", ent);
// if(l==0)
// ItemNBTHelper.setDelayedSoundsForStack(stack, "cylinderClose", "fire.ignite",.6f,5, 1,6,1);
// l = ItemNBTHelper.handleDelayedSoundsForStack(stack, "cylinderClose", ent);
// if(l==0)
// ItemNBTHelper.setDelayedSoundsForStack(stack, "cylinderSpin", "note.hat",.1f,5, 5,8,1);
// l = ItemNBTHelper.handleDelayedSoundsForStack(stack, "cylinderSpin", ent);
// if(l==0)
// ItemNBTHelper.remove(stack, "blocked");
// }
}
@Override
public ActionResult<ItemStack> onItemRightClick(ItemStack stack, World world, EntityPlayer player, EnumHand hand)
{
int energy = IEConfig.Tools.railgun_consumption;
float energyMod = 1 + this.getUpgrades(stack).getFloat("consumption");
energy = (int)(energy*energyMod);
if(this.extractEnergy(stack, energy, true)==energy && findAmmo(player)!=null)
{
player.setActiveHand(hand);
player.playSound(getChargeTime(stack) <= 20 ? IESounds.chargeFast : IESounds.chargeSlow, 1.5f, 1);
return new ActionResult(EnumActionResult.SUCCESS, stack);
}
return new ActionResult(EnumActionResult.PASS, stack);
}
@Override
public void onUsingTick(ItemStack stack, EntityLivingBase user, int count)
{
int inUse = this.getMaxItemUseDuration(stack)-count;
if(inUse>getChargeTime(stack) && inUse%20 == user.getRNG().nextInt(20))
user.playSound(IESounds.spark, .8f+(.2f*user.getRNG().nextFloat()), .5f+(.5f*user.getRNG().nextFloat()));
}
@Override
public void onPlayerStoppedUsing(ItemStack stack, World world, EntityLivingBase user, int timeLeft)
{
if(user instanceof EntityPlayer)
{
int inUse = this.getMaxItemUseDuration(stack) - timeLeft;
ItemNBTHelper.remove(stack, "inUse");
if (inUse < getChargeTime(stack))
return;
int energy = IEConfig.Tools.railgun_consumption;
float energyMod = 1 + this.getUpgrades(stack).getFloat("consumption");
energy = (int) (energy * energyMod);
if (this.extractEnergy(stack, energy, true) == energy)
{
ItemStack ammo = findAmmo((EntityPlayer)user);
if(ammo!=null)
{
Vec3d vec = user.getLookVec();
float speed = 20;
EntityRailgunShot shot = new EntityRailgunShot(user.worldObj, user, vec.xCoord * speed, vec.yCoord * speed, vec.zCoord * speed, Utils.copyStackWithAmount(ammo, 1));
ammo.stackSize--;
if(ammo.stackSize<=0)
((EntityPlayer)user).inventory.deleteStack(ammo);
user.playSound(IESounds.railgunFire, 1, .5f + (.5f * user.getRNG().nextFloat()));
this.extractEnergy(stack, energy, false);
if (!world.isRemote)
user.worldObj.spawnEntityInWorld(shot);
}
}
}
}
public static ItemStack findAmmo(EntityPlayer player)
{
if(isAmmo(player.getHeldItem(EnumHand.OFF_HAND)))
return player.getHeldItem(EnumHand.OFF_HAND);
else if(isAmmo(player.getHeldItem(EnumHand.MAIN_HAND)))
return player.getHeldItem(EnumHand.MAIN_HAND);
else
for(int i=0; i<player.inventory.getSizeInventory(); i++)
{
ItemStack itemstack = player.inventory.getStackInSlot(i);
if(isAmmo(itemstack))
return itemstack;
}
return null;
}
public static boolean isAmmo(ItemStack stack)
{
if(stack == null)
return false;
RailgunHandler.RailgunProjectileProperties prop = RailgunHandler.getProjectileProperties(stack);
return prop!=null;
}
public int getChargeTime(ItemStack railgun)
{
return (int)(40/(1+this.getUpgrades(railgun).getFloat("speed")));
}
@Override
public int getMaxItemUseDuration(ItemStack stack)
{
return 72000;
}
@Override
public void removeFromWorkbench(EntityPlayer player, ItemStack stack)
{
ItemStack[] contents = this.getContainedItems(stack);
player.addStat(IEAchievements.craftRailgun);
// if(contents[18]!=null&&contents[19]!=null)
// player.triggerAchievement(IEAchievements.upgradeRailgun);
}
@Override
public int receiveEnergy(ItemStack container, int energy, boolean simulate)
{
return ItemNBTHelper.insertFluxItem(container, energy, getMaxEnergyStored(container), simulate);
}
@Override
public int extractEnergy(ItemStack container, int energy, boolean simulate)
{
return ItemNBTHelper.extractFluxFromItem(container, energy, simulate);
}
@Override
public int getEnergyStored(ItemStack container)
{
return ItemNBTHelper.getFluxStoredInItem(container);
}
@Override
public int getMaxEnergyStored(ItemStack container)
{
return 8000+this.getUpgrades(container).getInteger("capacity");
}
public String[] compileRender(ItemStack stack)
{
HashSet<String> render = new HashSet<String>();
render.add("frame");
render.add("barrel");
render.add("grip");
render.add("capacitors");
render.add("sled");
render.add("wires");
NBTTagCompound upgrades = this.getUpgrades(stack);
if(upgrades.getDouble("speed")>0)
render.add("upgrade_speed");
if(upgrades.getBoolean("scope"))
render.add("upgrade_scope");
return render.toArray(new String[render.size()]);
}
@Override
public boolean canZoom(ItemStack stack, EntityPlayer player)
{
return this.getUpgrades(stack).getBoolean("scope");
}
float[] zoomSteps = new float[]{.1f,.15625f,.2f,.25f, .3125f, .4f, .5f,.625f};
@Override
public float[] getZoomSteps(ItemStack stack, EntityPlayer player)
{
return zoomSteps;
}
@Override
public boolean isTool(ItemStack item)
{
return true;
}
@SideOnly(Side.CLIENT)
@Override
public TextureAtlasSprite getTextureReplacement(ItemStack stack, String material)
{
return null;
}
@SideOnly(Side.CLIENT)
@Override
public boolean shouldRenderGroup(ItemStack stack, String group)
{
if (group.equals("upgrade_scope"))
return getUpgrades(stack).getBoolean("scope");
if (group.equals("upgrade_speed"))
return getUpgrades(stack).getDouble("speed")>0;
return true;
}
@SideOnly(Side.CLIENT)
@Override
public Optional<TRSRTransformation> applyTransformations(ItemStack stack, String group, Optional<TRSRTransformation> transform)
{
// if(transform.isPresent())
// {
// NBTTagCompound upgrades = this.getUpgrades(stack);
// Matrix4 mat = new Matrix4(transform.get().getMatrix());
//// mat.translate(.41f,2,0);
// return Optional.of(new TRSRTransformation(mat.toMatrix4f()));
// }
return transform;
}
@SideOnly(Side.CLIENT)
@Override
public Matrix4 handlePerspective(ItemStack stack, TransformType cameraTransformType, Matrix4 perspective)
{
// if(stack.)
// if(ItemNBTHelper.getBoolean(stack, "inUse"))
// {
// //ToDo: Accoutn for hands
// if (cameraTransformType==TransformType.FIRST_PERSON_RIGHT_HAND)
// perspective = perspective.translate(-.75, -2, -.5).rotate(Math.toRadians(-78), 0, 0, 1);
// else
// perspective = perspective.translate(0, -.5, -.375).rotate(Math.toRadians(8), 0, 1, 0).rotate(Math.toRadians(-12), 1, 0, 0).rotate(Math.toRadians(8), 0, 0, 1);
// }
return perspective;
}
}