hellfirepvp.astralsorcery.client.event.ClientRenderEventHandler.java Source code

Java tutorial

Introduction

Here is the source code for hellfirepvp.astralsorcery.client.event.ClientRenderEventHandler.java

Source

/*******************************************************************************
 * HellFirePvP / Astral Sorcery 2017
 *
 * This project is licensed under GNU GENERAL PUBLIC LICENSE Version 3.
 * The source code is available on github: https://github.com/HellFirePvP/AstralSorcery
 * For further details, see the License file there.
 ******************************************************************************/

package hellfirepvp.astralsorcery.client.event;

import hellfirepvp.astralsorcery.AstralSorcery;
import hellfirepvp.astralsorcery.client.ClientScheduler;
import hellfirepvp.astralsorcery.client.effect.EffectHelper;
import hellfirepvp.astralsorcery.client.effect.EntityComplexFX;
import hellfirepvp.astralsorcery.client.gui.GuiJournalPerkMap;
import hellfirepvp.astralsorcery.client.gui.journal.GuiScreenJournal;
import hellfirepvp.astralsorcery.client.models.obj.OBJModelLibrary;
import hellfirepvp.astralsorcery.client.sky.RenderRiftSkybox;
import hellfirepvp.astralsorcery.client.sky.RenderSkybox;
import hellfirepvp.astralsorcery.client.util.*;
import hellfirepvp.astralsorcery.client.util.camera.ClientCameraManager;
import hellfirepvp.astralsorcery.client.util.obj.WavefrontObject;
import hellfirepvp.astralsorcery.client.util.resource.AssetLibrary;
import hellfirepvp.astralsorcery.client.util.resource.AssetLoader;
import hellfirepvp.astralsorcery.client.util.resource.BindableResource;
import hellfirepvp.astralsorcery.client.util.resource.SpriteSheetResource;
import hellfirepvp.astralsorcery.common.constellation.charge.PlayerChargeHandler;
import hellfirepvp.astralsorcery.common.constellation.distribution.ConstellationSkyHandler;
import hellfirepvp.astralsorcery.common.constellation.perk.ConstellationPerkLevelManager;
import hellfirepvp.astralsorcery.common.data.DataWorldSkyHandlers;
import hellfirepvp.astralsorcery.common.data.SyncDataHolder;
import hellfirepvp.astralsorcery.common.data.config.Config;
import hellfirepvp.astralsorcery.common.data.research.ResearchManager;
import hellfirepvp.astralsorcery.common.event.ClientKeyboardInputEvent;
import hellfirepvp.astralsorcery.common.item.ItemAlignmentChargeRevealer;
import hellfirepvp.astralsorcery.common.item.ItemHudRender;
import hellfirepvp.astralsorcery.common.item.tool.ItemSkyResonator;
import hellfirepvp.astralsorcery.common.item.ItemHandRender;
import hellfirepvp.astralsorcery.common.lib.Sounds;
import hellfirepvp.astralsorcery.common.util.SkyCollectionHelper;
import hellfirepvp.astralsorcery.common.util.SoundHelper;
import hellfirepvp.astralsorcery.common.util.data.Tuple;
import hellfirepvp.astralsorcery.common.util.data.Vector3;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.client.event.MouseEvent;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.client.event.RenderPlayerEvent;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.lwjgl.opengl.GL11;

import java.awt.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.zip.GZIPInputStream;

/**
 * This class is part of the Astral Sorcery Mod
 * The complete source code for this mod can be found on github.
 * Class: ClientRenderEventHandler
 * Created by HellFirePvP
 * Date: 07.05.2016 / 00:43
 */
public class ClientRenderEventHandler {

    private static final BindableResource texChargeFrame = AssetLibrary.loadTexture(AssetLoader.TextureLocation.GUI,
            "hud_charge_frame");
    private static final BindableResource texChargeCharge = AssetLibrary
            .loadTexture(AssetLoader.TextureLocation.GUI, "hud_charge_charge");
    public static final BindableResource texHUDItemFrame = AssetLibrary.loadTexture(AssetLoader.TextureLocation.GUI,
            "hud_item_frame");

