buildcraft.robotics.gui.GuiZonePlanner.java Source code

Java tutorial

Introduction

Here is the source code for buildcraft.robotics.gui.GuiZonePlanner.java

Source

/* Copyright (c) 2016 SpaceToad and the BuildCraft team
 * 
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. */
package buildcraft.robotics.gui;

import buildcraft.core.BCCoreItems;
import buildcraft.core.item.ItemPaintbrush_BC8;
import buildcraft.lib.gui.GuiBC8;
import buildcraft.lib.gui.GuiIcon;
import buildcraft.lib.gui.GuiRectangle;
import buildcraft.robotics.container.ContainerZonePlanner;
import buildcraft.robotics.zone.*;
import buildcraft.robotics.zone.ZonePlannerMapChunk.MapColourData;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;

import javax.vecmath.Vector3d;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

public class GuiZonePlanner extends GuiBC8<ContainerZonePlanner> {
    private static final ResourceLocation TEXTURE_BASE = new ResourceLocation(
            "buildcraftrobotics:textures/gui/zone_planner.png");
    private static final int SIZE_X = 256, SIZE_Y = 228;
    private static final GuiIcon ICON_GUI = new GuiIcon(TEXTURE_BASE, 0, 0, SIZE_X, SIZE_Y);
    private static final GuiIcon ICON_PROGRESS_INPUT = new GuiIcon(TEXTURE_BASE, 9, 228, 28, 9);
    private static final GuiIcon ICON_PROGRESS_OUTPUT = new GuiIcon(TEXTURE_BASE, 0, 228, 9, 28);
    private static final GuiRectangle RECT_PROGRESS_INPUT = new GuiRectangle(44, 128, 28, 9);
    private static final GuiRectangle RECT_PROGRESS_OUTPUT = new GuiRectangle(236, 45, 9, 28);
    private float startMouseX = 0;
    private float startMouseY = 0;
    private float startPositionX = 0;
    private float startPositionZ = 0;
    private float camY = 256;
    private float scaleSpeed = 0;
    private float positionX = 0;
    private float positionZ = 0;
    private boolean canDrag = false;
    private BlockPos lastSelected = null;
    private BlockPos selectionStartXZ = null;
    private ZonePlan bufferLayer = null;

    public GuiZonePlanner(ContainerZonePlanner container) {
        super(container);
        xSize = SIZE_X;
        ySize = SIZE_Y;
        BlockPos tilePos = container.tile.getPos();
        positionX = tilePos.getX();
        positionZ = tilePos.getZ();
    }

    private ItemStack getCurrentStack() {
        return mc.player.inventory.getItemStack();
    }

    private ItemStack getPaintbrush() {
        ItemStack currentStack = getCurrentStack();
        if (currentStack != null && currentStack.getItem() instanceof ItemPaintbrush_BC8) {
            return currentStack;
        }
        return null;
    }

    private ItemPaintbrush_BC8.Brush getPaintbrushBrush() {
        ItemStack paintbrush = getPaintbrush();
        if (paintbrush != null) {
            return BCCoreItems.paintbrush.getBrushFromStack(paintbrush);
        }
        return null;
    }

    @Override
    public void handleMouseInput() throws IOException {
        int wheel = Mouse.getEventDWheel();
        if (wheel != 0) {
            scaleSpeed -= wheel / 30F;
        }
        super.handleMouseInput();
    }

