org.agpu.oc.common.tileentity.AdvancedMonitor.java Source code

Java tutorial

Introduction

Here is the source code for org.agpu.oc.common.tileentity.AdvancedMonitor.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.agpu.oc.common.tileentity;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import li.cil.oc.api.Network;
import li.cil.oc.api.network.Component;
import li.cil.oc.api.network.Node;
import li.cil.oc.api.network.SidedEnvironment;
import li.cil.oc.api.network.Visibility;
import li.cil.oc.api.prefab.TileEntityEnvironment;
import net.minecraft.client.Minecraft;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.agpu.oc.common.block.BlockAdvancedMonitor;
import org.agpu.oc.common.networking.AdvancedMonitorMessage;
import org.agpu.oc.common.networking.NetworkManager;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL30;
import org.lwjgl.util.glu.GLU;

/**
 *
 * @author arnau
 */
public class AdvancedMonitor extends TileEntityEnvironment implements SidedEnvironment {

    //Multiblock stuff
    private int monitorsW = 1;
    private int monitorsH = 1;
    private AdvancedMonitor origin = this;
    private Set<AdvancedMonitor> monitors = new HashSet<AdvancedMonitor>();

    //Rendering stuff
    public int width = 512;
    public int height = 512;
    private float cr, cg, cb, ca;

    //Client rendering stuff
    @SideOnly(Side.CLIENT)
    public boolean shouldRender;

    @SideOnly(Side.CLIENT)
    public int textureID;

    @SideOnly(Side.CLIENT)
    public int frameBufferID;

    public AdvancedMonitor(boolean client) {
        this.node = Network.newNode(this, Visibility.Network).withComponent("ascreen").create();
        monitors.add(this);
        if (client) {
            shouldRender = true;
            textureID = -1;
        }
    }

    public void setResolution(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public void startDrawing3D(int x, int y, int width, int height, float fov, float zNear, float zFar) {
        if (worldObj.isRemote) {
            GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferID);

            GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
            GL11.glViewport(0, 0, width, height);

            GL11.glMatrixMode(GL11.GL_PROJECTION);
            GL11.glPushMatrix();
            GL11.glLoadIdentity();
            GLU.gluPerspective(fov, (float) width / (float) height, zNear, zFar);

            GL11.glMatrixMode(GL11.GL_MODELVIEW);
            GL11.glPushMatrix();
            GL11.glLoadIdentity();

            GL11.glClearColor(cr, cg, cb, ca);
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
        }
    }