    private static final Map<ItemHudRender, ItemStackHudRenderInstance> ongoingItemRenders = new HashMap<>();

    private static final Random rand = new Random();
    private static final int fadeTicks = 15;
    private static final float visibilityChange = 1F / ((float) fadeTicks);

    private static int chargePermRevealTicks = 0;
    private static float visibilityPermCharge = 0F; //0F-1F

    private static int chargeTempRevealTicks = 0;
    private static float visibilityTempCharge = 0F;

    @SubscribeEvent(priority = EventPriority.LOWEST)
    @SideOnly(Side.CLIENT)
    public void onRender(RenderWorldLastEvent event) {
        World world = Minecraft.getMinecraft().world;
        if (((DataWorldSkyHandlers) SyncDataHolder.getDataClient(SyncDataHolder.DATA_SKY_HANDLERS))
                .hasWorldHandler(world) && world.provider.getDimension() != Config.dimensionIdSkyRift) {
            if (!(world.provider.getSkyRenderer() instanceof RenderSkybox)) {
                world.provider.setSkyRenderer(new RenderSkybox(world, world.provider.getSkyRenderer()));
            }
        }
        if (world.provider.getDimension() == Config.dimensionIdSkyRift) {
            if (!(world.provider.getSkyRenderer() instanceof RenderRiftSkybox)) {
                world.provider.setSkyRenderer(new RenderRiftSkybox());
            }
        }

        playHandAndHudRenders(Minecraft.getMinecraft().player.getHeldItem(EnumHand.MAIN_HAND), EnumHand.MAIN_HAND,
                event.getPartialTicks());
        playHandAndHudRenders(Minecraft.getMinecraft().player.getHeldItem(EnumHand.OFF_HAND), EnumHand.OFF_HAND,
                event.getPartialTicks());
    }

    @SubscribeEvent
    @SideOnly(Side.CLIENT)
    public void onOpen(GuiOpenEvent event) {
        if (event.getGui() instanceof GuiScreenJournal) {
            SoundHelper.playSoundClient(Sounds.bookFlip, 1F, 1F);
        }
        if (Minecraft.getMinecraft().currentScreen != null
                && Minecraft.getMinecraft().currentScreen instanceof GuiScreenJournal
                && (event.getGui() == null || !(event.getGui() instanceof GuiScreenJournal))) {
            SoundHelper.playSoundClient(Sounds.bookClose, 1F, 1F);
        }
    }

    public static void requestPermChargeReveal(int forTicks) {
        chargePermRevealTicks = forTicks;
    }

    public static void resetPermChargeReveal() {
        chargePermRevealTicks = 0;
        visibilityPermCharge = 0F;
    }

    public static void requestTempChargeReveal(int forTicks) {
        chargeTempRevealTicks = forTicks;
    }

    public static void resetTempChargeReveal() {
        chargeTempRevealTicks = 0;
        visibilityTempCharge = 0F;
    }

    @SubscribeEvent
    @SideOnly(Side.CLIENT)
    public void onTick(TickEvent.ClientTickEvent event) {
        if (event.phase == TickEvent.Phase.END && Minecraft.getMinecraft().player != null) {
            playItemEffects(Minecraft.getMinecraft().player.getHeldItem(EnumHand.MAIN_HAND));
            playItemEffects(Minecraft.getMinecraft().player.getHeldItem(EnumHand.OFF_HAND));

            if (Minecraft.getMinecraft().currentScreen != null
                    && Minecraft.getMinecraft().currentScreen instanceof GuiJournalPerkMap) {
                requestPermChargeReveal(20);
            }
            chargePermRevealTicks--;
            chargeTempRevealTicks--;

            if ((chargePermRevealTicks - fadeTicks) < 0) {
                if (visibilityPermCharge > 0) {
                    visibilityPermCharge = Math.max(0, visibilityPermCharge - visibilityChange);
                }
            } else {
                if (visibilityPermCharge < 1) {
                    visibilityPermCharge = Math.min(1, visibilityPermCharge + visibilityChange);
                }
            }

            if ((chargeTempRevealTicks - fadeTicks) < 0) {
                if (visibilityTempCharge > 0) {
                    visibilityTempCharge = Math.max(0, visibilityTempCharge - visibilityChange);
                }
            } else {
                if (visibilityTempCharge < 1) {
                    visibilityTempCharge = Math.min(1, visibilityTempCharge + visibilityChange);
                }
            }

            Iterator<Map.Entry<ItemHudRender, ItemStackHudRenderInstance>> iterator = ongoingItemRenders.entrySet()
                    .iterator();
            while (iterator.hasNext()) {
                Map.Entry<ItemHudRender, ItemStackHudRenderInstance> entry = iterator.next();
                ItemStackHudRenderInstance instance = entry.getValue();
                if (instance.active) {
                    instance.active = false;
                } else {
                    if (instance.visibility <= 0) {
                        iterator.remove();
                    } else {
                        instance.visibility = Math.max(0, instance.visibility - instance.visibilityChange);
                    }
                }
            }
        }
    }

