blusunrize.immersiveengineering.common.items.ItemRailgun.java Source code

Java tutorial

Introduction

Here is the source code for blusunrize.immersiveengineering.common.items.ItemRailgun.java

Source

/*
 * BluSunrize
 * Copyright (c) 2017
 *
 * This code is licensed under "Blu's License of Common Sense"
 * Details can be found in the license file in the root folder of this project
 */

package blusunrize.immersiveengineering.common.items;

import blusunrize.immersiveengineering.api.Lib;
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.shader.ShaderCase;
import blusunrize.immersiveengineering.api.shader.ShaderRegistry;
import blusunrize.immersiveengineering.api.shader.ShaderRegistry.ShaderRegistryEntry;
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.EnergyHelper;
import blusunrize.immersiveengineering.common.util.EnergyHelper.IIEEnergyItem;
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 blusunrize.immersiveengineering.common.util.inventory.IEItemStackHandler;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.util.ITooltipFlag;
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.Slot;
import net.minecraft.item.EnumAction;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.*;
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.energy.CapabilityEnergy;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import org.apache.commons.lang3.tuple.Triple;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;

public class ItemRailgun extends ItemUpgradeableTool
        implements IIEEnergyItem, IZoomTool, ITool, IOBJModelCallback<ItemStack> {
    public ItemRailgun() {
        super("railgun", 1, "RAILGUN");
    }

    @Override
    public int getSlotCount(ItemStack stack) {
        return 2 + 1;
    }

    @Override
    public Slot[] getWorkbenchSlots(Container container, ItemStack stack) {
        IItemHandler inv = stack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
        return new Slot[] { new IESlot.Upgrades(container, inv, 0, 80, 32, "RAILGUN", stack, true),
                new IESlot.Upgrades(container, inv, 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) {
        if (!stack.isEmpty())
            return new IEItemStackHandler(stack) {
                final EnergyHelper.ItemEnergyStorage energyStorage = new EnergyHelper.ItemEnergyStorage(stack);
                final ShaderWrapper_Item shaders = new ShaderWrapper_Item("immersiveengineering:railgun", stack);

                @Override
                public boolean hasCapability(@Nonnull Capability<?> capability, EnumFacing facing) {
                    return capability == CapabilityEnergy.ENERGY || capability == CapabilityShader.SHADER_CAPABILITY
                            || super.hasCapability(capability, facing);
                }

                @Override
                public <T> T getCapability(@Nonnull Capability<T> capability, EnumFacing facing) {
                    if (capability == CapabilityEnergy.ENERGY)
                        return (T) energyStorage;
                    if (capability == CapabilityShader.SHADER_CAPABILITY)
                        return (T) shaders;
                    return super.getCapability(capability, facing);
                }
            };
        return null;
    }

    @Override
    public void addInformation(ItemStack stack, @Nullable World world, List<String> list, ITooltipFlag flag) {
        String stored = this.getEnergyStored(stack) + "/" + this.getMaxEnergyStored(stack);
        list.add(I18n.format(Lib.DESC + "info.energyStored", stored));
    }

    @Override
    public String getTranslationKey(ItemStack stack) {
        //      if(stack.getItemDamage()!=1)
        //      {
        //         String tag = getRevolverDisplayTag(stack);
        //         if(!tag.isEmpty())
        //            return this.getTranslationKey()+"."+tag;
        //      }
        return super.getTranslationKey(stack);
    }

    @Override
    public boolean isFull3D() {
        return true;
    }

    @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) {
        super.onUpdate(stack, world, ent, slot, inHand);
    }

    @Override
    public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
        ItemStack stack = player.getHeldItem(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).isEmpty()) {
            player.setActiveHand(hand);
            player.world.playSound(null, player.posX, player.posY, player.posZ,
                    getChargeTime(stack) <= 20 ? IESounds.chargeFast : IESounds.chargeSlow, SoundCategory.PLAYERS,
                    1.5f, 1f);
            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.world.playSound(null, user.posX, user.posY, user.posZ, IESounds.spark, SoundCategory.PLAYERS,
                    .8f + (.2f * user.getRNG().nextFloat()), .5f + (.5f * user.getRNG().nextFloat()));
            Triple<ItemStack, ShaderRegistryEntry, ShaderCase> shader = ShaderRegistry
                    .getStoredShaderAndCase(stack);
            if (shader != null) {
                Vec3d pos = Utils.getLivingFrontPos(user, .4375, user.height * .75,
                        user.getActiveHand() == EnumHand.MAIN_HAND ? user.getPrimaryHand()
                                : user.getPrimaryHand().opposite(),
                        false, 1);
                shader.getMiddle().getEffectFunction().execute(user.world, shader.getLeft(), stack,
                        shader.getRight().getShaderType(), pos, null, .0625f);
            }
        }
    }

    @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.isEmpty()) {
                    Vec3d vec = user.getLookVec();
                    float speed = 20;
                    EntityRailgunShot shot = new EntityRailgunShot(user.world, user, vec.x * speed, vec.y * speed,
                            vec.z * speed, Utils.copyStackWithAmount(ammo, 1));
                    ammo.shrink(1);
                    if (ammo.getCount() <= 0)
                        ((EntityPlayer) user).inventory.deleteStack(ammo);
                    user.world.playSound(null, user.posX, user.posY, user.posZ, IESounds.railgunFire,
                            SoundCategory.PLAYERS, 1, .5f + (.5f * user.getRNG().nextFloat()));
                    this.extractEnergy(stack, energy, false);
                    if (!world.isRemote)
                        user.world.spawnEntity(shot);

                    Triple<ItemStack, ShaderRegistryEntry, ShaderCase> shader = ShaderRegistry
                            .getStoredShaderAndCase(stack);
                    if (shader != null) {
                        Vec3d pos = Utils.getLivingFrontPos(user, .75, user.height * .75,
                                user.getActiveHand() == EnumHand.MAIN_HAND ? user.getPrimaryHand()
                                        : user.getPrimaryHand().opposite(),
                                false, 1);
                        shader.getMiddle().getEffectFunction().execute(world, shader.getLeft(), stack,
                                shader.getRight().getShaderType(), pos, user.getForward(), .125f);
                    }
                }
            }
        }
    }

    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 ItemStack.EMPTY;
    }

    public static boolean isAmmo(ItemStack stack) {
        if (stack.isEmpty())
            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) {
        //      ToDo: Make an Upgrade Advancement?
        //      if(contents[18]!=null&&contents[19]!=null)
        //         Utils.unlockIEAdvancement(player, "upgrade_railgun");
    }

    @Override
    public int getMaxEnergyStored(ItemStack container) {
        return 1600;
    }

    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 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,
            EntityLivingBase entity) {
        //      if(stack.)
        //      if(ItemNBTHelper.getBoolean(stack, "inUse"))
        //      {
        //         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;
    }
}