    @Override
    protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
        super.mouseClicked(mouseX, mouseY, mouseButton);
        canDrag = false;
        if (getPaintbrush() != null) {
            if (lastSelected != null) {
                selectionStartXZ = lastSelected;
            }
        } else if (getCurrentStack() == null) {
            startPositionX = positionX;
            startPositionZ = positionZ;
            startMouseX = mouseX;
            startMouseY = mouseY;
            canDrag = true;
        }
    }

    @Override
    protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) {
        super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick);
        if (!canDrag) {
            if (lastSelected != null && getPaintbrushBrush() != null) {
                bufferLayer = new ZonePlan(container.tile.layers[getPaintbrushBrush().colour.getMetadata()]);
                if (selectionStartXZ != null && getPaintbrushBrush() != null && lastSelected != null) {
                    final ZonePlan layer = container.tile.layers[getPaintbrushBrush().colour.getMetadata()];
                    for (int x = Math.min(selectionStartXZ.getX(), lastSelected.getX()); x < Math
                            .max(selectionStartXZ.getX(), lastSelected.getX()); x++) {
                        for (int z = Math.min(selectionStartXZ.getZ(), lastSelected.getZ()); z < Math
                                .max(selectionStartXZ.getZ(), lastSelected.getZ()); z++) {
                            if (clickedMouseButton == 0) {
                                bufferLayer.set(x, z, true);
                            } else if (clickedMouseButton == 1) {
                                bufferLayer.set(x, z, false);
                            }
                        }
                    }
                }
            }
            return;
        }
        float deltaX = mouseX - startMouseX;
        float deltaY = mouseY - startMouseY;
        float s = 0.3F;
        positionX = startPositionX - deltaX * s;
        positionZ = startPositionZ - deltaY * s;
    }

    @Override
    protected void mouseReleased(int mouseX, int mouseY, int state) {
        super.mouseReleased(mouseX, mouseY, state);
        selectionStartXZ = null;
        if (getPaintbrushBrush() != null && bufferLayer != null) {
            container.tile.layers[getPaintbrushBrush().colour.getMetadata()] = bufferLayer;
            container.tile.sendLayerToServer(getPaintbrushBrush().colour.getMetadata());
        }
        bufferLayer = null;
    }

    @Override
    protected void drawBackgroundLayer(float partialTicks) {
        ICON_GUI.drawAt(rootElement);

        ICON_PROGRESS_INPUT.drawCutInside(RECT_PROGRESS_INPUT
                .createProgress(container.tile.deltaProgressInput.getDynamic(partialTicks) / 100, 1)
                .offset(rootElement));
        ICON_PROGRESS_OUTPUT.drawCutInside(RECT_PROGRESS_OUTPUT
                .createProgress(1, container.tile.deltaProgressOutput.getDynamic(partialTicks) / 100)
                .offset(rootElement));
    }

    @SuppressWarnings("PointlessBitwiseExpression")
    @Override
    protected void drawForegroundLayer() {
        camY += scaleSpeed;
        scaleSpeed *= 0.7F;
        int posX = (int) positionX;
        int posZ = (int) positionZ;
        int dimension = Minecraft.getMinecraft().world.provider.getDimension();
        {
            ChunkPos chunkPos = new ChunkPos(posX >> 4, posZ >> 4);
            ZonePlannerMapChunkKey key = new ZonePlannerMapChunkKey(chunkPos, dimension, container.tile.getLevel());
            ZonePlannerMapChunk chunk = ZonePlannerMapDataClient.INSTANCE.getLoadedChunk(key);
            BlockPos pos = null;
            if (chunk != null) {
                MapColourData data = chunk.getData(posX, posZ);
                if (data != null) {
                    pos = new BlockPos(posX, data.posY, posZ);
                }
            }
            if (pos != null && pos.getY() + 10 > camY) {
                camY = Math.max(camY, pos.getY() + 10);
            }
        }
        int x = guiLeft;
        int y = guiTop;
        if (lastSelected != null) {
            String text = "X: " + lastSelected.getX() + " Y: " + lastSelected.getY() + " Z: " + lastSelected.getZ();
            fontRendererObj.drawString(text, x + 130, y + 130, 0x404040);
        }
        int offsetX = 8;
        int offsetY = 9;
        int sizeX = 213;
        int sizeY = 100;
        GlStateManager.clear(GL11.GL_DEPTH_BUFFER_BIT); // TODO: save depth buffer?
        GlStateManager.pushMatrix();
        GlStateManager.matrixMode(GL11.GL_PROJECTION);
        GlStateManager.pushMatrix();
        GlStateManager.loadIdentity();
        ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
        GlStateManager.viewport(//
                (x + offsetX) * scaledResolution.getScaleFactor(), //
                Minecraft.getMinecraft().displayHeight - (sizeY + y + offsetY) * scaledResolution.getScaleFactor(), //
                sizeX * scaledResolution.getScaleFactor(), //
                sizeY * scaledResolution.getScaleFactor()//
        );
        GlStateManager.scale(scaledResolution.getScaleFactor(), scaledResolution.getScaleFactor(), 1);
        GLU.gluPerspective(70.0F, (float) sizeX / sizeY, 1F, 1000.0F);
        GlStateManager.matrixMode(GL11.GL_MODELVIEW);
        GlStateManager.loadIdentity();
        RenderHelper.enableStandardItemLighting();
        GlStateManager.enableRescaleNormal();
        GlStateManager.rotate(90, 1, 0, 0); // look down
        GlStateManager.pushMatrix();
        GlStateManager.translate(-positionX, -camY, -positionZ);
        GlStateManager.disableBlend();
        GlStateManager.disableAlpha();
        GlStateManager.disableTexture2D();
        int chunkBaseX = posX >> 4;
        int chunkBaseZ = posZ >> 4;
        int radius = 8;
        for (int chunkX = chunkBaseX - radius; chunkX < chunkBaseX + radius; chunkX++) {
            for (int chunkZ = chunkBaseZ - radius; chunkZ < chunkBaseZ + radius; chunkZ++) {
                ZonePlannerMapChunkKey key = new ZonePlannerMapChunkKey(new ChunkPos(chunkX, chunkZ), dimension,
                        container.tile.getLevel());
                int glId = ZonePlannerMapRenderer.INSTANCE.getChunkGlList(key);
                if (glId > 0) {
                    GlStateManager.callList(glId);
                }
            }
        }

        BlockPos found = null;
        int foundColor = 0;

        if (Mouse.getX() / scaledResolution.getScaleFactor() > x + offsetX
                && Mouse.getX() / scaledResolution.getScaleFactor() < x + offsetX + sizeX
                && scaledResolution.getScaledHeight() - Mouse.getY() / scaledResolution.getScaleFactor() > y
                        + offsetY
                && scaledResolution.getScaledHeight() - Mouse.getY() / scaledResolution.getScaleFactor() < y
                        + offsetY + sizeY) {
            FloatBuffer projectionBuffer = BufferUtils.createFloatBuffer(16);
            FloatBuffer modelViewBuffer = BufferUtils.createFloatBuffer(16);
            IntBuffer viewportBuffer = BufferUtils.createIntBuffer(16);

            GlStateManager.getFloat(GL11.GL_PROJECTION_MATRIX, projectionBuffer);
            GlStateManager.getFloat(GL11.GL_MODELVIEW_MATRIX, modelViewBuffer);
            GlStateManager.glGetInteger(GL11.GL_VIEWPORT, viewportBuffer);

            FloatBuffer positionNearBuffer = BufferUtils.createFloatBuffer(3);
            FloatBuffer positionFarBuffer = BufferUtils.createFloatBuffer(3);

            GLU.gluUnProject(Mouse.getX(), Mouse.getY(), 0f, modelViewBuffer, projectionBuffer, viewportBuffer,
                    positionNearBuffer);
            GLU.gluUnProject(Mouse.getX(), Mouse.getY(), 1f, modelViewBuffer, projectionBuffer, viewportBuffer,
                    positionFarBuffer);

            Vector3d rayStart = new Vector3d(positionNearBuffer.get(0), positionNearBuffer.get(1),
                    positionNearBuffer.get(2));
            Vector3d rayPosition = new Vector3d(rayStart);
            Vector3d rayDirection = new Vector3d(positionFarBuffer.get(0), positionFarBuffer.get(1),
                    positionFarBuffer.get(2));
            rayDirection.sub(rayStart);
            rayDirection.normalize();
            Vector3d offset = new Vector3d(rayDirection);
            offset.scale(100);
            rayPosition.add(offset);
            rayDirection.negate();

            for (int i = 0; i < 100; i++) {
                int chunkX = (int) Math.round(rayPosition.getX()) >> 4;
                int chunkZ = (int) Math.round(rayPosition.getZ()) >> 4;
                ZonePlannerMapChunk zonePlannerMapChunk = ZonePlannerMapDataClient.INSTANCE
                        .getLoadedChunk(new ZonePlannerMapChunkKey(new ChunkPos(chunkX, chunkZ),
                                Minecraft.getMinecraft().world.provider.getDimension(), container.tile.getLevel()));
                if (zonePlannerMapChunk != null) {
                    BlockPos pos = new BlockPos(Math.round(rayPosition.getX()) - chunkX * 16,
                            Math.round(rayPosition.getY()), Math.round(rayPosition.getZ()) - chunkZ * 16);
                    MapColourData data = zonePlannerMapChunk.getData(pos.getX(), pos.getZ());
                    if (data != null && data.posY >= pos.getY()) {
                        found = new BlockPos(pos.getX() + chunkX * 16, data.posY, pos.getZ() + chunkZ * 16);
                        foundColor = data.colour;
                    }
                } else {
                    break;
                }
                rayPosition.add(rayDirection);
            }
        }

        if (found != null) {
            GlStateManager.disableDepth();
            GlStateManager.enableBlend();
            GlStateManager.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
            GlStateManager.glLineWidth(2);
            int r = (int) (((foundColor >> 16) & 0xFF) * 0.7);
            int g = (int) (((foundColor >> 8) & 0xFF) * 0.7);
            int b = (int) (((foundColor >> 0) & 0xFF) * 0.7);
            int a = 0x77;
            ZonePlannerMapRenderer.INSTANCE.setColor(r << 16 | g << 8 | b << 0 | a << 24);
            VertexBuffer builder = Tessellator.getInstance().getBuffer();
            builder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
            ZonePlannerMapRenderer.INSTANCE.drawBlockCuboid(builder, found.getX(), found.getY(), found.getZ());
            Tessellator.getInstance().draw();
            GlStateManager.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
            GlStateManager.disableBlend();
            GlStateManager.enableDepth();
        }

        GlStateManager.disableLighting();
        GlStateManager.enableBlend();

        for (int i = 0; i < container.tile.layers.length; i++) {
            if (getPaintbrushBrush() != null && getPaintbrushBrush().colour.getMetadata() != i) {
                continue;
            }
            ZonePlan layer = container.tile.layers[i];
            if (getPaintbrushBrush() != null && getPaintbrushBrush().colour.getMetadata() == i
                    && bufferLayer != null) {
                layer = bufferLayer;
            }
            if (!layer.getChunkPoses().isEmpty()) {
                for (int chunkX = chunkBaseX - radius; chunkX < chunkBaseX + radius; chunkX++) {
                    for (int chunkZ = chunkBaseZ - radius; chunkZ < chunkBaseZ + radius; chunkZ++) {
                        ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
                        if (layer.hasChunk(chunkPos)) {
                            for (int blockX = chunkPos.getXStart(); blockX <= chunkPos.getXEnd(); blockX++) {
                                for (int blockZ = chunkPos.getZStart(); blockZ <= chunkPos.getZEnd(); blockZ++) {
                                    if (layer.get(blockX, blockZ)) {
                                        int height = 256;
                                        ZonePlannerMapChunk zonePlannerMapChunk = ZonePlannerMapDataClient.INSTANCE
                                                .getLoadedChunk(new ZonePlannerMapChunkKey(chunkPos, dimension,
                                                        container.tile.getLevel()));
                                        if (zonePlannerMapChunk != null) {
                                            MapColourData data = zonePlannerMapChunk.getData(blockX, blockZ);
                                            if (data != null) {
                                                height = data.posY;
                                            }
                                        }
                                        int color = EnumDyeColor.byMetadata(i).getMapColor().colorValue;
                                        int r = (color >> 16) & 0xFF;
                                        int g = (color >> 8) & 0xFF;
                                        int b = (color >> 0) & 0xFF;
                                        int a = 0x55;
                                        ZonePlannerMapRenderer.INSTANCE
                                                .setColor(r << 16 | g << 8 | b << 0 | a << 24);
                                        VertexBuffer builder = Tessellator.getInstance().getBuffer();
                                        builder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
                                        ZonePlannerMapRenderer.INSTANCE.drawBlockCuboid(builder, blockX,
                                                height + 0.1, blockZ, height, 0.6);
                                        Tessellator.getInstance().draw();
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        GlStateManager.disableBlend();
        GlStateManager.disableLighting();
        GlStateManager.enableTexture2D();

        lastSelected = found;
        GlStateManager.popMatrix();
        GlStateManager.disableRescaleNormal();
        GlStateManager.matrixMode(GL11.GL_PROJECTION);
        GlStateManager.viewport(0, 0, Minecraft.getMinecraft().displayWidth,
                Minecraft.getMinecraft().displayHeight);
        GlStateManager.popMatrix();
        GlStateManager.matrixMode(GL11.GL_MODELVIEW);
        GlStateManager.popMatrix();
        RenderHelper.disableStandardItemLighting();
        GlStateManager.disableBlend();
    }
}