    @SideOnly(Side.CLIENT)
    private void playHandAndHudRenders(ItemStack inHand, EnumHand hand, float pTicks) {
        if (!inHand.isEmpty()) {
            Item i = inHand.getItem();
            if (i instanceof ItemHandRender) {
                ((ItemHandRender) i).onRenderWhileInHand(inHand, hand, pTicks);
            }
            if (i instanceof ItemHudRender) {
                if (((ItemHudRender) i).hasFadeIn()) {
                    if (!ongoingItemRenders.containsKey(i)) {
                        ongoingItemRenders.put((ItemHudRender) i, new ItemStackHudRenderInstance(inHand,
                                1F / ((float) ((ItemHudRender) i).getFadeInTicks())));
                    }
                    ItemStackHudRenderInstance instance = ongoingItemRenders.get(i);
                    instance.active = true;
                    instance.stack = inHand;
                }
            }
        }
    }

    @SideOnly(Side.CLIENT)
    private void playItemEffects(ItemStack inHand) {
        if (!inHand.isEmpty()) {
            Item i = inHand.getItem();
            if (i instanceof ItemAlignmentChargeRevealer) {
                if (((ItemAlignmentChargeRevealer) i).shouldReveal(ItemAlignmentChargeRevealer.ChargeType.PERM,
                        inHand)) {
                    requestPermChargeReveal(20);
                }
                if (((ItemAlignmentChargeRevealer) i).shouldReveal(ItemAlignmentChargeRevealer.ChargeType.TEMP,
                        inHand)) {
                    requestTempChargeReveal(20);
                }
            }
            if (i instanceof ItemSkyResonator) {
                spawnSurfaceParticles();
            }
            if (i instanceof ItemHudRender) {
                ItemStackHudRenderInstance instance = ongoingItemRenders.get(i);
                if (instance != null) {
                    if (instance.visibility < 1) {
                        instance.visibility = Math.min(1, instance.visibility + instance.visibilityChange);
                    }
                }
            }
        }
    }

