Java tutorial
/* * 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(); } } }