hellfirepvp.astralsorcery.client.util.UIGateway.java Source code

Java tutorial

Introduction

Here is the source code for hellfirepvp.astralsorcery.client.util.UIGateway.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.util;

import hellfirepvp.astralsorcery.client.ClientScheduler;
import hellfirepvp.astralsorcery.client.sky.RenderAstralSkybox;
import hellfirepvp.astralsorcery.common.base.CelestialGatewaySystem;
import hellfirepvp.astralsorcery.common.util.data.Vector3;
import hellfirepvp.astralsorcery.common.util.data.WorldBlockPos;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import org.lwjgl.opengl.GL11;

import javax.annotation.Nullable;
import java.awt.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

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

    private List<GatewayEntry> gatewayEntries = new LinkedList<>();
    private final Vector3 origin;
    private final double radius;

    private UIGateway(Vector3 pos, double radius) {
        this.origin = pos;
        this.radius = radius;
    }

    public Vector3 getPos() {
        return origin;
    }

    public double getRadius() {
        return radius;
    }

    public static UIGateway initialize(World world, Vector3 source, double sphereRadius) {
        UIGateway ui = new UIGateway(source, sphereRadius);
        CelestialGatewaySystem system = CelestialGatewaySystem.instance;
        int dimid = world.provider.getDimension();
        List<BlockPos> sameDimensionPositions = system.getGatewaysForWorld(world, Side.CLIENT);
        gatherStars(ui, world.provider.getDimension(), sameDimensionPositions, true, sphereRadius);

        for (Map.Entry<Integer, List<BlockPos>> entries : system.getGatewayCache(Side.CLIENT).entrySet()) {
            if (entries.getKey() == dimid)
                continue;
            List<BlockPos> otherPositions = entries.getValue();
            gatherStars(ui, entries.getKey(), otherPositions, false, sphereRadius);
        }

        return ui;
    }

    @Nullable
    public GatewayEntry findMatchingEntry(float yaw, float pitch) {
        float matchAccurancy = 4;
        for (GatewayEntry entry : gatewayEntries) {
            if (Math.abs(entry.pitch - pitch) < matchAccurancy && (Math.abs(entry.yaw - yaw) <= matchAccurancy
                    || Math.abs(entry.yaw - yaw - 360F) <= matchAccurancy)) {
                return entry;
            }
        }
        return null;
    }

    private static void gatherStars(UIGateway gateway, int dimId, List<BlockPos> otherPositions, boolean sameWorld,
            double sphereRadius) {
        Vector3 gatePosition = gateway.getPos();
        for (BlockPos other : otherPositions) {
            Vector3 otherPos = new Vector3(other);
            if (sameWorld && otherPos.distance(gatePosition) < 16)
                continue;

            Vector3 direction = otherPos.subtract(gatePosition).normalize().multiply(sphereRadius);
            GatewayEntry potentialEntry = new GatewayEntry(other, dimId, direction);
            if (sameWorld) {
                boolean mayAdd = true;
                for (GatewayEntry entry : gateway.gatewayEntries) {
                    if (Math.abs(entry.pitch - potentialEntry.pitch) < 10
                            && (Math.abs(entry.yaw - potentialEntry.yaw) <= 10
                                    || Math.abs(entry.yaw - potentialEntry.yaw - 360F) <= 10)) {
                        mayAdd = false;
                    }
                }
                if (mayAdd) {
                    gateway.gatewayEntries.add(potentialEntry);
                }
            } else {
                long seed = 0xA7401CE1466A1095L;
                seed |= ((long) other.getX()) << 48;
                seed |= ((long) other.getY()) << 24;
                seed |= ((long) other.getZ());
                Random rand = new Random(seed);
                direction = Vector3.positiveYRandom(rand).normalize().multiply(sphereRadius);
                potentialEntry = new GatewayEntry(other, dimId, direction);
                int tries = 30;
                boolean foundSpace = false;
                while (!foundSpace && tries > 0) {
                    boolean mayAdd = true;
                    for (GatewayEntry entry : gateway.gatewayEntries) {
                        if (Math.abs(entry.pitch - potentialEntry.pitch) < 25
                                && (Math.abs(entry.yaw - potentialEntry.yaw) <= 25
                                        || Math.abs(entry.yaw - potentialEntry.yaw - 360F) <= 25)) {
                            mayAdd = false;
                        }
                    }
                    if (mayAdd) {
                        foundSpace = true;
                    } else {
                        direction = Vector3.positiveYRandom(rand).normalize().multiply(sphereRadius);
                        potentialEntry = new GatewayEntry(other, dimId, direction);
                    }
                    tries--;
                }
                if (foundSpace) {
                    gateway.gatewayEntries.add(potentialEntry);
                }
            }
        }
    }

    public void renderIntoWorld(float pticks) {
        if (Minecraft.getMinecraft().player == null)
            return;

        double dst = new Vector3(origin).distance(new Vector3(Minecraft.getMinecraft().player));
        if (dst > 3)
            return;
        float alpha = 1F - ((float) (dst / 2D));
        alpha = MathHelper.clamp(alpha, 0F, 1F);
        Color c = new Color(0xF0BD00);
        float red = c.getRed() / 255F;
        float green = c.getGreen() / 255F;
        float blue = c.getBlue() / 255F;

        long seed = 0xA781B4F01C771923L;
        seed |= ((long) origin.getBlockX()) << 48;
        seed |= ((long) origin.getBlockY()) << 24;
        seed |= ((long) origin.getBlockZ());
        Random rand = new Random(seed);

        GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
        GL11.glPushMatrix();
        GL11.glEnable(GL11.GL_BLEND);
        Blending.DEFAULT.apply();
        GL11.glDisable(GL11.GL_ALPHA_TEST);
        GL11.glColor4f(1F, 1F, 1F, 1F);
        RenderAstralSkybox.TEX_STAR_1.bind();

        Tessellator tes = Tessellator.getInstance();
        VertexBuffer vb = tes.getBuffer();
        vb.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
        for (int i = 0; i < 300; i++) {
            Vector3 dir = Vector3.random(rand).normalize().multiply(radius);
            float a = RenderConstellation.conCFlicker(ClientScheduler.getClientTick(), pticks, rand.nextInt(7) + 6);
            a *= alpha;
            RenderingUtils.renderFacingFullQuadVB(vb, origin.getX() + dir.getX(), origin.getY() + dir.getY(),
                    origin.getZ() + dir.getZ(), pticks, 0.07F, 0, 1F, 1F, 1F, a);
        }
        for (GatewayEntry entry : gatewayEntries) {
            float a = RenderConstellation.conCFlicker(ClientScheduler.getClientTick(), pticks, rand.nextInt(7) + 6);
            a = 0.4F + (0.6F * a);
            a = (a * alpha);
            RenderingUtils.renderFacingFullQuadVB(vb, origin.getX() + entry.relativePos.getX(),
                    origin.getY() + entry.relativePos.getY(), origin.getZ() + entry.relativePos.getZ(), pticks,
                    0.16F, 0, red, green, blue, a);
        }
        RenderingUtils.sortVertexData(vb);
        tes.draw();
        TextureHelper.refreshTextureBindState();
        GL11.glPopMatrix();
        GL11.glPopAttrib();
    }

    public static class GatewayEntry {

        //Used for transfer
        public final BlockPos originalBlockPos;
        public final int originalDimId;

        //Used for drawing
        public final Vector3 relativePos;

        //Used for matching
        private final float yaw, pitch;

        private GatewayEntry(BlockPos originalBlockPos, int originalDimId, Vector3 relativePos) {
            this.originalBlockPos = originalBlockPos;
            this.originalDimId = originalDimId;
            this.relativePos = relativePos.clone();
            if (this.relativePos.getY() < 0) {
                this.relativePos.setY(0);
            }

            Vector3 angles = relativePos.copyToPolar();
            this.yaw = (float) (180F - angles.getZ());
            this.pitch = Math.min(0F, (float) (-90F + angles.getY()));
        }

    }

}