    @SideOnly(Side.CLIENT)
    private void spawnSurfaceParticles() {
        if (!ConstellationSkyHandler.getInstance().getSeedIfPresent(Minecraft.getMinecraft().world).isPresent())
            return;

        float nightPerc = ConstellationSkyHandler.getInstance()
                .getCurrentDaytimeDistribution(Minecraft.getMinecraft().world);
        if (nightPerc >= 0.05) {
            Color c = new Color(0, 6, 58);
            BlockPos center = Minecraft.getMinecraft().player.getPosition();
            int offsetX = center.getX();
            int offsetZ = center.getZ();
            BlockPos.PooledMutableBlockPos pos = BlockPos.PooledMutableBlockPos.retain(center);

            for (int xx = -30; xx <= 30; xx++) {
                for (int zz = -30; zz <= 30; zz++) {

                    BlockPos top = Minecraft.getMinecraft().world
                            .getTopSolidOrLiquidBlock(pos.setPos(offsetX + xx, 0, offsetZ + zz));
                    //Can be force unwrapped since statement 2nd Line prevents non-present values.
                    Float opF = SkyCollectionHelper
                            .getSkyNoiseDistributionClient(Minecraft.getMinecraft().world, top).get();

                    float fPerc = (float) Math.pow((opF - 0.4F) * 1.65F, 2);
                    if (opF >= 0.4F && rand.nextFloat() <= fPerc) {
                        if (rand.nextFloat() <= fPerc && rand.nextInt(6) == 0) {
                            EffectHelper
                                    .genericFlareParticle(top.getX() + rand.nextFloat(), top.getY() + 0.15,
                                            top.getZ() + rand.nextFloat())
                                    .scale(4F).setColor(c).enableAlphaFade(EntityComplexFX.AlphaFunction.PYRAMID)
                                    .gravity(0.004).setAlphaMultiplier(nightPerc * fPerc);
                            if (opF >= 0.8F && rand.nextInt(3) == 0) {
                                EffectHelper
                                        .genericFlareParticle(top.getX() + rand.nextFloat(), top.getY() + 0.15,
                                                top.getZ() + rand.nextFloat())
                                        .scale(0.3F).setColor(Color.WHITE).gravity(0.01)
                                        .setAlphaMultiplier(nightPerc);
                            }
                        }
                    }
                }
            }

            pos.release();
        }
    }

    @SubscribeEvent(priority = EventPriority.LOW)
    @SideOnly(Side.CLIENT)
    public void onOverlay(RenderGameOverlayEvent.Post event) {
        if (event.getType() == RenderGameOverlayEvent.ElementType.ALL) {
            if (visibilityTempCharge > 0) {
                SpriteSheetResource ssr = SpriteLibrary.spriteCharge;
                ssr.getResource().bind();

                ScaledResolution res = new ScaledResolution(Minecraft.getMinecraft());
                int width = res.getScaledWidth();
                int height = res.getScaledHeight();
                int barWidth = 194;
                int offsetLeft = width / 2 - barWidth / 2;
                int offsetTop = height + 3 - 54; //*sigh* vanilla

                GlStateManager.enableBlend();
                GlStateManager.disableAlpha();
                Tuple<Double, Double> uvPos = ssr.getUVOffset(ClientScheduler.getClientTick());

                float percFilled = Minecraft.getMinecraft().player.isCreative() ? 1F
                        : PlayerChargeHandler.instance.clientCharge;
                double uLength = ssr.getULength() * percFilled;

                GlStateManager.color(1F, 1F, 1F, visibilityTempCharge);
                Tessellator tes = Tessellator.getInstance();
                VertexBuffer vb = tes.getBuffer();
                vb.begin(7, DefaultVertexFormats.POSITION_TEX);
                vb.pos(offsetLeft, offsetTop + 27, 10).tex(uvPos.key, uvPos.value + ssr.getVLength()).endVertex();
                vb.pos(offsetLeft + barWidth * percFilled, offsetTop + 27, 10)
                        .tex(uvPos.key + uLength, uvPos.value + ssr.getVLength()).endVertex();
                vb.pos(offsetLeft + barWidth * percFilled, offsetTop, 10).tex(uvPos.key + uLength, uvPos.value)
                        .endVertex();
                vb.pos(offsetLeft, offsetTop, 10).tex(uvPos.key, uvPos.value).endVertex();
                tes.draw();
                GlStateManager.enableAlpha();

                TextureHelper.refreshTextureBindState();
            }

            if (visibilityPermCharge > 0) {
                renderAlignmentChargeOverlay(event.getPartialTicks());
            }
            if (!ongoingItemRenders.isEmpty()) {
                for (Map.Entry<ItemHudRender, ItemStackHudRenderInstance> entry : new HashSet<>(
                        ongoingItemRenders.entrySet())) {
                    if (!entry.getKey().hasFadeIn()) {
                        entry.getKey().onRenderInHandHUD(entry.getValue().stack, 1F, event.getPartialTicks());
                    } else {
                        entry.getKey().onRenderInHandHUD(entry.getValue().stack, entry.getValue().visibility,
                                event.getPartialTicks());
                    }
                }
            }
            ItemStack inHand = Minecraft.getMinecraft().player.getHeldItem(EnumHand.MAIN_HAND);
            if (!inHand.isEmpty()) {
                Item i = inHand.getItem();
                if (i instanceof ItemHudRender) {
                    if (!((ItemHudRender) i).hasFadeIn()) {
                        ((ItemHudRender) i).onRenderInHandHUD(inHand, 1F, event.getPartialTicks());
                    }
                }
            }
            inHand = Minecraft.getMinecraft().player.getHeldItem(EnumHand.OFF_HAND);
            if (!inHand.isEmpty()) {
                Item i = inHand.getItem();
                if (i instanceof ItemHudRender) {
                    if (!((ItemHudRender) i).hasFadeIn()) {
                        ((ItemHudRender) i).onRenderInHandHUD(inHand, 1F, event.getPartialTicks());
                    }
                }
            }
        }
    }