    public void startDrawing2D(int x, int y, int width, int height) {
        if (worldObj.isRemote) {
            GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferID);

            GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
            GL11.glViewport(x, y, width, height);

            GL11.glMatrixMode(GL11.GL_PROJECTION);
            GL11.glPushMatrix();
            GL11.glLoadIdentity();
            GL11.glOrtho(0, width, height, 0, 1, -1);

            GL11.glMatrixMode(GL11.GL_MODELVIEW);
            GL11.glPushMatrix();
            GL11.glLoadIdentity();

            GL11.glClearColor(cr, cg, cb, ca);
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
        }
    }

    public void swapBuffers(NBTTagCompound tag) {
        if (worldObj.isRemote) {
            for (int i = 0; i < tag.getInteger("commands"); i++) {
                NBTTagCompound t = tag.getCompoundTag(String.valueOf(i));
                String type = t.getString("type");
                if (type.equals("startDrawing3D")) {
                    startDrawing3D(t.getInteger("x"), t.getInteger("y"), t.getInteger("width"),
                            t.getInteger("height"), t.getFloat("fov"), t.getFloat("zNear"), t.getFloat("zFar"));
                } else if (type.equals("startDrawing2D")) {
                    startDrawing2D(t.getInteger("x"), t.getInteger("y"), t.getInteger("width"),
                            t.getInteger("height"));
                } else if (type.equals("setColor")) {
                    GL11.glColor4f(t.getFloat("r"), t.getFloat("g"), t.getFloat("b"), t.getFloat("a"));
                } else if (type.equals("vertex3f")) {
                    GL11.glVertex3f(t.getFloat("x"), t.getFloat("y"), t.getFloat("z"));
                } else if (type.equals("vertex2i")) {
                    GL11.glVertex2i(t.getInteger("x"), t.getInteger("y"));
                } else if (type.equals("translate")) {
                    GL11.glTranslatef(t.getFloat("x"), t.getFloat("y"), t.getFloat("z"));
                } else if (type.equals("rotate")) {
                    GL11.glRotatef(t.getFloat("angle"), t.getFloat("x"), t.getFloat("y"), t.getFloat("z"));
                } else if (type.equals("scale")) {
                    GL11.glScalef(t.getFloat("x"), t.getFloat("y"), t.getFloat("z"));
                } else if (type.equals("begin")) {
                    GL11.glBegin(t.getInteger("m"));
                } else if (type.equals("end")) {
                    GL11.glEnd();
                } else if (type.equals("string")) {
                    Minecraft.getMinecraft().fontRendererObj.drawString(t.getString("string"), t.getInteger("x"),
                            t.getInteger("y"), t.getInteger("color"));
                } else if (type.equals("enable")) {
                    GL11.glEnable(t.getInteger("v"));
                } else if (type.equals("disable")) {
                    GL11.glDisable(t.getInteger("v"));
                } else {
                    System.out.println("Unknown packet type received: " + type);
                }
            }

            GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);

            GL11.glMatrixMode(GL11.GL_PROJECTION);
            GL11.glPopMatrix();

            GL11.glMatrixMode(GL11.GL_MODELVIEW);
            GL11.glPopMatrix();
            GL11.glPopAttrib();
        }
    }

    public void setClearColor(float r, float g, float b, float a) {
        if (worldObj.isRemote) {
            cr = r;
            cg = g;
            cb = b;
            ca = a;
        } else {
            NetworkManager.advancedMonitorChannel
                    .sendToAll(new AdvancedMonitorMessage.SetClearColorMessage(pos, r, g, b, a));
        }
    }

    @Override
    public Node sidedNode(EnumFacing side) {
        return node();
    }

    @Override
    public boolean canConnect(EnumFacing side) {
        return ((BlockAdvancedMonitor.Rotation) this.getBlockType().getStateFromMeta(this.getBlockMetadata())
                .getValue(BlockAdvancedMonitor.ROTATION)).compareEnumFacing(side);
    }

    public void checkMultiblock() {
        Queue<AdvancedMonitor> screens = new LinkedList<AdvancedMonitor>();
        Queue<AdvancedMonitor> queue = new LinkedList<AdvancedMonitor>();
        queue.add(this);
        int xMod = 0;
        int zMod = 0;
        switch (((BlockAdvancedMonitor.Rotation) worldObj.getBlockState(getPos())
                .getValue(BlockAdvancedMonitor.ROTATION))) {
        case NORTH:
            xMod = -1;
            break;
        case SOUTH:
            xMod = 1;
            break;
        case EAST:
            zMod = 1;
            break;
        case WEST:
            zMod = -1;
            break;
        }
        while (!queue.isEmpty()) {
            AdvancedMonitor m = queue.remove();
            screens.add(m);
            tryAddingToQueue(m.getPos().add(xMod * 1, 0, zMod * 1), screens, queue);
            tryAddingToQueue(m.getPos().add(xMod * -1, 0, zMod * -1), screens, queue);
            tryAddingToQueue(m.getPos().add(0, 1, 0), screens, queue);
            tryAddingToQueue(m.getPos().add(0, -1, 0), screens, queue);
        }
        while (!screens.isEmpty()) {
            AdvancedMonitor m = screens.element();
            while (m.tryMerging(xMod, zMod)) {

            }
            ;
            for (AdvancedMonitor am : m.monitors) {
                screens.remove(am);
                queue.add(am);
            }
        }
        while (!queue.isEmpty()) {
            AdvancedMonitor m = queue.remove();
            if (!worldObj.isRemote) {
                if (m.isOrigin()) {
                    ((Component) m.node()).setVisibility(Visibility.Network);
                } else {
                    ((Component) m.node()).setVisibility(Visibility.None);
                }
            }
        }
    }

    private void tryAddingToQueue(BlockPos pos, Queue<AdvancedMonitor> s, Queue<AdvancedMonitor> q) {
        if (worldObj.getBlockState(pos).getBlock() instanceof BlockAdvancedMonitor
                && worldObj.getBlockState(pos) == worldObj.getBlockState(getPos())) {
            AdvancedMonitor m = (AdvancedMonitor) worldObj.getTileEntity(pos);
            if (!s.contains(m)) {
                s.add(m);
                q.add(m);
            }
        }
    }

    private boolean tryMerging(int xMod, int zMod) {
        return tryMergingTo(getPos().add(xMod * monitorsW, 0, zMod * monitorsW))
                || tryMergingTo(getPos().add(xMod, 0, zMod)) || tryMergingTo(getPos().add(0, monitorsH, 0))
                || tryMergingTo(getPos().add(0, -1, 0));
    }

    private boolean tryMergingTo(BlockPos pos) {
        if (worldObj.getTileEntity(pos) != null && worldObj.getTileEntity(pos) instanceof AdvancedMonitor) {
            AdvancedMonitor m = (AdvancedMonitor) worldObj.getTileEntity(pos);
            boolean mergeW = m.origin.getPos().getY() == origin.getPos().getY() && m.monitorsH == monitorsH
                    && !monitors.contains(m);
            boolean mergeH = m.origin.getPos().getX() == origin.getPos().getX()
                    && pos.getZ() == origin.getPos().getZ() && m.monitorsW == monitorsW && !monitors.contains(m);
            if (mergeW || mergeH) {
                AdvancedMonitor newOrigin;
                if (mergeW) {
                    if (pos.getX() < origin.getPos().getX() || pos.getZ() < origin.getPos().getZ()) {
                        newOrigin = m.origin;
                    } else {
                        newOrigin = origin;
                    }
                } else {
                    if (pos.getY() < origin.getPos().getY()) {
                        newOrigin = m.origin;
                    } else {
                        newOrigin = origin;
                    }
                }
                int newWidth, newHeight;
                if (mergeW) {
                    newWidth = monitorsW + m.monitorsW;
                    newHeight = monitorsH;
                } else {
                    newWidth = monitorsW;
                    newHeight = monitorsH + m.monitorsH;
                }
                Set<AdvancedMonitor> newMonitors = new HashSet<AdvancedMonitor>(monitors);
                newMonitors.addAll(m.monitors);
                for (AdvancedMonitor am : newMonitors) {
                    am.origin = newOrigin;
                    am.monitorsH = newHeight;
                    am.monitorsW = newWidth;
                    am.monitors.addAll(newMonitors);
                }
                return true;
            }
        }
        return false;
    }

    public boolean isOrigin() {
        return origin == this;
    }

    public AdvancedMonitor getOrigin() {
        return origin;
    }

    public int getMonitorsWidth() {
        return monitorsW;
    }

    public int getMonitorsHeigth() {
        return monitorsH;
    }

    @Override
    public void invalidate() {
        super.invalidate();
        monitors.remove(this);
        //wanna make sure to reset all fields before checking again
        for (AdvancedMonitor m : monitors) {
            m.monitorsH = 1;
            m.monitorsW = 1;
            m.monitors.clear();
            m.monitors.add(m);
            m.origin = m;
        }
        for (AdvancedMonitor m : monitors) {
            m.checkMultiblock();
        }
    }
}