org.spoutcraft.client.gui.minimap.MapRenderer.java Source code

Java tutorial

Introduction

Here is the source code for org.spoutcraft.client.gui.minimap.MapRenderer.java

Source

/*
 * This file is part of Spoutcraft.
 *
 * Copyright (c) 2011 Spout LLC <http://www.spout.org/>
 * Spoutcraft is licensed under the GNU Lesser General Public License.
 *
 * Spoutcraft is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Spoutcraft is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.spoutcraft.client.gui.minimap;

import org.lwjgl.opengl.GL11;
import org.newdawn.slick.opengl.Texture;

import net.minecraft.client.Minecraft;
import net.minecraft.src.Entity;
import net.minecraft.src.MathHelper;
import net.minecraft.src.Tessellator;

import org.spoutcraft.api.Spoutcraft;
import org.spoutcraft.api.gui.RenderUtil;

public class MapRenderer {
    /** Direction you're facing */
    public float direction = 0.0f;

    /** Last direction you were facing */
    public float oldDir = 0.0f;

    private Map map;
    private TextureManager texman;

    private double distanceToFocus;

    /**
     * @param minimap
     *         minimap instance to init with
     */
    public MapRenderer(ZanMinimap minimap) {
        map = minimap.map;
        texman = minimap.texman;
    }

    /**
     * Do rendering
     *
     * @param scWidth
     *         screen width
     * @param scHeight
     *         screen height
     */
    public void onRenderTick(int scWidth, int scHeight) {
        if (this.oldDir != Minecraft.theMinecraft.thePlayer.rotationYaw) {
            this.direction += this.oldDir - Minecraft.theMinecraft.thePlayer.rotationYaw;
            this.oldDir = Minecraft.theMinecraft.thePlayer.rotationYaw;
        }

        if (this.direction >= 360.0f)
            this.direction %= 360.0f;

        if (this.direction < 0.0f) {
            while (this.direction < 0.0f)
                this.direction += 360.0f;
        }

        GL11.glPushMatrix();
        GL11.glTranslatef(scWidth, 0.0f, 0.0f);
        GL11.glTranslatef(MinimapConfig.getInstance().getAdjustX(), MinimapConfig.getInstance().getAdjustY(), 0);
        GL11.glScalef(MinimapConfig.getInstance().getSizeAdjust(), MinimapConfig.getInstance().getSizeAdjust(), 1F);
        if (!MinimapConfig.getInstance().isScale()) {
            float scaleFactor = Math.max(scWidth / 427, scHeight / 240F);
            GL11.glScalef(scaleFactor, scaleFactor, 1);
        }
        renderMap();
        if (MinimapConfig.getInstance().isCavemap())
            renderMapFull(0, scHeight);

        GL11.glDepthMask(true);
        GL11.glDisable(3042);
        GL11.glEnable(2929);
        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);

        showCoords(0);
        GL11.glPopMatrix();
    }

    private void renderMap() {
        GL11.glDisable(2929);
        GL11.glEnable(3042);
        GL11.glDepthMask(false);
        GL11.glBlendFunc(770, 0);
        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);

        if (MinimapConfig.getInstance().isEnabled()) {
            if (MinimapConfig.getInstance().isSquare()) {
                // Scale
                GL11.glPushMatrix();
                switch (MinimapConfig.getInstance().getZoom()) {
                case 0:
                    GL11.glScalef(8F, 8F, 1F);
                    GL11.glTranslatef(56, 0, 0F);
                    break;
                case 1:
                    GL11.glScalef(4F, 4F, 1F);
                    GL11.glTranslatef(48, 0, 0F);
                    break;
                case 2:
                    GL11.glScalef(2F, 2F, 1F);
                    GL11.glTranslatef(32, 0, 0F);
                    break;
                }

                map.loadColorImage();

                drawOnMap();

                if (MinimapConfig.getInstance().isHeightmap()) {
                    GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_DST_COLOR);

                    map.loadHeightImage();

                    drawOnMap();
                }

                GL11.glPopMatrix();

                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
                renderEntities();

                try {
                    GL11.glPushMatrix();
                    GL11.glScalef(1.8f, 1.8f, 1.0f);
                    GL11.glTranslatef(27, -1, 0F); // don't ask
                    if (MinimapConfig.getInstance().isShowBackground()) {
                        texman.loadMinimap();
                    } else {
                        GL11.glScalef(138F / 256F, 138F / 256F, 1F);
                        GL11.glTranslatef(-54, 0, 0);
                        texman.loadWhiteMinimap();
                    }
                    drawOnMap();
                } catch (Exception e) {
                    //               System.err.println("error: minimap overlay not found!");
                    //               e.printStackTrace();
                } finally {
                    GL11.glPopMatrix();
                }

                renderWaypoints();

                try {
                    GL11.glPushMatrix();
                    texman.loadMMArrow();
                    GL11.glTranslatef(-34.0F, 30.0F, 0.0F);
                    GL11.glRotatef(-this.direction + 90F, 0.0F, 0.0F, 1.0F);
                    GL11.glTranslatef(32.0F, -(32.0F), 0.0F);
                    drawOnMap();
                } catch (Exception e) {
                    //               System.err.println("Error: minimap arrow not found!");
                    e.printStackTrace();
                } finally {
                    GL11.glPopMatrix();
                }

                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

                // render directions with fudge factor to make them line up
                GL11.glPushMatrix();
                GL11.glTranslatef(-2, 2, 0.0F);
                drawDirections();
                drawFocusSquare();
                GL11.glPopMatrix();

            } else {
                GL11.glPushMatrix();

                map.loadColorImage();

                GL11.glTranslatef(-32.0f, 32.0F, 0.0F);
                GL11.glRotatef(this.direction + 90.0F, 0.0F, 0.0F, 1.0F);
                GL11.glTranslatef(32.0F, -(32.0F), 0.0F);

                switch (MinimapConfig.getInstance().getZoom()) {
                case 0:
                    GL11.glScalef(8F, 8F, 1F);
                    GL11.glTranslatef(56.25F, 0.25F, 0F);
                    break;
                case 1:
                    GL11.glScalef(4F, 4F, 1F);
                    GL11.glTranslatef(48.5F, 0.5F, 0F);
                    break;
                case 2:
                    GL11.glScalef(2F, 2F, 1F);
                    GL11.glTranslatef(33F, 1F, 0F);
                    break;
                case 3:
                    GL11.glTranslatef(2F, 2F, 0F);
                    break;
                }

                drawOnMap();

                if (MinimapConfig.getInstance().isHeightmap()) {
                    GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_DST_COLOR);

                    map.loadHeightImage();

                    drawOnMap();
                }

                GL11.glPopMatrix();
                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

                renderWaypoints();
                renderEntities();
                drawRound();
                drawDirections();
                GL11.glPushMatrix();
                drawFocusRound();
                GL11.glPopMatrix();
            }
        }
    }

    private void renderEntities() {
        if (!Spoutcraft.hasPermission("spout.plugin.minimap.showentities")) {
            return;
        }
        if (!MinimapConfig.getInstance().isShowingEntities()) {
            return;
        }
        double playerX = map.getPlayerX();
        double playerZ = map.getPlayerZ();

        synchronized (map.watchedEntities) {
            for (WatchedEntity w : map.watchedEntities) {
                Entity e = w.entity;
                double entityX = e.posX - playerX;
                double entityZ = e.posZ - playerZ;
                boolean render = false;

                int circleX = MathHelper.floor_double(playerX);
                int circleY = MathHelper.floor_double(playerZ);

                if (MinimapConfig.getInstance().isSquare()) {
                    render = Math.abs(playerX - (int) e.posX) < map.renderSize
                            && Math.abs(playerZ - (int) e.posZ) < map.renderSize;
                } else {
                    render = MinimapUtils.insideCircle(circleX, circleY, map.renderSize / 2, (int) e.posX,
                            (int) e.posZ);
                }
                Texture tex = w.getTexture();
                if (render && tex != null) {
                    GL11.glPushMatrix();
                    GL11.glTranslatef(-32.0f, 32.0F, 0.0F);
                    if (!MinimapConfig.getInstance().isSquare()) {
                        GL11.glRotatef((this.direction + 90.0F), 0.0F, 0.0F, 1.0F);
                    }
                    switch (MinimapConfig.getInstance().getZoom()) {
                    case 0:
                        GL11.glTranslated(-entityZ, entityX, 0F);
                        break;
                    case 1:
                        GL11.glTranslated(-entityZ * 0.45F, entityX * 0.45F, 0F);
                        break;
                    case 2:
                        GL11.glTranslated(-entityZ * 0.25F, entityX * 0.28F, 0F);
                        break;
                    case 3:
                        GL11.glTranslated(-entityZ * 0.125F, entityX * 0.125F, 0F);
                        break;
                    }
                    GL11.glScaled(0.05, 0.05, 0.05);
                    GL11.glTranslated(-32f, -32f, 0);
                    GL11.glRotatef(180, 0, 0, 1);
                    if (!MinimapConfig.getInstance().isSquare()) {
                        GL11.glRotatef(-(this.direction + 90f), 0, 0, 1);
                    }
                    tex.bind();
                    drawOnMap();
                    GL11.glPopMatrix();
                }
            }
        }
    }

    private void drawFocusRound() {
        Waypoint focus = MinimapConfig.getInstance().getFocussedWaypoint();
        if (focus != null) {
            GL11.glTranslated(-map.renderSize / 4d, map.renderSize / 4d, 0);
            GL11.glPushMatrix();
            GL11.glRotatef(this.direction - 180f, 0f, 0f, 1f);
            double px = Minecraft.theMinecraft.thePlayer.posX;
            double pz = Minecraft.theMinecraft.thePlayer.posZ;
            int x = focus.x;
            int z = focus.z;

            int radius = map.renderSize / 4 - 4;
            double dx = x - px;
            double dz = z - pz;
            double l = Math.sqrt(dx * dx + dz * dz);
            this.distanceToFocus = l;
            if (l > radius * 2) {
                double f = radius / l;
                int fx = (int) (f * dx);
                int fz = (int) (f * dz);
                RenderUtil.drawRectangle(fx - 1, fz - 1, fx + 1, fz + 1, 0xff00ffff);
            }
            GL11.glPopMatrix();
        }
    }

    private void drawFocusSquare() {
        Waypoint focus = MinimapConfig.getInstance().getFocussedWaypoint();
        if (focus != null) {
            GL11.glTranslated(-map.renderSize / 4d, map.renderSize / 4d - 4, 0);
            GL11.glRotatef(90f, 0, 0, 1f);
            RenderUtil.drawRectangle(map.renderSize / 4, 0, map.renderSize / 4 + 2, 2, 0xff0000);
            double px = Minecraft.theMinecraft.thePlayer.posX;
            double pz = Minecraft.theMinecraft.thePlayer.posZ;
            double x = focus.x;
            double z = focus.z;

            double dx = x - px;
            double dz = z - pz;

            double alpha = 0;
            if (dx == 0) {
                alpha = 0d;
            } else {
                alpha = Math.atan(dz / dx);
            }
            double l = Math.sqrt(dx * dx + dz * dz);
            this.distanceToFocus = l;
            if (true) {
                int fx;
                int fz;
                if (Math.abs(dx) > Math.abs(dz)) {
                    if (dx > 0) {
                        fx = map.renderSize / 4;
                    } else {
                        fx = -map.renderSize / 4;
                    }
                    fz = (int) (Math.tan(alpha) * fx);
                } else {
                    if (dz > 0) {
                        fz = map.renderSize / 4;
                    } else {
                        fz = -map.renderSize / 4;
                    }
                    fx = (int) (1 / Math.tan(alpha) * fz);
                }
                if (Math.abs(dx) >= (map.renderSize - 5) / 2 || Math.abs(dz) >= (map.renderSize - 5) / 2) {
                    RenderUtil.drawRectangle(fx - 1, fz - 1, fx + 1, fz + 1, 0xff00ffff);
                }
            }
        }
    }

    private void renderWaypoints() {
        double playerX = Minecraft.theMinecraft.thePlayer.posX;
        double playerZ = Minecraft.theMinecraft.thePlayer.posZ;
        for (Waypoint pt : MinimapConfig.getInstance().getWaypoints(MinimapUtils.getWorldName())) {
            if (pt.enabled) {
                double wayX = playerX - pt.x;
                double wayY = playerZ - pt.z;

                int circleX = MathHelper.floor_double(playerX);
                int circleY = MathHelper.floor_double(playerZ);

                boolean render = false;
                if (MinimapConfig.getInstance().isSquare()) {
                    render = Math.abs(playerX - pt.x) < map.renderSize && Math.abs(playerZ - pt.z) < map.renderSize;
                } else {
                    render = MinimapUtils.insideCircle(circleX, circleY, map.renderSize / 2, pt.x, pt.z);
                }

                if (render) {
                    GL11.glPushMatrix();

                    GL11.glTranslatef(32.0f, -32.0F, 0.0F);
                    GL11.glRotatef(-(this.direction + 90.0F), 0.0F, 0.0F, 1.0F);
                    GL11.glTranslatef(-32.0F, -32.0F, 0.0F);

                    GL11.glTranslatef(-33F, 29F, 0F);
                    switch (MinimapConfig.getInstance().getZoom()) {
                    case 0:
                        GL11.glTranslated(wayY, -wayX, 0F);
                        break;
                    case 1:
                        GL11.glTranslated(wayY * 0.45F, -wayX * 0.45F, 0F);
                        break;
                    case 2:
                        GL11.glTranslated(wayY * 0.25F, -wayX * 0.28F, 0F);
                        break;
                    case 3:
                        GL11.glTranslated(wayY * 0.125F, -wayX * 0.125F, 0F);
                        break;
                    }
                    GL11.glScalef(0.25F, 0.25F, 1F);

                    GL11.glPopMatrix();
                }
            }
        }
        GL11.glColor3f(1f, 1f, 1f);
    }

    private void renderMapFull(int scWidth, int scHeight) {
        map.loadColorImage();
        Tessellator.instance.startDrawingQuads();
        Tessellator.instance.addVertexWithUV((scWidth) / 2 - 128, (scHeight) / 2 + 128, 1.0D, 0.0D, 1.0D);
        Tessellator.instance.addVertexWithUV((scWidth) / 2 + 128, (scHeight) / 2 + 128, 1.0D, 1.0D, 1.0D);
        Tessellator.instance.addVertexWithUV((scWidth) / 2 + 128, (scHeight) / 2 - 128, 1.0D, 1.0D, 0.0D);
        Tessellator.instance.addVertexWithUV((scWidth) / 2 - 128, (scHeight) / 2 - 128, 1.0D, 0.0D, 0.0D);
        Tessellator.instance.draw();

        try {
            GL11.glPushMatrix();
            texman.loadMMArrow();
            GL11.glTranslatef((scWidth) / 2, (scHeight) / 2, 0.0F);
            GL11.glRotatef(-this.direction - 90.0F, 0.0F, 0.0F, 1.0F);
            GL11.glTranslatef(-((scWidth) / 2), -((scHeight) / 2), 0.0F);
            Tessellator.instance.startDrawingQuads();
            Tessellator.instance.addVertexWithUV((scWidth) / 2 - 32, (scHeight) / 2 + 32, 1.0D, 0.0D, 1.0D);
            Tessellator.instance.addVertexWithUV((scWidth) / 2 + 32, (scHeight) / 2 + 32, 1.0D, 1.0D, 1.0D);
            Tessellator.instance.addVertexWithUV((scWidth) / 2 + 32, (scHeight) / 2 - 32, 1.0D, 1.0D, 0.0D);
            Tessellator.instance.addVertexWithUV((scWidth) / 2 - 32, (scHeight) / 2 - 32, 1.0D, 0.0D, 0.0D);
            Tessellator.instance.draw();
        } catch (Exception e) {
            //         System.err.println("Error: minimap arrow not found!");
            e.printStackTrace();
        } finally {
            GL11.glPopMatrix();
        }
    }

    private void showCoords(int scWidth) {
        if (MinimapConfig.getInstance().isCoords()) {
            GL11.glPushMatrix();
            GL11.glScalef(0.5f, 0.5f, 1.0f);
            String xy = ((int) Minecraft.theMinecraft.thePlayer.posX) + ", "
                    + ((int) Minecraft.theMinecraft.thePlayer.posZ);
            int m = Minecraft.theMinecraft.fontRenderer.getStringWidth(xy) / 2;
            Minecraft.theMinecraft.fontRenderer.drawString(xy, scWidth * 2 - 32 * 2 - m, 146, 0xffffff);
            xy = Integer.toString((int) (Minecraft.theMinecraft.thePlayer.posY - 1.620d)); // Substract eyes pos
            m = Minecraft.theMinecraft.fontRenderer.getStringWidth(xy) / 2;
            Minecraft.theMinecraft.fontRenderer.drawString(xy, scWidth * 2 - 32 * 2 - m, 156, 0xffffff);
            if (MinimapConfig.getInstance().getFocussedWaypoint() != null) {
                String text = (int) distanceToFocus + "m";
                int y = MinimapConfig.getInstance().getFocussedWaypoint().y;
                if (distanceToFocus < 10) {
                    double py = Minecraft.theMinecraft.thePlayer.posY;
                    if (y < py - 3) {
                        text = "\\/ " + text;
                    }
                    if (y > py + 3) {
                        text = "/\\ " + text;
                    }
                }
                m = Minecraft.theMinecraft.fontRenderer.getStringWidth(text);
                Minecraft.theMinecraft.fontRenderer.drawString(text, scWidth * 2 - 32 * 2 - m / 2, 166, 0xffffff);
            }
            GL11.glPopMatrix();
        }
    }

    private void drawRound() {
        try {
            GL11.glPushMatrix();
            if (MinimapConfig.getInstance().isShowBackground()) {
                texman.loadRoundmap();
            } else {
                GL11.glScaled(0.95F, 0.95F, 1F);
                GL11.glTranslatef(-2F, 2F, 0);
                texman.loadWhiteRoundmap();
            }
            drawOnMap();
        } catch (Exception localException) {
            //         System.err.println("Error: minimap overlay not found!");
        } finally {
            GL11.glPopMatrix();
        }
    }

    private void drawOnMap() {
        Tessellator.instance.startDrawingQuads();
        Tessellator.instance.addVertexWithUV(-64.0D, 64.0D, 1.0D, 0.0D, 1.0D);
        Tessellator.instance.addVertexWithUV(0, 64.0D, 1.0D, 1.0D, 1.0D);
        Tessellator.instance.addVertexWithUV(0, 0, 1.0D, 1.0D, 0.0D);
        Tessellator.instance.addVertexWithUV(-64.0D, 0, 1.0D, 0.0D, 0.0D);
        Tessellator.instance.draw();
    }

    private void drawDirections() {
        if (!MinimapConfig.getInstance().isDirections()) {
            return;
        }
        float dir = this.direction;
        GL11.glPushMatrix();
        GL11.glScalef(0.5f, 0.5f, 1.0f);
        GL11.glTranslated((64.0D * Math.sin(Math.toRadians(-(dir)))), (64.0D * Math.cos(Math.toRadians(-(dir)))),
                0.0D);
        Minecraft.theMinecraft.fontRenderer.drawString("N", -66, 60, 0xffffff);
        GL11.glPopMatrix();

        dir += 90;

        GL11.glPushMatrix();
        GL11.glScalef(0.5f, 0.5f, 1.0f);
        GL11.glTranslated((64.0D * Math.sin(Math.toRadians(-dir))), (64.0D * Math.cos(Math.toRadians(-dir))), 0.0D);
        Minecraft.theMinecraft.fontRenderer.drawString("E", -66, 60, 0xffffff);
        GL11.glPopMatrix();

        dir += 90;

        GL11.glPushMatrix();
        GL11.glScalef(0.5f, 0.5f, 1.0f);
        GL11.glTranslated((64.0D * Math.sin(Math.toRadians(-(dir)))), (64.0D * Math.cos(Math.toRadians(-(dir)))),
                0.0D);
        Minecraft.theMinecraft.fontRenderer.drawString("S", -66, 60, 0xffffff);
        GL11.glPopMatrix();

        dir += 90;

        GL11.glPushMatrix();
        GL11.glScalef(0.5f, 0.5f, 1.0f);
        GL11.glTranslated((64.0D * Math.sin(Math.toRadians(-(dir)))), (64.0D * Math.cos(Math.toRadians(-(dir)))),
                0.0D);
        Minecraft.theMinecraft.fontRenderer.drawString("W", -66, 60, 0xffffff);
        GL11.glPopMatrix();
    }
}