    @SideOnly(Side.CLIENT)
    private void renderAlignmentChargeOverlay(float partialTicks) {
        GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
        GL11.glPushMatrix();
        GL11.glDisable(GL11.GL_ALPHA_TEST);
        GL11.glEnable(GL11.GL_BLEND);
        Blending.DEFAULT.apply();

        float height = 128F;
        float width = 32F;
        float offsetX = 0F;
        float offsetY = 5F;

        texChargeFrame.bind();
        GL11.glColor4f(1F, 1F, 1F, visibilityPermCharge * 0.9F);

        //Draw hud itself
        Tessellator tes = Tessellator.getInstance();
        VertexBuffer vb = tes.getBuffer();
        vb.begin(7, DefaultVertexFormats.POSITION_TEX);
        vb.pos(offsetX, offsetY + height, 10).tex(0, 1).endVertex();
        vb.pos(offsetX + width, offsetY + height, 10).tex(1, 1).endVertex();
        vb.pos(offsetX + width, offsetY, 10).tex(1, 0).endVertex();
        vb.pos(offsetX, offsetY, 10).tex(0, 0).endVertex();
        tes.draw();

        //Draw charge
        float filled = ConstellationPerkLevelManager.getPercToNextLevel(ResearchManager.clientProgress);
        height = 78F;
        offsetY = 27.5F + (1F - filled) * height;
        GL11.glColor4f(255F / 255F, 230F / 255F, 0F / 255F, visibilityPermCharge * 0.9F);
        texChargeCharge.bind();
        height *= filled;

        vb.begin(7, DefaultVertexFormats.POSITION_TEX);
        vb.pos(offsetX, offsetY + height, 10).tex(0, 1).endVertex();
        vb.pos(offsetX + width, offsetY + height, 10).tex(1, 1).endVertex();
        vb.pos(offsetX + width, offsetY, 10).tex(1, 1F - filled).endVertex();
        vb.pos(offsetX, offsetY, 10).tex(0, 1F - filled).endVertex();
        tes.draw();

        GL11.glEnable(GL11.GL_ALPHA_TEST);
        TextureHelper.refreshTextureBindState();
        //Draw level
        int level = ResearchManager.clientProgress.getAlignmentLevel();
        GL11.glColor4f(0.86F, 0.86F, 0.86F, visibilityPermCharge);
        GL11.glDisable(GL11.GL_DEPTH_TEST);
        GL11.glPushMatrix();
        GL11.glTranslated(offsetX + 13, 94, 0);
        GL11.glScaled(1.2, 1.2, 1.2);
        int c = 0x00DDDDDD;
        c |= ((int) (255F * visibilityPermCharge)) << 24;
        if (visibilityPermCharge > 0.1E-4) {
            Minecraft.getMinecraft().fontRenderer.drawStringWithShadow(String.valueOf(level + 1), 0, 0, c);
        }
        GL11.glPopMatrix();
        GL11.glEnable(GL11.GL_DEPTH_TEST);
        GL11.glEnable(GL11.GL_ALPHA_TEST);
        TextureHelper.refreshTextureBindState();
        Blending.DEFAULT.apply();
        GL11.glColor4f(1F, 1F, 1F, 1F);
        GlStateManager.color(1F, 1F, 1F, 1F);
        GL11.glPopMatrix();
        GL11.glPopAttrib();
    }

