/** * Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team * http://www.mod-buildcraft.com * <p/> * BuildCraft is distributed under the terms of the Minecraft Mod Public * License 1.0, or MMPL. Please check the contents of the license located in * http://www.mod-buildcraft.com/MMPL-1.0.txt */ package buildcraft.transport.render; import org.lwjgl.opengl.GL11; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.RenderBlocks; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IIcon; import net.minecraftforge.common.util.ForgeDirection; import buildcraft.BuildCraftCore; import buildcraft.BuildCraftCore.RenderMode; import buildcraft.BuildCraftTransport; import buildcraft.api.core.render.ITextureStates; import buildcraft.api.gates.IGateExpansion; import buildcraft.api.transport.IPipeTile; import buildcraft.api.transport.PipeWire; import buildcraft.api.transport.pluggable.PipePluggable; import buildcraft.core.CoreConstants; import buildcraft.core.lib.render.RenderEntityBlock; import buildcraft.core.lib.render.RenderEntityBlock.RenderInfo; import buildcraft.core.lib.utils.MatrixTranformations; import buildcraft.core.proxy.CoreProxy; import buildcraft.transport.Pipe; import buildcraft.transport.PipeRenderState; import buildcraft.transport.TileGenericPipe; import buildcraft.transport.gates.GatePluggable; public class PipeRendererTESR extends TileEntitySpecialRenderer { public static final PipeRendererTESR INSTANCE = new PipeRendererTESR(); protected PipeRendererTESR() { } public void onTextureReload() { PipeTransportPowerRenderer.clear(); PipeTransportFluidsRenderer.clear(); } @Override public void renderTileEntityAt(TileEntity tileentity, double x, double y, double z, float f) { if (BuildCraftCore.render == RenderMode.NoDynamic) { return; } TileGenericPipe pipe = (TileGenericPipe) tileentity; if (pipe.pipe == null) { return; } renderGatesWires(pipe, x, y, z); renderPluggables(pipe, x, y, z); PipeTransportRenderer renderer = PipeTransportRenderer.RENDERER_MAP.get(pipe.pipe.transport.getClass()); if (renderer != null) { renderer.render(renderer.useServerTileIfPresent() ? (Pipe) (((IPipeTile) CoreProxy.proxy.getServerTile(pipe)).getPipe()) : pipe.pipe, x, y, z, f); } } private void renderGatesWires(TileGenericPipe pipe, double x, double y, double z) { PipeRenderState state = pipe.renderState; if (state.wireMatrix.hasWire(PipeWire.RED)) { pipeWireRender(pipe, CoreConstants.PIPE_MIN_POS, CoreConstants.PIPE_MAX_POS, CoreConstants.PIPE_MIN_POS, PipeWire.RED, x, y, z); } if (state.wireMatrix.hasWire(PipeWire.BLUE)) { pipeWireRender(pipe, CoreConstants.PIPE_MAX_POS, CoreConstants.PIPE_MAX_POS, CoreConstants.PIPE_MAX_POS, PipeWire.BLUE, x, y, z); } if (state.wireMatrix.hasWire(PipeWire.GREEN)) { pipeWireRender(pipe, CoreConstants.PIPE_MAX_POS, CoreConstants.PIPE_MIN_POS, CoreConstants.PIPE_MIN_POS, PipeWire.GREEN, x, y, z); } if (state.wireMatrix.hasWire(PipeWire.YELLOW)) { pipeWireRender(pipe, CoreConstants.PIPE_MIN_POS, CoreConstants.PIPE_MIN_POS, CoreConstants.PIPE_MAX_POS, PipeWire.YELLOW, x, y, z); } } private void pipeWireRender(TileGenericPipe pipe, float cx, float cy, float cz, PipeWire color, double x, double y, double z) { PipeRenderState state = pipe.renderState; float minX = CoreConstants.PIPE_MIN_POS; float minY = CoreConstants.PIPE_MIN_POS; float minZ = CoreConstants.PIPE_MIN_POS; float maxX = CoreConstants.PIPE_MAX_POS; float maxY = CoreConstants.PIPE_MAX_POS; float maxZ = CoreConstants.PIPE_MAX_POS; boolean foundX = false, foundY = false, foundZ = false; if (state.wireMatrix.isWireConnected(color, ForgeDirection.WEST)) { minX = 0; foundX = true; } if (state.wireMatrix.isWireConnected(color, ForgeDirection.EAST)) { maxX = 1; foundX = true; } if (state.wireMatrix.isWireConnected(color, ForgeDirection.DOWN)) { minY = 0; foundY = true; } if (state.wireMatrix.isWireConnected(color, ForgeDirection.UP)) { maxY = 1; foundY = true; } if (state.wireMatrix.isWireConnected(color, ForgeDirection.NORTH)) { minZ = 0; foundZ = true; } if (state.wireMatrix.isWireConnected(color, ForgeDirection.SOUTH)) { maxZ = 1; foundZ = true; } boolean center = false; if (minX == 0 && maxX != 1 && (foundY || foundZ)) { if (cx == CoreConstants.PIPE_MIN_POS) { maxX = CoreConstants.PIPE_MIN_POS; } else { center = true; } } if (minX != 0 && maxX == 1 && (foundY || foundZ)) { if (cx == CoreConstants.PIPE_MAX_POS) { minX = CoreConstants.PIPE_MAX_POS; } else { center = true; } } if (minY == 0 && maxY != 1 && (foundX || foundZ)) { if (cy == CoreConstants.PIPE_MIN_POS) { maxY = CoreConstants.PIPE_MIN_POS; } else { center = true; } } if (minY != 0 && maxY == 1 && (foundX || foundZ)) { if (cy == CoreConstants.PIPE_MAX_POS) { minY = CoreConstants.PIPE_MAX_POS; } else { center = true; } } if (minZ == 0 && maxZ != 1 && (foundX || foundY)) { if (cz == CoreConstants.PIPE_MIN_POS) { maxZ = CoreConstants.PIPE_MIN_POS; } else { center = true; } } if (minZ != 0 && maxZ == 1 && (foundX || foundY)) { if (cz == CoreConstants.PIPE_MAX_POS) { minZ = CoreConstants.PIPE_MAX_POS; } else { center = true; } } boolean found = foundX || foundY || foundZ; GL11.glPushMatrix(); GL11.glColor3f(1, 1, 1); GL11.glTranslatef((float) x, (float) y, (float) z); float scale = 1.001f; GL11.glTranslatef(0.5F, 0.5F, 0.5F); GL11.glScalef(scale, scale, scale); GL11.glTranslatef(-0.5F, -0.5F, -0.5F); bindTexture(TextureMap.locationBlocksTexture); RenderInfo renderBox = new RenderInfo(); renderBox.texture = BuildCraftTransport.instance.wireIconProvider.getIcon(state.wireMatrix.getWireIconIndex(color)); boolean isLit = (state.wireMatrix.getWireIconIndex(color) & 1) > 0; // Z render if (minZ != CoreConstants.PIPE_MIN_POS || maxZ != CoreConstants.PIPE_MAX_POS || !found) { renderBox.setBounds(cx == CoreConstants.PIPE_MIN_POS ? cx - 0.05F : cx, cy == CoreConstants.PIPE_MIN_POS ? cy - 0.05F : cy, minZ, cx == CoreConstants.PIPE_MIN_POS ? cx : cx + 0.05F, cy == CoreConstants.PIPE_MIN_POS ? cy : cy + 0.05F, maxZ); renderLitBox(renderBox, isLit); } // X render if (minX != CoreConstants.PIPE_MIN_POS || maxX != CoreConstants.PIPE_MAX_POS || !found) { renderBox.setBounds(minX, cy == CoreConstants.PIPE_MIN_POS ? cy - 0.05F : cy, cz == CoreConstants.PIPE_MIN_POS ? cz - 0.05F : cz, maxX, cy == CoreConstants.PIPE_MIN_POS ? cy : cy + 0.05F, cz == CoreConstants.PIPE_MIN_POS ? cz : cz + 0.05F); renderLitBox(renderBox, isLit); } // Y render if (minY != CoreConstants.PIPE_MIN_POS || maxY != CoreConstants.PIPE_MAX_POS || !found) { renderBox.setBounds(cx == CoreConstants.PIPE_MIN_POS ? cx - 0.05F : cx, minY, cz == CoreConstants.PIPE_MIN_POS ? cz - 0.05F : cz, cx == CoreConstants.PIPE_MIN_POS ? cx : cx + 0.05F, maxY, cz == CoreConstants.PIPE_MIN_POS ? cz : cz + 0.05F); renderLitBox(renderBox, isLit); } if (center || !found) { renderBox.setBounds(cx == CoreConstants.PIPE_MIN_POS ? cx - 0.05F : cx, cy == CoreConstants.PIPE_MIN_POS ? cy - 0.05F : cy, cz == CoreConstants.PIPE_MIN_POS ? cz - 0.05F : cz, cx == CoreConstants.PIPE_MIN_POS ? cx : cx + 0.05F, cy == CoreConstants.PIPE_MIN_POS ? cy : cy + 0.05F, cz == CoreConstants.PIPE_MIN_POS ? cz : cz + 0.05F); renderLitBox(renderBox, isLit); } GL11.glPopMatrix(); } private void renderPluggables(TileGenericPipe pipe, double x, double y, double z) { TileEntityRendererDispatcher.instance.field_147553_e.bindTexture(TextureMap.locationBlocksTexture); for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) { PipePluggable pluggable = pipe.getPipePluggable(direction); if (pluggable != null && pluggable.getDynamicRenderer() != null) { pluggable.getDynamicRenderer().renderPluggable(pipe.getPipe(), direction, pluggable, x, y, z); } } } public static void renderGateStatic(RenderBlocks renderblocks, ForgeDirection direction, GatePluggable gate, ITextureStates blockStateMachine, int x, int y, int z) { blockStateMachine.getTextureState().set(gate.getLogic().getGateIcon()); float trim = 0.1F; float[][] zeroState = new float[3][2]; float min = CoreConstants.PIPE_MIN_POS + trim / 2F; float max = CoreConstants.PIPE_MAX_POS - trim / 2F; // X START - END zeroState[0][0] = min; zeroState[0][1] = max; // Y START - END zeroState[1][0] = CoreConstants.PIPE_MIN_POS - 0.10F; zeroState[1][1] = CoreConstants.PIPE_MIN_POS + 0.001F; // Z START - END zeroState[2][0] = min; zeroState[2][1] = max; float[][] rotated = MatrixTranformations.deepClone(zeroState); MatrixTranformations.transform(rotated, direction); blockStateMachine.setRenderAllSides(); renderblocks.setRenderBounds(rotated[0][0], rotated[1][0], rotated[2][0], rotated[0][1], rotated[1][1], rotated[2][1]); renderblocks.renderStandardBlock(blockStateMachine.getBlock(), x, y, z); } public static void renderGate(double x, double y, double z, GatePluggable gate, ForgeDirection direction) { GL11.glPushMatrix(); GL11.glColor3f(1, 1, 1); GL11.glTranslatef((float) x, (float) y, (float) z); IIcon lightIcon; if (gate.isLit) { lightIcon = gate.getLogic().getIconLit(); } else { lightIcon = gate.getLogic().getIconDark(); } float translateCenter = 0; renderGate(lightIcon, 0, 0.1F, 0, 0, direction, gate.isLit, 1); float pulseStage = gate.getPulseStage() * 2F; if (gate.isPulsing || pulseStage != 0) { IIcon gateIcon = gate.getLogic().getGateIcon(); // Render pulsing gate float amplitude = 0.10F; float start = 0.01F; if (pulseStage < 1) { translateCenter = (pulseStage * amplitude) + start; } else { translateCenter = amplitude - ((pulseStage - 1F) * amplitude) + start; } renderGate(gateIcon, 0, 0.13F, translateCenter, translateCenter, direction, false, 2); renderGate(lightIcon, 0, 0.13F, translateCenter, translateCenter, direction, gate.isLit, 0); } IIcon materialIcon = gate.getMaterial().getIconBlock(); if (materialIcon != null) { renderGate(materialIcon, 1, 0.13F, translateCenter, translateCenter, direction, false, 1); } for (IGateExpansion expansion : gate.getExpansions()) { renderGate(expansion.getOverlayBlock(), 2, 0.13F, translateCenter, translateCenter, direction, false, 0); } GL11.glPopMatrix(); } private static void renderGate(IIcon icon, int layer, float trim, float translateCenter, float extraDepth, ForgeDirection direction, boolean isLit, int sideRenderingMode) { RenderInfo renderBox = new RenderInfo(); renderBox.texture = icon; float[][] zeroState = new float[3][2]; float min = CoreConstants.PIPE_MIN_POS + trim / 2F; float max = CoreConstants.PIPE_MAX_POS - trim / 2F; // X START - END zeroState[0][0] = min; zeroState[0][1] = max; // Y START - END zeroState[1][0] = CoreConstants.PIPE_MIN_POS - 0.10F - 0.001F * layer; zeroState[1][1] = CoreConstants.PIPE_MIN_POS + 0.001F + 0.01F * layer + extraDepth; // Z START - END zeroState[2][0] = min; zeroState[2][1] = max; if (translateCenter != 0) { GL11.glPushMatrix(); float xt = direction.offsetX * translateCenter, yt = direction.offsetY * translateCenter, zt = direction.offsetZ * translateCenter; GL11.glTranslatef(xt, yt, zt); } float[][] rotated = MatrixTranformations.deepClone(zeroState); MatrixTranformations.transform(rotated, direction); switch (sideRenderingMode) { case 0: renderBox.setRenderSingleSide(direction.ordinal()); break; case 1: renderBox.setRenderSingleSide(direction.ordinal()); renderBox.renderSide[direction.ordinal() ^ 1] = true; break; case 2: break; } renderBox.setBounds(rotated[0][0], rotated[1][0], rotated[2][0], rotated[0][1], rotated[1][1], rotated[2][1]); renderLitBox(renderBox, isLit); if (translateCenter != 0) { GL11.glPopMatrix(); } } private static void renderLitBox(RenderInfo info, boolean isLit) { RenderEntityBlock.INSTANCE.renderBlock(info); float lastX = OpenGlHelper.lastBrightnessX; float lastY = OpenGlHelper.lastBrightnessY; if (isLit) { GL11.glPushMatrix(); GL11.glEnable(GL11.GL_BLEND); GL11.glDisable(GL11.GL_LIGHTING); GL11.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE); GL11.glDepthMask(true); OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 61680, 0); RenderEntityBlock.INSTANCE.renderBlock(info); GL11.glDisable(GL11.GL_BLEND); GL11.glEnable(GL11.GL_LIGHTING); GL11.glPopMatrix(); } OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, lastX, lastY); } public boolean isOpenOrientation(PipeRenderState state, ForgeDirection direction) { int connections = 0; ForgeDirection targetOrientation = ForgeDirection.UNKNOWN; for (ForgeDirection o : ForgeDirection.VALID_DIRECTIONS) { if (state.pipeConnectionMatrix.isConnected(o)) { connections++; if (connections == 1) { targetOrientation = o; } } } if (connections > 1 || connections == 0) { return false; } return targetOrientation.getOpposite() == direction; } }