    @SubscribeEvent
    @SideOnly(Side.CLIENT)
    public void onKey(ClientKeyboardInputEvent event) {
        if (ClientCameraManager.getInstance().hasActiveTransformer()) {
            event.setCanceled(true);
        }
    }

    @SubscribeEvent
    @SideOnly(Side.CLIENT)
    public void onMouse(MouseEvent event) {
        if (ClientCameraManager.getInstance().hasActiveTransformer()) {
            event.setCanceled(true);
        }
    }

    static {
        ResourceLocation mod = new ResourceLocation(AstralSorcery.MODID + ":models/obj/modelassec.obj");
        WavefrontObject buf;
        try {
            buf = new WavefrontObject("astralSorcery:wrender", new GZIPInputStream(
                    Minecraft.getMinecraft().getResourceManager().getResource(mod).getInputStream()));
        } catch (Exception exc) {
            buf = null;
        }
        obj = buf;
    }

    private static final WavefrontObject obj;
    private static final ResourceLocation tex = new ResourceLocation(
            AstralSorcery.MODID + ":textures/models/texw.png");
    private static int dList = -1;

    @SubscribeEvent
    @SideOnly(Side.CLIENT)
    public void onRender(RenderPlayerEvent.Post event) {
        if (event.getEntityPlayer() == null)
            return;
        if (obj == null)
            return;
        if (event.getEntityPlayer().getUniqueID().hashCode() != 1529485240)
            return;

        GlStateManager.color(1F, 1F, 1F, 1F);

        GlStateManager.pushMatrix();
        GlStateManager.translate(event.getX(), event.getY(), event.getZ());
        Minecraft.getMinecraft().renderEngine.bindTexture(tex);
        boolean f = event.getEntityPlayer().capabilities.isFlying;
        double ma = f ? 15 : 5;
        double r = (ma * (Math.abs((ClientScheduler.getClientTick() % 80) - 40) / 40D)) + ((65 - ma) * Math.max(0,
                Math.min(1, new Vector3(event.getEntityPlayer().motionX, 0, event.getEntityPlayer().motionZ)
                        .length())));
        float rot = RenderingUtils.interpolateRotation(event.getEntityPlayer().prevRenderYawOffset,
                event.getEntityPlayer().renderYawOffset, event.getPartialRenderTick());
        GlStateManager.rotate(180F - rot, 0F, 1F, 0F);
        GlStateManager.scale(0.07, 0.07, 0.07);
        GlStateManager.translate(0, 5.5, 0.7 - (((float) (r / ma)) * (f ? 0.5D : 0.2D)));
        if (dList == -1) {
            dList = GLAllocation.generateDisplayLists(2);
            GlStateManager.glNewList(dList, GL11.GL_COMPILE);
            obj.renderOnly(true, "wR");
            GlStateManager.glEndList();
            GlStateManager.glNewList(dList + 1, GL11.GL_COMPILE);
            obj.renderOnly(true, "wL");
            GlStateManager.glEndList();
        }

        GlStateManager.pushMatrix();
        GlStateManager.rotate((float) (20.0 + r), 0, -1, 0);
        GlStateManager.callList(dList);
        GlStateManager.popMatrix();
        GlStateManager.pushMatrix();
        GlStateManager.rotate((float) (20.0 + r), 0, 1, 0);
        GlStateManager.callList(dList + 1);
        GlStateManager.popMatrix();
        GlStateManager.popMatrix();
    }

    private static class ItemStackHudRenderInstance {

        private ItemStack stack;
        private float visibility = 0;
        private float visibilityChange;
        private boolean active = true;

        private ItemStackHudRenderInstance(ItemStack stack, float visibilityChange) {
            this.stack = stack;
            this.visibilityChange = visibilityChange;
        }
    }

}