From b05f9e268a4b318f1af10cddc2dab7ee507dcef0 Mon Sep 17 00:00:00 2001
From: Léa Gris <lea.gris@noiraude.net>
Date: Tue, 16 Feb 2021 17:30:31 +0100
Subject: feat(render): tile ambient occlusion

Render smooth lighting ambient occlusion on all Gregtech tiles:
- Ores
- Machines
- Pipes, Cables, Wires, Frames

Add new Client-side configuration entry in Gregtech.cfg.
If false, the flat lighting rendering of older versions is used.

```yml
render {
    B:TileAmbientOcclusion_true=true
}
```
---
 .../java/gregtech/api/util/LightingHelper.java     | 718 +++++++++++++++++++++
 1 file changed, 718 insertions(+)
 create mode 100644 src/main/java/gregtech/api/util/LightingHelper.java

(limited to 'src/main/java/gregtech/api/util/LightingHelper.java')

diff --git a/src/main/java/gregtech/api/util/LightingHelper.java b/src/main/java/gregtech/api/util/LightingHelper.java
new file mode 100644
index 0000000000..3696d88fec
--- /dev/null
+++ b/src/main/java/gregtech/api/util/LightingHelper.java
@@ -0,0 +1,718 @@
+/*
+ * LightingHelper - Derived and adapted from @Mineshopper / carpentersblocks
+ * Copyright (c) 2013-2021.
+ *
+ * This library 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 version 2.1
+ * of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+package gregtech.api.util;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import net.minecraft.block.Block;
+import net.minecraft.client.renderer.EntityRenderer;
+import net.minecraft.client.renderer.RenderBlocks;
+import net.minecraft.client.renderer.Tessellator;
+
+@SuppressWarnings("unused")
+@SideOnly(Side.CLIENT)
+public class LightingHelper {
+    public static final int NORMAL_BRIGHTNESS = 0xff00ff;
+    public static final int MAX_BRIGHTNESS = 0xf000f0;
+    protected static final float[] LIGHTNESS = {0.5F, 1.0F, 0.8F, 0.8F, 0.6F, 0.6F};
+    private final RenderBlocks renderBlocks;
+    /**
+     * Brightness for side.
+     */
+    private int brightness;
+    /**
+     * Ambient occlusion values for all four corners of side.
+     */
+    private float aoTopLeft, aoBottomLeft, aoBottomRight, aoTopRight;
+    private boolean hasLightnessOverride;
+    private float lightnessOverride;
+    private boolean hasBrightnessOverride;
+    private int brightnessOverride;
+    private boolean hasColorOverride;
+    private int colorOverride = 0xffffff;
+
+    /**
+     * Class constructor specifying the {@link RenderBlocks}.
+     *
+     * @param renderBlocks the {@link RenderBlocks}
+     */
+    public LightingHelper(RenderBlocks renderBlocks) {
+        this.renderBlocks = renderBlocks;
+    }
+
+    /**
+     * Gets average brightness from two brightness values.
+     *
+     * @param brightnessA the first brightness value
+     * @param brightnessB the second brightness value
+     * @return the mixed brightness
+     */
+    public static int getAverageBrightness(int brightnessA, int brightnessB) {
+        int sectionA1 = brightnessA >> 16 & 0xff;
+        int sectionA2 = brightnessA & 255;
+
+        int sectionB1 = brightnessB >> 16 & 0xff;
+        int sectionB2 = brightnessB & 255;
+
+        int difference1 = (int) ((sectionA1 + sectionB1) / 2.0F);
+        int difference2 = (int) ((sectionA2 + sectionB2) / 2.0F);
+
+        return difference1 << 16 | difference2;
+    }
+
+    /**
+     * Gets rgb color from RGBA array.
+     *
+     * @param color the integer color
+     * @return a float array with rgb values
+     */
+    public static float[] getRGB(short[] color) {
+        float red = color[0] / 255.0F;
+        float green = color[1] / 255.0F;
+        float blue = color[2] / 255.0F;
+
+        return new float[]{red, green, blue};
+    }
+
+    /**
+     * Clears brightness override.
+     */
+    public void clearBrightnessOverride() {
+        hasBrightnessOverride = false;
+    }
+
+    /**
+     * Clears color override.
+     */
+    public void clearColorOverride() {
+        hasColorOverride = false;
+    }
+
+    /**
+     * Clears lightness override.
+     */
+    public void clearLightnessOverride() {
+        hasLightnessOverride = false;
+    }
+
+    /**
+     * @return the Ambient Occlusion for Bottom-Left corner
+     */
+    public float getAoBottomLeft() {
+        return aoBottomLeft;
+    }
+
+    /**
+     * @return the Ambient Occlusion for Bottom-Right corner
+     */
+    public float getAoBottomRight() {
+        return aoBottomRight;
+    }
+
+    /**
+     * @return the Ambient Occlusion for Top-Left corner
+     */
+    public float getAoTopLeft() {
+        return aoTopLeft;
+    }
+
+    /**
+     * @return the Ambient Occlusion for Top-Right corner
+     */
+    public float getAoTopRight() {
+        return aoTopRight;
+    }
+
+    /**
+     * Sets brightness override.
+     *
+     * @param brightness the brightness override
+     * @return the {@link LightingHelper}
+     */
+    public LightingHelper setBrightnessOverride(int brightness) {
+        hasBrightnessOverride = true;
+        brightnessOverride = brightness;
+        return this;
+    }
+
+    public LightingHelper setColorOverride(short[] color) {
+        return setColorOverride(getColor(color));
+    }
+
+    /**
+     * Sets color override.
+     *
+     * @param color the color override
+     * @return the {@link LightingHelper}
+     */
+    public LightingHelper setColorOverride(int color) {
+        hasColorOverride = true;
+        colorOverride = color;
+        return this;
+    }
+
+    /**
+     * Gets int color from RGBA array.
+     *
+     * @param rgba the short RGBA color array
+     * @return int color
+     */
+    public static int getColor(short[] rgba) {
+        return (rgba[2] & 0xff) | (rgba[1] & 0xff) << 8 | (rgba[0] & 0xff) << 16;
+    }
+
+    /**
+     * Sets lightness override.
+     *
+     * @param lightness the lightness override
+     * @return the {@link LightingHelper}
+     */
+    public LightingHelper setLightnessOverride(float lightness) {
+        hasLightnessOverride = true;
+        lightnessOverride = lightness;
+        return this;
+    }
+
+    /**
+     * Sets up the color using lightness, brightness, and the primary color
+     * value (usually the dye color) for the side.
+     *
+     * @param side the side
+     * @param rgba the primary short[] RGBA color array
+     */
+    public void setupColor(int side, short[] rgba) {
+        setupColor(side, getColor(rgba));
+    }
+
+    /**
+     * Sets up the color using lightness, brightness, and the primary color
+     * value (usually the dye color) for the side.
+     *
+     * @param side     the side
+     * @param hexColor the primary color
+     */
+    public void setupColor(int side, int hexColor) {
+        Tessellator tessellator = Tessellator.instance;
+        float lightness = hasLightnessOverride ? lightnessOverride : LIGHTNESS[side];
+        float[] rgb = getRGB(hexColor);
+
+        if (hasColorOverride && !renderBlocks.hasOverrideBlockTexture()) {
+            rgb = getRGB(colorOverride);
+        }
+
+        applyAnaglyph(rgb);
+
+        if (renderBlocks.enableAO) {
+            tessellator.setBrightness(hasBrightnessOverride ? brightnessOverride : brightness);
+
+            if (renderBlocks.hasOverrideBlockTexture()) {
+
+                renderBlocks.colorRedTopLeft = renderBlocks.colorRedBottomLeft = renderBlocks.colorRedBottomRight = renderBlocks.colorRedTopRight = rgb[0];
+                renderBlocks.colorGreenTopLeft = renderBlocks.colorGreenBottomLeft = renderBlocks.colorGreenBottomRight = renderBlocks.colorGreenTopRight = rgb[1];
+                renderBlocks.colorBlueTopLeft = renderBlocks.colorBlueBottomLeft = renderBlocks.colorBlueBottomRight = renderBlocks.colorBlueTopRight = rgb[2];
+
+            } else {
+
+                renderBlocks.colorRedTopLeft = renderBlocks.colorRedBottomLeft = renderBlocks.colorRedBottomRight = renderBlocks.colorRedTopRight = rgb[0] * lightness;
+                renderBlocks.colorGreenTopLeft = renderBlocks.colorGreenBottomLeft = renderBlocks.colorGreenBottomRight = renderBlocks.colorGreenTopRight = rgb[1] * lightness;
+                renderBlocks.colorBlueTopLeft = renderBlocks.colorBlueBottomLeft = renderBlocks.colorBlueBottomRight = renderBlocks.colorBlueTopRight = rgb[2] * lightness;
+
+                renderBlocks.colorRedTopLeft *= aoTopLeft;
+                renderBlocks.colorGreenTopLeft *= aoTopLeft;
+                renderBlocks.colorBlueTopLeft *= aoTopLeft;
+                renderBlocks.colorRedBottomLeft *= aoBottomLeft;
+                renderBlocks.colorGreenBottomLeft *= aoBottomLeft;
+                renderBlocks.colorBlueBottomLeft *= aoBottomLeft;
+                renderBlocks.colorRedBottomRight *= aoBottomRight;
+                renderBlocks.colorGreenBottomRight *= aoBottomRight;
+                renderBlocks.colorBlueBottomRight *= aoBottomRight;
+                renderBlocks.colorRedTopRight *= aoTopRight;
+                renderBlocks.colorGreenTopRight *= aoTopRight;
+                renderBlocks.colorBlueTopRight *= aoTopRight;
+            }
+
+        } else {
+
+            tessellator.setColorOpaque_F(rgb[0] * lightness, rgb[1] * lightness, rgb[2] * lightness);
+
+        }
+    }
+
+    /**
+     * Gets rgb color from integer.
+     *
+     * @param color the integer color
+     * @return a float array with rgb values
+     */
+    public static float[] getRGB(int color) {
+        float red = (color >> 16 & 0xff) / 255.0F;
+        float green = (color >> 8 & 0xff) / 255.0F;
+        float blue = (color & 0xff) / 255.0F;
+
+        return new float[]{red, green, blue};
+    }
+
+    /**
+     * Will apply anaglyph color multipliers to RGB float array.
+     * <p>
+     * If {@link EntityRenderer#anaglyphEnable} is false,
+     * will do nothing.
+     *
+     * @param rgb array containing red, green and blue float values
+     */
+    public void applyAnaglyph(float[] rgb) {
+        if (EntityRenderer.anaglyphEnable) {
+            rgb[0] = (rgb[0] * 30.0F + rgb[1] * 59.0F + rgb[2] * 11.0F) / 100.0F;
+            rgb[1] = (rgb[0] * 30.0F + rgb[1] * 70.0F) / 100.0F;
+            rgb[2] = (rgb[0] * 30.0F + rgb[2] * 70.0F) / 100.0F;
+        }
+    }
+
+    /**
+     * Sets up lighting for the West face and returns the {@link LightingHelper}.
+     * <p>
+     * This is a consolidated <code>method</code> that sets side shading
+     * with respect to the following attributes:
+     * <p>
+     * <ul>
+     *   <li>{@link RenderBlocks#enableAO}</li>
+     *   <li>{@link RenderBlocks#partialRenderBounds}</li>
+     * </ul>
+     *
+     * @param block the block {@link Block}
+     * @param x     the x coordinate
+     * @param y     the y coordinate
+     * @param z     the z coordinate
+     * @return the {@link LightingHelper}
+     */
+    public LightingHelper setupLightingXNeg(Block block, int x, int y, int z) {
+        int xOffset = renderBlocks.renderMinX > 0.0F ? x : x - 1;
+
+        if (renderBlocks.enableAO) {
+
+            int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y, z);
+            brightness = mixedBrightness;
+
+            float ratio = (float) (1.0F - renderBlocks.renderMinX);
+            float aoLightValue = renderBlocks.blockAccess.getBlock(xOffset, y, z).getAmbientOcclusionLightValue();
+
+            renderBlocks.aoBrightnessXYNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y - 1, z);
+            renderBlocks.aoBrightnessXZNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y, z - 1);
+            renderBlocks.aoBrightnessXZNP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y, z + 1);
+            renderBlocks.aoBrightnessXYNP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y + 1, z);
+            renderBlocks.aoBrightnessXYZNNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y - 1, z - 1);
+            renderBlocks.aoBrightnessXYZNNP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y - 1, z + 1);
+            renderBlocks.aoBrightnessXYZNPN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y + 1, z - 1);
+            renderBlocks.aoBrightnessXYZNPP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y + 1, z + 1);
+            renderBlocks.aoLightValueScratchXYNN = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y - 1, z).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y - 1, z).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXZNN = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y, z - 1).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXZNP = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y, z + 1).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXYNP = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y + 1, z).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y + 1, z).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXYZNNN = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y - 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y - 1, z - 1).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXYZNNP = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y - 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y - 1, z + 1).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXYZNPN = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y + 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y + 1, z - 1).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXYZNPP = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y + 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y + 1, z + 1).getAmbientOcclusionLightValue(), ratio);
+
+            int brightnessMixedXYZNPN = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXZNN, renderBlocks.aoBrightnessXYZNPN, renderBlocks.aoBrightnessXYNP, mixedBrightness);
+            int brightnessMixedXYZNNN = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXYZNNN, renderBlocks.aoBrightnessXYNN, renderBlocks.aoBrightnessXZNN, mixedBrightness);
+            int brightnessMixedXYZNNP = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXYNN, renderBlocks.aoBrightnessXYZNNP, renderBlocks.aoBrightnessXZNP, mixedBrightness);
+            int brightnessMixedXYZNPP = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXZNP, renderBlocks.aoBrightnessXYNP, renderBlocks.aoBrightnessXYZNPP, mixedBrightness);
+
+            float aoMixedXYZNPN = (renderBlocks.aoLightValueScratchXZNN + aoLightValue + renderBlocks.aoLightValueScratchXYZNPN + renderBlocks.aoLightValueScratchXYNP) / 4.0F;
+            float aoMixedXYZNNN = (renderBlocks.aoLightValueScratchXYZNNN + renderBlocks.aoLightValueScratchXYNN + renderBlocks.aoLightValueScratchXZNN + aoLightValue) / 4.0F;
+            float aoMixedXYZNNP = (renderBlocks.aoLightValueScratchXYNN + renderBlocks.aoLightValueScratchXYZNNP + aoLightValue + renderBlocks.aoLightValueScratchXZNP) / 4.0F;
+            float aoMixedXYZNPP = (aoLightValue + renderBlocks.aoLightValueScratchXZNP + renderBlocks.aoLightValueScratchXYNP + renderBlocks.aoLightValueScratchXYZNPP) / 4.0F;
+
+            aoTopLeft = (float) (aoMixedXYZNPP * renderBlocks.renderMaxY * renderBlocks.renderMaxZ + aoMixedXYZNPN * renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMaxZ) + aoMixedXYZNNN * (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMaxZ) + aoMixedXYZNNP * (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMaxZ);
+            aoBottomLeft = (float) (aoMixedXYZNPP * renderBlocks.renderMaxY * renderBlocks.renderMinZ + aoMixedXYZNPN * renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMinZ) + aoMixedXYZNNN * (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMinZ) + aoMixedXYZNNP * (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMinZ);
+            aoBottomRight = (float) (aoMixedXYZNPP * renderBlocks.renderMinY * renderBlocks.renderMinZ + aoMixedXYZNPN * renderBlocks.renderMinY * (1.0D - renderBlocks.renderMinZ) + aoMixedXYZNNN * (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMinZ) + aoMixedXYZNNP * (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMinZ);
+            aoTopRight = (float) (aoMixedXYZNPP * renderBlocks.renderMinY * renderBlocks.renderMaxZ + aoMixedXYZNPN * renderBlocks.renderMinY * (1.0D - renderBlocks.renderMaxZ) + aoMixedXYZNNN * (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMaxZ) + aoMixedXYZNNP * (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMaxZ);
+
+            renderBlocks.brightnessTopLeft = renderBlocks.mixAoBrightness(brightnessMixedXYZNPP, brightnessMixedXYZNPN, brightnessMixedXYZNNN, brightnessMixedXYZNNP, renderBlocks.renderMaxY * renderBlocks.renderMaxZ, renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMaxZ), (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMaxZ), (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMaxZ);
+            renderBlocks.brightnessBottomLeft = renderBlocks.mixAoBrightness(brightnessMixedXYZNPP, brightnessMixedXYZNPN, brightnessMixedXYZNNN, brightnessMixedXYZNNP, renderBlocks.renderMaxY * renderBlocks.renderMinZ, renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMinZ), (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMinZ), (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMinZ);
+            renderBlocks.brightnessBottomRight = renderBlocks.mixAoBrightness(brightnessMixedXYZNPP, brightnessMixedXYZNPN, brightnessMixedXYZNNN, brightnessMixedXYZNNP, renderBlocks.renderMinY * renderBlocks.renderMinZ, renderBlocks.renderMinY * (1.0D - renderBlocks.renderMinZ), (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMinZ), (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMinZ);
+            renderBlocks.brightnessTopRight = renderBlocks.mixAoBrightness(brightnessMixedXYZNPP, brightnessMixedXYZNPN, brightnessMixedXYZNNN, brightnessMixedXYZNNP, renderBlocks.renderMinY * renderBlocks.renderMaxZ, renderBlocks.renderMinY * (1.0D - renderBlocks.renderMaxZ), (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMaxZ), (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMaxZ);
+
+        }
+
+        return this;
+    }
+
+    /**
+     * Gets mixed ambient occlusion value from two inputs, with a
+     * ratio applied to the final result.
+     *
+     * @param ao1   the first ambient occlusion value
+     * @param ao2   the second ambient occlusion value
+     * @param ratio the ratio for mixing
+     * @return the mixed red, green, blue float values
+     */
+    public static float getMixedAo(float ao1, float ao2, double ratio) {
+        float diff = (float) (Math.abs(ao1 - ao2) * (1.0F - ratio));
+
+        return ao1 > ao2 ? ao1 - diff : ao1 + diff;
+    }
+
+    /**
+     * Sets up lighting for the East face and returns the {@link LightingHelper}.
+     * <p>
+     * This is a consolidated <code>method</code> that sets side shading
+     * with respect to the following attributes:
+     * <p>
+     * <ul>
+     *   <li>{@link RenderBlocks#enableAO}</li>
+     *   <li>{@link RenderBlocks#partialRenderBounds}</li>
+     * </ul>
+     *
+     * @param block the block {@link Block}
+     * @param x     the x coordinate
+     * @param y     the y coordinate
+     * @param z     the z coordinate
+     * @return the {@link LightingHelper}
+     */
+    public LightingHelper setupLightingXPos(Block block, int x, int y, int z) {
+        int xOffset = renderBlocks.renderMaxX < 1.0F ? x : x + 1;
+
+        if (renderBlocks.enableAO) {
+
+            int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y, z);
+            brightness = mixedBrightness;
+
+            float aoLightValue = renderBlocks.blockAccess.getBlock(xOffset, y, z).getAmbientOcclusionLightValue();
+
+            renderBlocks.aoBrightnessXYPN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y - 1, z);
+            renderBlocks.aoBrightnessXZPN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y, z - 1);
+            renderBlocks.aoBrightnessXZPP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y, z + 1);
+            renderBlocks.aoBrightnessXYPP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y + 1, z);
+            renderBlocks.aoBrightnessXYZPNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y - 1, z - 1);
+            renderBlocks.aoBrightnessXYZPNP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y - 1, z + 1);
+            renderBlocks.aoBrightnessXYZPPN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y + 1, z - 1);
+            renderBlocks.aoBrightnessXYZPPP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y + 1, z + 1);
+            renderBlocks.aoLightValueScratchXYPN = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y - 1, z).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y - 1, z).getAmbientOcclusionLightValue(), renderBlocks.renderMaxX);
+            renderBlocks.aoLightValueScratchXZPN = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y, z - 1).getAmbientOcclusionLightValue(), renderBlocks.renderMaxX);
+            renderBlocks.aoLightValueScratchXZPP = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y, z + 1).getAmbientOcclusionLightValue(), renderBlocks.renderMaxX);
+            renderBlocks.aoLightValueScratchXYPP = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y + 1, z).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y + 1, z).getAmbientOcclusionLightValue(), renderBlocks.renderMaxX);
+            renderBlocks.aoLightValueScratchXYZPNN = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y - 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y - 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.renderMaxX);
+            renderBlocks.aoLightValueScratchXYZPNP = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y - 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y - 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.renderMaxX);
+            renderBlocks.aoLightValueScratchXYZPPN = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y + 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y + 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.renderMaxX);
+            renderBlocks.aoLightValueScratchXYZPPP = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y + 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y + 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.renderMaxX);
+
+            int brightnessMixedXYZPPP = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXZPP, renderBlocks.aoBrightnessXYPP, renderBlocks.aoBrightnessXYZPPP, mixedBrightness);
+            int brightnessMixedXYZPNP = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXYPN, renderBlocks.aoBrightnessXYZPNP, renderBlocks.aoBrightnessXZPP, mixedBrightness);
+            int brightnessMixedXYZPNN = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXYZPNN, renderBlocks.aoBrightnessXYPN, renderBlocks.aoBrightnessXZPN, mixedBrightness);
+            int brightnessMixedXYZPPN = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXZPN, renderBlocks.aoBrightnessXYZPPN, renderBlocks.aoBrightnessXYPP, mixedBrightness);
+
+            float aoMixedXYZPPP = (aoLightValue + renderBlocks.aoLightValueScratchXZPP + renderBlocks.aoLightValueScratchXYPP + renderBlocks.aoLightValueScratchXYZPPP) / 4.0F;
+            float aoMixedXYZPNP = (renderBlocks.aoLightValueScratchXYPN + renderBlocks.aoLightValueScratchXYZPNP + aoLightValue + renderBlocks.aoLightValueScratchXZPP) / 4.0F;
+            float aoMixedXYZPNN = (renderBlocks.aoLightValueScratchXYZPNN + renderBlocks.aoLightValueScratchXYPN + renderBlocks.aoLightValueScratchXZPN + aoLightValue) / 4.0F;
+            float aoMixedXYZPPN = (renderBlocks.aoLightValueScratchXZPN + aoLightValue + renderBlocks.aoLightValueScratchXYZPPN + renderBlocks.aoLightValueScratchXYPP) / 4.0F;
+
+            aoTopLeft = (float) (aoMixedXYZPNP * (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMaxZ + aoMixedXYZPNN * (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMaxZ) + aoMixedXYZPPN * renderBlocks.renderMinY * (1.0D - renderBlocks.renderMaxZ) + aoMixedXYZPPP * renderBlocks.renderMinY * renderBlocks.renderMaxZ);
+            aoBottomLeft = (float) (aoMixedXYZPNP * (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMinZ + aoMixedXYZPNN * (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMinZ) + aoMixedXYZPPN * renderBlocks.renderMinY * (1.0D - renderBlocks.renderMinZ) + aoMixedXYZPPP * renderBlocks.renderMinY * renderBlocks.renderMinZ);
+            aoBottomRight = (float) (aoMixedXYZPNP * (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMinZ + aoMixedXYZPNN * (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMinZ) + aoMixedXYZPPN * renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMinZ) + aoMixedXYZPPP * renderBlocks.renderMaxY * renderBlocks.renderMinZ);
+            aoTopRight = (float) (aoMixedXYZPNP * (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMaxZ + aoMixedXYZPNN * (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMaxZ) + aoMixedXYZPPN * renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMaxZ) + aoMixedXYZPPP * renderBlocks.renderMaxY * renderBlocks.renderMaxZ);
+
+            renderBlocks.brightnessTopLeft = renderBlocks.mixAoBrightness(brightnessMixedXYZPNP, brightnessMixedXYZPNN, brightnessMixedXYZPPN, brightnessMixedXYZPPP, (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMaxZ, (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMaxZ), renderBlocks.renderMinY * (1.0D - renderBlocks.renderMaxZ), renderBlocks.renderMinY * renderBlocks.renderMaxZ);
+            renderBlocks.brightnessBottomLeft = renderBlocks.mixAoBrightness(brightnessMixedXYZPNP, brightnessMixedXYZPNN, brightnessMixedXYZPPN, brightnessMixedXYZPPP, (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMinZ, (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMinZ), renderBlocks.renderMinY * (1.0D - renderBlocks.renderMinZ), renderBlocks.renderMinY * renderBlocks.renderMinZ);
+            renderBlocks.brightnessBottomRight = renderBlocks.mixAoBrightness(brightnessMixedXYZPNP, brightnessMixedXYZPNN, brightnessMixedXYZPPN, brightnessMixedXYZPPP, (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMinZ, (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMinZ), renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMinZ), renderBlocks.renderMaxY * renderBlocks.renderMinZ);
+            renderBlocks.brightnessTopRight = renderBlocks.mixAoBrightness(brightnessMixedXYZPNP, brightnessMixedXYZPNN, brightnessMixedXYZPPN, brightnessMixedXYZPPP, (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMaxZ, (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMaxZ), renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMaxZ), renderBlocks.renderMaxY * renderBlocks.renderMaxZ);
+
+        }
+
+        return this;
+    }
+
+    /**
+     * Sets up lighting for the bottom face and returns the {@link LightingHelper}.
+     * <p>
+     * This is a consolidated <code>method</code> that sets side shading
+     * with respect to the following attributes:
+     * <p>
+     * <ul>
+     *   <li>{@link RenderBlocks#enableAO}</li>
+     *   <li>{@link RenderBlocks#partialRenderBounds}</li>
+     * </ul>
+     *
+     * @param block the block {@link Block}
+     * @param x     the x coordinate
+     * @param y     the y coordinate
+     * @param z     the z coordinate
+     * @return the {@link LightingHelper}
+     */
+    public LightingHelper setupLightingYNeg(Block block, int x, int y, int z) {
+
+        int yOffset = renderBlocks.renderMinY > 0.0F ? y : y - 1;
+
+        if (renderBlocks.enableAO) {
+
+            int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, yOffset, z);
+            brightness = mixedBrightness;
+
+            float ratio = (float) (1.0F - renderBlocks.renderMinY);
+            float aoLightValue = renderBlocks.blockAccess.getBlock(x, yOffset, z).getAmbientOcclusionLightValue();
+
+            renderBlocks.aoBrightnessXYNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, yOffset, z);
+            renderBlocks.aoBrightnessYZNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, yOffset, z - 1);
+            renderBlocks.aoBrightnessYZNP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, yOffset, z + 1);
+            renderBlocks.aoBrightnessXYPN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x + 1, yOffset, z);
+            renderBlocks.aoBrightnessXYZNNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, yOffset, z - 1);
+            renderBlocks.aoBrightnessXYZNNP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, yOffset, z + 1);
+            renderBlocks.aoBrightnessXYZPNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x + 1, yOffset, z - 1);
+            renderBlocks.aoBrightnessXYZPNP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x + 1, yOffset, z + 1);
+            renderBlocks.aoLightValueScratchXYNN = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y - 1, z).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x - 1, y, z).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchYZNN = getMixedAo(renderBlocks.blockAccess.getBlock(x, y - 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y, z - 1).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchYZNP = getMixedAo(renderBlocks.blockAccess.getBlock(x, y - 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y, z + 1).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXYPN = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y - 1, z).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x + 1, y, z).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXYZNNN = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y - 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x - 1, y, z - 1).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXYZNNP = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y - 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x - 1, y, z + 1).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXYZPNN = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y - 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x + 1, y, z - 1).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXYZPNP = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y - 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x + 1, y, z + 1).getAmbientOcclusionLightValue(), ratio);
+
+            int brightnessMixedXYZPNP = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessYZNP, renderBlocks.aoBrightnessXYZPNP, renderBlocks.aoBrightnessXYPN, mixedBrightness);
+            int brightnessMixedXYZPNN = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessYZNN, renderBlocks.aoBrightnessXYPN, renderBlocks.aoBrightnessXYZPNN, mixedBrightness);
+            int brightnessMixedXYZNNN = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXYNN, renderBlocks.aoBrightnessXYZNNN, renderBlocks.aoBrightnessYZNN, mixedBrightness);
+            int brightnessMixedXYZNNP = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXYZNNP, renderBlocks.aoBrightnessXYNN, renderBlocks.aoBrightnessYZNP, mixedBrightness);
+
+            float aoMixedXYZPNP = (renderBlocks.aoLightValueScratchYZNP + aoLightValue + renderBlocks.aoLightValueScratchXYZPNP + renderBlocks.aoLightValueScratchXYPN) / 4.0F;
+            float aoMixedXYZPNN = (aoLightValue + renderBlocks.aoLightValueScratchYZNN + renderBlocks.aoLightValueScratchXYPN + renderBlocks.aoLightValueScratchXYZPNN) / 4.0F;
+            float aoMixedXYZNNN = (renderBlocks.aoLightValueScratchXYNN + renderBlocks.aoLightValueScratchXYZNNN + aoLightValue + renderBlocks.aoLightValueScratchYZNN) / 4.0F;
+            float aoMixedXYZNNP = (renderBlocks.aoLightValueScratchXYZNNP + renderBlocks.aoLightValueScratchXYNN + renderBlocks.aoLightValueScratchYZNP + aoLightValue) / 4.0F;
+
+            aoTopLeft  = (float) (aoMixedXYZNNP * renderBlocks.renderMaxZ * (1.0D - renderBlocks.renderMinX) + aoMixedXYZPNP * renderBlocks.renderMaxZ * renderBlocks.renderMinX + aoMixedXYZPNN * (1.0D - renderBlocks.renderMaxZ) * renderBlocks.renderMinX + aoMixedXYZNNN * (1.0D - renderBlocks.renderMaxZ) * (1.0D - renderBlocks.renderMinX));
+            aoBottomLeft = (float) (aoMixedXYZNNP * renderBlocks.renderMinZ * (1.0D - renderBlocks.renderMinX) + aoMixedXYZPNP * renderBlocks.renderMinZ * renderBlocks.renderMinX + aoMixedXYZPNN * (1.0D - renderBlocks.renderMinZ) * renderBlocks.renderMinX + aoMixedXYZNNN * (1.0D - renderBlocks.renderMinZ) * (1.0D - renderBlocks.renderMinX));
+            aoBottomRight = (float) (aoMixedXYZNNP * renderBlocks.renderMinZ * (1.0D - renderBlocks.renderMaxX) + aoMixedXYZPNP * renderBlocks.renderMinZ * renderBlocks.renderMaxX + aoMixedXYZPNN * (1.0D - renderBlocks.renderMinZ) * renderBlocks.renderMaxX + aoMixedXYZNNN * (1.0D - renderBlocks.renderMinZ) * (1.0D - renderBlocks.renderMaxX));
+            aoTopRight = (float) (aoMixedXYZNNP * renderBlocks.renderMaxZ * (1.0D - renderBlocks.renderMaxX) + aoMixedXYZPNP * renderBlocks.renderMaxZ * renderBlocks.renderMaxX + aoMixedXYZPNN * (1.0D - renderBlocks.renderMaxZ) * renderBlocks.renderMaxX + aoMixedXYZNNN * (1.0D - renderBlocks.renderMaxZ) * (1.0D - renderBlocks.renderMaxX));
+
+            renderBlocks.brightnessTopLeft = renderBlocks.mixAoBrightness(brightnessMixedXYZNNP, brightnessMixedXYZPNP, brightnessMixedXYZPNN, brightnessMixedXYZNNN, renderBlocks.renderMaxZ * (1.0D - renderBlocks.renderMinX), renderBlocks.renderMaxZ * renderBlocks.renderMinX, (1.0D - renderBlocks.renderMaxZ) * renderBlocks.renderMinX, (1.0D - renderBlocks.renderMaxZ) * (1.0D - renderBlocks.renderMinX));
+            renderBlocks.brightnessBottomLeft = renderBlocks.mixAoBrightness(brightnessMixedXYZNNP, brightnessMixedXYZPNP, brightnessMixedXYZPNN, brightnessMixedXYZNNN, renderBlocks.renderMinZ * (1.0D - renderBlocks.renderMinX), renderBlocks.renderMinZ * renderBlocks.renderMinX, (1.0D - renderBlocks.renderMinZ) * renderBlocks.renderMinX, (1.0D - renderBlocks.renderMinZ) * (1.0D - renderBlocks.renderMinX));
+            renderBlocks.brightnessBottomRight = renderBlocks.mixAoBrightness(brightnessMixedXYZNNP, brightnessMixedXYZPNP, brightnessMixedXYZPNN, brightnessMixedXYZNNN, renderBlocks.renderMinZ * (1.0D - renderBlocks.renderMaxX), renderBlocks.renderMinZ * renderBlocks.renderMaxX, (1.0D - renderBlocks.renderMinZ) * renderBlocks.renderMaxX, (1.0D - renderBlocks.renderMinZ) * (1.0D - renderBlocks.renderMaxX));
+            renderBlocks.brightnessTopRight = renderBlocks.mixAoBrightness(brightnessMixedXYZNNP, brightnessMixedXYZPNP, brightnessMixedXYZPNN, brightnessMixedXYZNNN, renderBlocks.renderMaxZ * (1.0D - renderBlocks.renderMaxX), renderBlocks.renderMaxZ * renderBlocks.renderMaxX, (1.0D - renderBlocks.renderMaxZ) * renderBlocks.renderMaxX, (1.0D - renderBlocks.renderMaxZ) * (1.0D - renderBlocks.renderMaxX));
+
+        }
+
+        return this;
+    }
+
+    /**
+     * Sets up lighting for the top face and returns the {@link LightingHelper}.
+     * <p>
+     * This is a consolidated <code>method</code> that sets side shading
+     * with respect to the following attributes:
+     * <p>
+     * <ul>
+     *   <li>{@link RenderBlocks#enableAO}</li>
+     *   <li>{@link RenderBlocks#partialRenderBounds}</li>
+     * </ul>
+     *
+     * @param block the block {@link Block}
+     * @param x     the x coordinate
+     * @param y     the y coordinate
+     * @param z     the z coordinate
+     * @return the {@link LightingHelper}
+     */
+    public LightingHelper setupLightingYPos(Block block, int x, int y, int z) {
+        int yOffset = renderBlocks.renderMaxY < 1.0F ? y : y + 1;
+
+        if (renderBlocks.enableAO) {
+
+            int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, yOffset, z);
+            brightness = mixedBrightness;
+
+            float aoLightValue = renderBlocks.blockAccess.getBlock(x, yOffset, z).getAmbientOcclusionLightValue();
+
+            renderBlocks.aoBrightnessXYNP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, yOffset, z);
+            renderBlocks.aoBrightnessXYPP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x + 1, yOffset, z);
+            renderBlocks.aoBrightnessYZPN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, yOffset, z - 1);
+            renderBlocks.aoBrightnessYZPP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, yOffset, z + 1);
+            renderBlocks.aoBrightnessXYZNPN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, yOffset, z - 1);
+            renderBlocks.aoBrightnessXYZPPN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x + 1, yOffset, z - 1);
+            renderBlocks.aoBrightnessXYZNPP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, yOffset, z + 1);
+            renderBlocks.aoBrightnessXYZPPP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x + 1, yOffset, z + 1);
+            renderBlocks.aoLightValueScratchXYNP = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y + 1, z).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x - 1, y, z).getAmbientOcclusionLightValue(), renderBlocks.renderMaxY);
+            renderBlocks.aoLightValueScratchXYPP = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y + 1, z).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x + 1, y, z).getAmbientOcclusionLightValue(), renderBlocks.renderMaxY);
+            renderBlocks.aoLightValueScratchYZPN = getMixedAo(renderBlocks.blockAccess.getBlock(x, y + 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y, z - 1).getAmbientOcclusionLightValue(), renderBlocks.renderMaxY);
+            renderBlocks.aoLightValueScratchYZPP = getMixedAo(renderBlocks.blockAccess.getBlock(x, y + 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y, z + 1).getAmbientOcclusionLightValue(), renderBlocks.renderMaxY);
+            renderBlocks.aoLightValueScratchXYZNPN = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y + 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x - 1, y, z - 1).getAmbientOcclusionLightValue(), renderBlocks.renderMaxY);
+            renderBlocks.aoLightValueScratchXYZPPN = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y + 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x + 1, y, z - 1).getAmbientOcclusionLightValue(), renderBlocks.renderMaxY);
+            renderBlocks.aoLightValueScratchXYZNPP = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y + 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x - 1, y, z + 1).getAmbientOcclusionLightValue(), renderBlocks.renderMaxY);
+            renderBlocks.aoLightValueScratchXYZPPP = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y + 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x + 1, y, z + 1).getAmbientOcclusionLightValue(), renderBlocks.renderMaxY);
+
+            int brightnessMixedXYZPPP = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessYZPP, renderBlocks.aoBrightnessXYZPPP, renderBlocks.aoBrightnessXYPP, mixedBrightness);
+            int brightnessMixedXYZPPN = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessYZPN, renderBlocks.aoBrightnessXYPP, renderBlocks.aoBrightnessXYZPPN, mixedBrightness);
+            int brightnessMixedXYZNPN = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXYNP, renderBlocks.aoBrightnessXYZNPN, renderBlocks.aoBrightnessYZPN, mixedBrightness);
+            int brightnessMixedXYZNPP = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXYZNPP, renderBlocks.aoBrightnessXYNP, renderBlocks.aoBrightnessYZPP, mixedBrightness);
+
+            float aoMixedXYZPPP = (renderBlocks.aoLightValueScratchYZPP + aoLightValue + renderBlocks.aoLightValueScratchXYZPPP + renderBlocks.aoLightValueScratchXYPP) / 4.0F;
+            float aoMixedXYZPPN = (aoLightValue + renderBlocks.aoLightValueScratchYZPN + renderBlocks.aoLightValueScratchXYPP + renderBlocks.aoLightValueScratchXYZPPN) / 4.0F;
+            float aoMixedXYZNPN = (renderBlocks.aoLightValueScratchXYNP + renderBlocks.aoLightValueScratchXYZNPN + aoLightValue + renderBlocks.aoLightValueScratchYZPN) / 4.0F;
+            float aoMixedXYZNPP = (renderBlocks.aoLightValueScratchXYZNPP + renderBlocks.aoLightValueScratchXYNP + renderBlocks.aoLightValueScratchYZPP + aoLightValue) / 4.0F;
+
+            aoTopLeft     /*SE*/ = (float) (aoMixedXYZNPP * renderBlocks.renderMaxZ * (1.0D - renderBlocks.renderMaxX) + aoMixedXYZPPP * renderBlocks.renderMaxZ * renderBlocks.renderMaxX + aoMixedXYZPPN * (1.0D - renderBlocks.renderMaxZ) * renderBlocks.renderMaxX + aoMixedXYZNPN * (1.0D - renderBlocks.renderMaxZ) * (1.0D - renderBlocks.renderMaxX));
+            aoBottomLeft  /*NE*/ = (float) (aoMixedXYZNPP * renderBlocks.renderMinZ * (1.0D - renderBlocks.renderMaxX) + aoMixedXYZPPP * renderBlocks.renderMinZ * renderBlocks.renderMaxX + aoMixedXYZPPN * (1.0D - renderBlocks.renderMinZ) * renderBlocks.renderMaxX + aoMixedXYZNPN * (1.0D - renderBlocks.renderMinZ) * (1.0D - renderBlocks.renderMaxX));
+            aoBottomRight /*NW*/ = (float) (aoMixedXYZNPP * renderBlocks.renderMinZ * (1.0D - renderBlocks.renderMinX) + aoMixedXYZPPP * renderBlocks.renderMinZ * renderBlocks.renderMinX + aoMixedXYZPPN * (1.0D - renderBlocks.renderMinZ) * renderBlocks.renderMinX + aoMixedXYZNPN * (1.0D - renderBlocks.renderMinZ) * (1.0D - renderBlocks.renderMinX));
+            aoTopRight    /*SW*/ = (float) (aoMixedXYZNPP * renderBlocks.renderMaxZ * (1.0D - renderBlocks.renderMinX) + aoMixedXYZPPP * renderBlocks.renderMaxZ * renderBlocks.renderMinX + aoMixedXYZPPN * (1.0D - renderBlocks.renderMaxZ) * renderBlocks.renderMinX + aoMixedXYZNPN * (1.0D - renderBlocks.renderMaxZ) * (1.0D - renderBlocks.renderMinX));
+
+            renderBlocks.brightnessTopLeft = renderBlocks.mixAoBrightness(brightnessMixedXYZNPP, brightnessMixedXYZPPP, brightnessMixedXYZPPN, brightnessMixedXYZNPN, renderBlocks.renderMaxZ * (1.0D - renderBlocks.renderMaxX), renderBlocks.renderMaxZ * renderBlocks.renderMaxX, (1.0D - renderBlocks.renderMaxZ) * renderBlocks.renderMaxX, (1.0D - renderBlocks.renderMaxZ) * (1.0D - renderBlocks.renderMaxX));
+            renderBlocks.brightnessBottomLeft = renderBlocks.mixAoBrightness(brightnessMixedXYZNPP, brightnessMixedXYZPPP, brightnessMixedXYZPPN, brightnessMixedXYZNPN, renderBlocks.renderMinZ * (1.0D - renderBlocks.renderMaxX), renderBlocks.renderMinZ * renderBlocks.renderMaxX, (1.0D - renderBlocks.renderMinZ) * renderBlocks.renderMaxX, (1.0D - renderBlocks.renderMinZ) * (1.0D - renderBlocks.renderMaxX));
+            renderBlocks.brightnessBottomRight = renderBlocks.mixAoBrightness(brightnessMixedXYZNPP, brightnessMixedXYZPPP, brightnessMixedXYZPPN, brightnessMixedXYZNPN, renderBlocks.renderMinZ * (1.0D - renderBlocks.renderMinX), renderBlocks.renderMinZ * renderBlocks.renderMinX, (1.0D - renderBlocks.renderMinZ) * renderBlocks.renderMinX, (1.0D - renderBlocks.renderMinZ) * (1.0D - renderBlocks.renderMinX));
+            renderBlocks.brightnessTopRight = renderBlocks.mixAoBrightness(brightnessMixedXYZNPP, brightnessMixedXYZPPP, brightnessMixedXYZPPN, brightnessMixedXYZNPN, renderBlocks.renderMaxZ * (1.0D - renderBlocks.renderMinX), renderBlocks.renderMaxZ * renderBlocks.renderMinX, (1.0D - renderBlocks.renderMaxZ) * renderBlocks.renderMinX, (1.0D - renderBlocks.renderMaxZ) * (1.0D - renderBlocks.renderMinX));
+        }
+
+        return this;
+    }
+
+    /**
+     * Sets up lighting for the North face and returns the {@link LightingHelper}.
+     * <p>
+     * This is a consolidated <code>method</code> that sets side shading
+     * with respect to the following attributes:
+     * <p>
+     * <ul>
+     *   <li>{@link RenderBlocks#enableAO}</li>
+     *   <li>{@link RenderBlocks#partialRenderBounds}</li>
+     * </ul>
+     *
+     * @param block the block {@link Block}
+     * @param x     the x coordinate
+     * @param y     the y coordinate
+     * @param z     the z coordinate
+     * @return the {@link LightingHelper}
+     */
+    public LightingHelper setupLightingZNeg(Block block, int x, int y, int z) {
+        int zOffset = renderBlocks.renderMinZ > 0.0F ? z : z - 1;
+
+        if (renderBlocks.enableAO) {
+
+            int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, y, zOffset);
+            brightness = mixedBrightness;
+
+            float ratio = (float) (1.0F - renderBlocks.renderMinZ);
+            float aoLightValue = renderBlocks.blockAccess.getBlock(x, y, zOffset).getAmbientOcclusionLightValue();
+
+            renderBlocks.aoBrightnessXZNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, y, zOffset);
+            renderBlocks.aoBrightnessYZNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, y - 1, zOffset);
+            renderBlocks.aoBrightnessYZPN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, y + 1, zOffset);
+            renderBlocks.aoBrightnessXZPN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x + 1, y, zOffset);
+            renderBlocks.aoBrightnessXYZNNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, y - 1, zOffset);
+            renderBlocks.aoBrightnessXYZNPN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, y + 1, zOffset);
+            renderBlocks.aoBrightnessXYZPNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x + 1, y - 1, zOffset);
+            renderBlocks.aoBrightnessXYZPPN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x + 1, y + 1, zOffset);
+            renderBlocks.aoLightValueScratchXZNN = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x - 1, y, z).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchYZNN = getMixedAo(renderBlocks.blockAccess.getBlock(x, y - 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y - 1, z).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchYZPN = getMixedAo(renderBlocks.blockAccess.getBlock(x, y + 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y + 1, z).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXZPN = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x + 1, y, z).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXYZNNN = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y - 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x - 1, y - 1, z).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXYZNPN = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y + 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x - 1, y + 1, z).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXYZPNN = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y - 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x + 1, y - 1, z).getAmbientOcclusionLightValue(), ratio);
+            renderBlocks.aoLightValueScratchXYZPPN = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y + 1, z - 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x + 1, y + 1, z).getAmbientOcclusionLightValue(), ratio);
+
+            int brightnessMixedXYZPPN = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessYZPN, renderBlocks.aoBrightnessXZPN, renderBlocks.aoBrightnessXYZPPN, mixedBrightness);
+            int brightnessMixedXYZPNN = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessYZNN, renderBlocks.aoBrightnessXYZPNN, renderBlocks.aoBrightnessXZPN, mixedBrightness);
+            int brightnessMixedXYZNNN = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXYZNNN, renderBlocks.aoBrightnessXZNN, renderBlocks.aoBrightnessYZNN, mixedBrightness);
+            int brightnessMixedXYZNPN = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXZNN, renderBlocks.aoBrightnessXYZNPN, renderBlocks.aoBrightnessYZPN, mixedBrightness);
+
+            float aoMixedXYZPPN = (aoLightValue + renderBlocks.aoLightValueScratchYZPN + renderBlocks.aoLightValueScratchXZPN + renderBlocks.aoLightValueScratchXYZPPN) / 4.0F;
+            float aoMixedXYZPNN = (renderBlocks.aoLightValueScratchYZNN + aoLightValue + renderBlocks.aoLightValueScratchXYZPNN + renderBlocks.aoLightValueScratchXZPN) / 4.0F;
+            float aoMixedXYZNNN = (renderBlocks.aoLightValueScratchXYZNNN + renderBlocks.aoLightValueScratchXZNN + renderBlocks.aoLightValueScratchYZNN + aoLightValue) / 4.0F;
+            float aoMixedXYZNPN = (renderBlocks.aoLightValueScratchXZNN + renderBlocks.aoLightValueScratchXYZNPN + aoLightValue + renderBlocks.aoLightValueScratchYZPN) / 4.0F;
+
+            aoTopLeft = (float) (aoMixedXYZNPN * renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMinX) + aoMixedXYZPPN * renderBlocks.renderMaxY * renderBlocks.renderMinX + aoMixedXYZPNN * (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMinX + aoMixedXYZNNN * (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMinX));
+            aoBottomLeft = (float) (aoMixedXYZNPN * renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMaxX) + aoMixedXYZPPN * renderBlocks.renderMaxY * renderBlocks.renderMaxX + aoMixedXYZPNN * (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMaxX + aoMixedXYZNNN * (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMaxX));
+            aoBottomRight = (float) (aoMixedXYZNPN * renderBlocks.renderMinY * (1.0D - renderBlocks.renderMaxX) + aoMixedXYZPPN * renderBlocks.renderMinY * renderBlocks.renderMaxX + aoMixedXYZPNN * (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMaxX + aoMixedXYZNNN * (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMaxX));
+            aoTopRight = (float) (aoMixedXYZNPN * renderBlocks.renderMinY * (1.0D - renderBlocks.renderMinX) + aoMixedXYZPPN * renderBlocks.renderMinY * renderBlocks.renderMinX + aoMixedXYZPNN * (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMinX + aoMixedXYZNNN * (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMinX));
+
+            renderBlocks.brightnessTopLeft = renderBlocks.mixAoBrightness(brightnessMixedXYZNPN, brightnessMixedXYZPPN, brightnessMixedXYZPNN, brightnessMixedXYZNNN, renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMinX), renderBlocks.renderMaxY * renderBlocks.renderMinX, (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMinX, (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMinX));
+            renderBlocks.brightnessBottomLeft = renderBlocks.mixAoBrightness(brightnessMixedXYZNPN, brightnessMixedXYZPPN, brightnessMixedXYZPNN, brightnessMixedXYZNNN, renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMaxX), renderBlocks.renderMaxY * renderBlocks.renderMaxX, (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMaxX, (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMaxX));
+            renderBlocks.brightnessBottomRight = renderBlocks.mixAoBrightness(brightnessMixedXYZNPN, brightnessMixedXYZPPN, brightnessMixedXYZPNN, brightnessMixedXYZNNN, renderBlocks.renderMinY * (1.0D - renderBlocks.renderMaxX), renderBlocks.renderMinY * renderBlocks.renderMaxX, (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMaxX, (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMaxX));
+            renderBlocks.brightnessTopRight = renderBlocks.mixAoBrightness(brightnessMixedXYZNPN, brightnessMixedXYZPPN, brightnessMixedXYZPNN, brightnessMixedXYZNNN, renderBlocks.renderMinY * (1.0D - renderBlocks.renderMinX), renderBlocks.renderMinY * renderBlocks.renderMinX, (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMinX, (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMinX));
+
+        }
+
+        return this;
+    }
+
+    /**
+     * Sets up lighting for the South face and returns the {@link LightingHelper}.
+     * <p>
+     * This is a consolidated <code>method</code> that sets side shading
+     * with respect to the following attributes:
+     * <p>
+     * <ul>
+     *   <li>{@link RenderBlocks#enableAO}</li>
+     *   <li>{@link RenderBlocks#partialRenderBounds}</li>
+     * </ul>
+     *
+     * @param block the block {@link Block}
+     * @param x     the x coordinate
+     * @param y     the y coordinate
+     * @param z     the z coordinate
+     * @return the {@link LightingHelper}
+     */
+    public LightingHelper setupLightingZPos(Block block, int x, int y, int z) {
+        int zOffset = renderBlocks.renderMaxZ < 1.0F ? z : z + 1;
+
+        if (renderBlocks.enableAO) {
+
+            int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, y, zOffset);
+            brightness = mixedBrightness;
+
+            float aoLightValue = renderBlocks.blockAccess.getBlock(x, y, zOffset).getAmbientOcclusionLightValue();
+
+            renderBlocks.aoBrightnessXZNP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, y, zOffset);
+            renderBlocks.aoBrightnessXZPP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x + 1, y, zOffset);
+            renderBlocks.aoBrightnessYZNP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, y - 1, zOffset);
+            renderBlocks.aoBrightnessYZPP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, y + 1, zOffset);
+            renderBlocks.aoBrightnessXYZNNP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, y - 1, zOffset);
+            renderBlocks.aoBrightnessXYZNPP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, y + 1, zOffset);
+            renderBlocks.aoBrightnessXYZPNP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x + 1, y - 1, zOffset);
+            renderBlocks.aoBrightnessXYZPPP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x + 1, y + 1, zOffset);
+            renderBlocks.aoLightValueScratchXZNP = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x - 1, y, z).getAmbientOcclusionLightValue(), renderBlocks.renderMaxZ);
+            renderBlocks.aoLightValueScratchXZPP = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x + 1, y, z).getAmbientOcclusionLightValue(), renderBlocks.renderMaxZ);
+            renderBlocks.aoLightValueScratchYZNP = getMixedAo(renderBlocks.blockAccess.getBlock(x, y - 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y - 1, z).getAmbientOcclusionLightValue(), renderBlocks.renderMaxZ);
+            renderBlocks.aoLightValueScratchYZPP = getMixedAo(renderBlocks.blockAccess.getBlock(x, y + 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x, y + 1, z).getAmbientOcclusionLightValue(), renderBlocks.renderMaxZ);
+            renderBlocks.aoLightValueScratchXYZNNP = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y - 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x - 1, y - 1, z).getAmbientOcclusionLightValue(), renderBlocks.renderMaxZ);
+            renderBlocks.aoLightValueScratchXYZNPP = getMixedAo(renderBlocks.blockAccess.getBlock(x - 1, y + 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x - 1, y + 1, z).getAmbientOcclusionLightValue(), renderBlocks.renderMaxZ);
+            renderBlocks.aoLightValueScratchXYZPNP = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y - 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x + 1, y - 1, z).getAmbientOcclusionLightValue(), renderBlocks.renderMaxZ);
+            renderBlocks.aoLightValueScratchXYZPPP = getMixedAo(renderBlocks.blockAccess.getBlock(x + 1, y + 1, z + 1).getAmbientOcclusionLightValue(), renderBlocks.blockAccess.getBlock(x + 1, y + 1, z).getAmbientOcclusionLightValue(), renderBlocks.renderMaxZ);
+
+            int brightnessMixedXYZNPP = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXZNP, renderBlocks.aoBrightnessXYZNPP, renderBlocks.aoBrightnessYZPP, mixedBrightness);
+            int brightnessMixedXYZNNP = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessXYZNNP, renderBlocks.aoBrightnessXZNP, renderBlocks.aoBrightnessYZNP, mixedBrightness);
+            int brightnessMixedXYZPNP = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessYZNP, renderBlocks.aoBrightnessXYZPNP, renderBlocks.aoBrightnessXZPP, mixedBrightness);
+            int brightnessMixedXYZPPP = renderBlocks.getAoBrightness(renderBlocks.aoBrightnessYZPP, renderBlocks.aoBrightnessXZPP, renderBlocks.aoBrightnessXYZPPP, mixedBrightness);
+
+            float aoMixedXYZNPP = (renderBlocks.aoLightValueScratchXZNP + renderBlocks.aoLightValueScratchXYZNPP + aoLightValue + renderBlocks.aoLightValueScratchYZPP) / 4.0F;
+            float aoMixedXYZNNP = (renderBlocks.aoLightValueScratchXYZNNP + renderBlocks.aoLightValueScratchXZNP + renderBlocks.aoLightValueScratchYZNP + aoLightValue) / 4.0F;
+            float aoMixedXYZPNP = (renderBlocks.aoLightValueScratchYZNP + aoLightValue + renderBlocks.aoLightValueScratchXYZPNP + renderBlocks.aoLightValueScratchXZPP) / 4.0F;
+            float aoMixedXYZPPP = (aoLightValue + renderBlocks.aoLightValueScratchYZPP + renderBlocks.aoLightValueScratchXZPP + renderBlocks.aoLightValueScratchXYZPPP) / 4.0F;
+
+            aoTopLeft = (float) (aoMixedXYZNPP * renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMinX) + aoMixedXYZPPP * renderBlocks.renderMaxY * renderBlocks.renderMinX + aoMixedXYZPNP * (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMinX + aoMixedXYZNNP * (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMinX));
+            aoBottomLeft = (float) (aoMixedXYZNPP * renderBlocks.renderMinY * (1.0D - renderBlocks.renderMinX) + aoMixedXYZPPP * renderBlocks.renderMinY * renderBlocks.renderMinX + aoMixedXYZPNP * (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMinX + aoMixedXYZNNP * (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMinX));
+            aoBottomRight = (float) (aoMixedXYZNPP * renderBlocks.renderMinY * (1.0D - renderBlocks.renderMaxX) + aoMixedXYZPPP * renderBlocks.renderMinY * renderBlocks.renderMaxX + aoMixedXYZPNP * (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMaxX + aoMixedXYZNNP * (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMaxX));
+            aoTopRight = (float) (aoMixedXYZNPP * renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMaxX) + aoMixedXYZPPP * renderBlocks.renderMaxY * renderBlocks.renderMaxX + aoMixedXYZPNP * (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMaxX + aoMixedXYZNNP * (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMaxX));
+
+            renderBlocks.brightnessTopLeft = renderBlocks.mixAoBrightness(brightnessMixedXYZNPP, brightnessMixedXYZNNP, brightnessMixedXYZPNP, brightnessMixedXYZPPP, renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMinX), (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMinX), (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMinX, renderBlocks.renderMaxY * renderBlocks.renderMinX);
+            renderBlocks.brightnessBottomLeft = renderBlocks.mixAoBrightness(brightnessMixedXYZNPP, brightnessMixedXYZNNP, brightnessMixedXYZPNP, brightnessMixedXYZPPP, renderBlocks.renderMinY * (1.0D - renderBlocks.renderMinX), (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMinX), (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMinX, renderBlocks.renderMinY * renderBlocks.renderMinX);
+            renderBlocks.brightnessBottomRight = renderBlocks.mixAoBrightness(brightnessMixedXYZNPP, brightnessMixedXYZNNP, brightnessMixedXYZPNP, brightnessMixedXYZPPP, renderBlocks.renderMinY * (1.0D - renderBlocks.renderMaxX), (1.0D - renderBlocks.renderMinY) * (1.0D - renderBlocks.renderMaxX), (1.0D - renderBlocks.renderMinY) * renderBlocks.renderMaxX, renderBlocks.renderMinY * renderBlocks.renderMaxX);
+            renderBlocks.brightnessTopRight = renderBlocks.mixAoBrightness(brightnessMixedXYZNPP, brightnessMixedXYZNNP, brightnessMixedXYZPNP, brightnessMixedXYZPPP, renderBlocks.renderMaxY * (1.0D - renderBlocks.renderMaxX), (1.0D - renderBlocks.renderMaxY) * (1.0D - renderBlocks.renderMaxX), (1.0D - renderBlocks.renderMaxY) * renderBlocks.renderMaxX, renderBlocks.renderMaxY * renderBlocks.renderMaxX);
+        }
+
+        return this;
+    }
+}
-- 
cgit 


From 22b4fef98a49481416a6930383380d0a6e5efcb8 Mon Sep 17 00:00:00 2001
From: Léa Gris <lea.gris@noiraude.net>
Date: Wed, 3 Mar 2021 03:09:05 +0100
Subject: impr(rendering): Machine block casts an ambient occlusion shadow

- Implement the missing ambient occlusion shadow from machine block over neighbour blocks.
- Fix the LightingHelper to properly shade pipes/cables/wires against an opaque block.
- Refactor and cleanup the GT_Block_Machines class of all bad practices and code smell,
  checked and validated with Sonarlint.
---
 src/main/java/gregtech/api/GregTech_API.java       |  19 +
 .../java/gregtech/api/util/LightingHelper.java     |  61 ++--
 .../gregtech/common/blocks/GT_Block_Machines.java  | 387 +++++++++++++--------
 .../common/blocks/GT_Material_Machines.java        |   2 +-
 4 files changed, 297 insertions(+), 172 deletions(-)

(limited to 'src/main/java/gregtech/api/util/LightingHelper.java')

diff --git a/src/main/java/gregtech/api/GregTech_API.java b/src/main/java/gregtech/api/GregTech_API.java
index 0fbb1cd745..e24297c48c 100644
--- a/src/main/java/gregtech/api/GregTech_API.java
+++ b/src/main/java/gregtech/api/GregTech_API.java
@@ -739,4 +739,23 @@ public class GregTech_API {
         sToolList.add(new GT_ItemStack(GT_Utility.copyAmount(1, aTool)));
         return true;
     }
+
+    /**
+     * Sets the {@link IIconRegister} for Block Icons
+     * @param aIconRegister The {@link IIconRegister} Icon Register
+     */
+    @SideOnly(Side.CLIENT)
+    public static void setBlockIconRegister(IIconRegister aIconRegister) {
+        sBlockIcons = aIconRegister;
+    };
+
+    /**
+     * Sets the {@link IIconRegister} for Items Icons
+     * @param aIconRegister The {@link IIconRegister} Icon Register
+     */
+    @SideOnly(Side.CLIENT)
+    public static void setItemIconRegister(IIconRegister aIconRegister) {
+        GregTech_API.sItemIcons = aIconRegister;
+    }
+
 }
diff --git a/src/main/java/gregtech/api/util/LightingHelper.java b/src/main/java/gregtech/api/util/LightingHelper.java
index 3696d88fec..df70ffaeef 100644
--- a/src/main/java/gregtech/api/util/LightingHelper.java
+++ b/src/main/java/gregtech/api/util/LightingHelper.java
@@ -285,6 +285,21 @@ public class LightingHelper {
         }
     }
 
+    /**
+     * Gets mixed ambient occlusion value from two inputs, with a
+     * ratio applied to the final result.
+     *
+     * @param ao1   the first ambient occlusion value
+     * @param ao2   the second ambient occlusion value
+     * @param ratio the ratio for mixing
+     * @return the mixed red, green, blue float values
+     */
+    public static float getMixedAo(float ao1, float ao2, double ratio) {
+        float diff = (float) (Math.abs(ao1 - ao2) * (1.0F - ratio));
+
+        return ao1 > ao2 ? ao1 - diff : ao1 + diff;
+    }
+
     /**
      * Sets up lighting for the West face and returns the {@link LightingHelper}.
      * <p>
@@ -303,15 +318,16 @@ public class LightingHelper {
      * @return the {@link LightingHelper}
      */
     public LightingHelper setupLightingXNeg(Block block, int x, int y, int z) {
-        int xOffset = renderBlocks.renderMinX > 0.0F ? x : x - 1;
 
         if (renderBlocks.enableAO) {
 
+            int xOffset = renderBlocks.renderMinX > 0.0F ? x : x - 1;
+
             int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y, z);
             brightness = mixedBrightness;
 
             float ratio = (float) (1.0F - renderBlocks.renderMinX);
-            float aoLightValue = renderBlocks.blockAccess.getBlock(xOffset, y, z).getAmbientOcclusionLightValue();
+            float aoLightValue = renderBlocks.blockAccess.getBlock(x - 1, y, z).getAmbientOcclusionLightValue();
 
             renderBlocks.aoBrightnessXYNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y - 1, z);
             renderBlocks.aoBrightnessXZNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y, z - 1);
@@ -355,21 +371,6 @@ public class LightingHelper {
         return this;
     }
 
-    /**
-     * Gets mixed ambient occlusion value from two inputs, with a
-     * ratio applied to the final result.
-     *
-     * @param ao1   the first ambient occlusion value
-     * @param ao2   the second ambient occlusion value
-     * @param ratio the ratio for mixing
-     * @return the mixed red, green, blue float values
-     */
-    public static float getMixedAo(float ao1, float ao2, double ratio) {
-        float diff = (float) (Math.abs(ao1 - ao2) * (1.0F - ratio));
-
-        return ao1 > ao2 ? ao1 - diff : ao1 + diff;
-    }
-
     /**
      * Sets up lighting for the East face and returns the {@link LightingHelper}.
      * <p>
@@ -388,14 +389,15 @@ public class LightingHelper {
      * @return the {@link LightingHelper}
      */
     public LightingHelper setupLightingXPos(Block block, int x, int y, int z) {
-        int xOffset = renderBlocks.renderMaxX < 1.0F ? x : x + 1;
 
         if (renderBlocks.enableAO) {
 
+            int xOffset = renderBlocks.renderMaxX < 1.0F ? x : x + 1;
+
             int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y, z);
             brightness = mixedBrightness;
 
-            float aoLightValue = renderBlocks.blockAccess.getBlock(xOffset, y, z).getAmbientOcclusionLightValue();
+            float aoLightValue = renderBlocks.blockAccess.getBlock(x + 1, y, z).getAmbientOcclusionLightValue();
 
             renderBlocks.aoBrightnessXYPN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y - 1, z);
             renderBlocks.aoBrightnessXZPN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y, z - 1);
@@ -458,15 +460,15 @@ public class LightingHelper {
      */
     public LightingHelper setupLightingYNeg(Block block, int x, int y, int z) {
 
-        int yOffset = renderBlocks.renderMinY > 0.0F ? y : y - 1;
-
         if (renderBlocks.enableAO) {
 
+            int yOffset = renderBlocks.renderMinY > 0.0F ? y : y - 1;
+
             int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, yOffset, z);
             brightness = mixedBrightness;
 
             float ratio = (float) (1.0F - renderBlocks.renderMinY);
-            float aoLightValue = renderBlocks.blockAccess.getBlock(x, yOffset, z).getAmbientOcclusionLightValue();
+            float aoLightValue = renderBlocks.blockAccess.getBlock(x, y - 1, z).getAmbientOcclusionLightValue();
 
             renderBlocks.aoBrightnessXYNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, yOffset, z);
             renderBlocks.aoBrightnessYZNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, yOffset, z - 1);
@@ -528,14 +530,15 @@ public class LightingHelper {
      * @return the {@link LightingHelper}
      */
     public LightingHelper setupLightingYPos(Block block, int x, int y, int z) {
-        int yOffset = renderBlocks.renderMaxY < 1.0F ? y : y + 1;
 
         if (renderBlocks.enableAO) {
 
+            int yOffset = renderBlocks.renderMaxY < 1.0F ? y : y + 1;
+
             int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, yOffset, z);
             brightness = mixedBrightness;
 
-            float aoLightValue = renderBlocks.blockAccess.getBlock(x, yOffset, z).getAmbientOcclusionLightValue();
+            float aoLightValue = renderBlocks.blockAccess.getBlock(x, y + 1, z).getAmbientOcclusionLightValue();
 
             renderBlocks.aoBrightnessXYNP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, yOffset, z);
             renderBlocks.aoBrightnessXYPP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x + 1, yOffset, z);
@@ -596,15 +599,16 @@ public class LightingHelper {
      * @return the {@link LightingHelper}
      */
     public LightingHelper setupLightingZNeg(Block block, int x, int y, int z) {
-        int zOffset = renderBlocks.renderMinZ > 0.0F ? z : z - 1;
 
         if (renderBlocks.enableAO) {
 
+            int zOffset = renderBlocks.renderMinZ > 0.0F ? z : z - 1;
+
             int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, y, zOffset);
             brightness = mixedBrightness;
 
             float ratio = (float) (1.0F - renderBlocks.renderMinZ);
-            float aoLightValue = renderBlocks.blockAccess.getBlock(x, y, zOffset).getAmbientOcclusionLightValue();
+            float aoLightValue = renderBlocks.blockAccess.getBlock(x, y, z - 1).getAmbientOcclusionLightValue();
 
             renderBlocks.aoBrightnessXZNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, y, zOffset);
             renderBlocks.aoBrightnessYZNN = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, y - 1, zOffset);
@@ -666,14 +670,15 @@ public class LightingHelper {
      * @return the {@link LightingHelper}
      */
     public LightingHelper setupLightingZPos(Block block, int x, int y, int z) {
-        int zOffset = renderBlocks.renderMaxZ < 1.0F ? z : z + 1;
 
         if (renderBlocks.enableAO) {
 
+            int zOffset = renderBlocks.renderMaxZ < 1.0F ? z : z + 1;
+
             int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, y, zOffset);
             brightness = mixedBrightness;
 
-            float aoLightValue = renderBlocks.blockAccess.getBlock(x, y, zOffset).getAmbientOcclusionLightValue();
+            float aoLightValue = renderBlocks.blockAccess.getBlock(x, y, z + 1).getAmbientOcclusionLightValue();
 
             renderBlocks.aoBrightnessXZNP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x - 1, y, zOffset);
             renderBlocks.aoBrightnessXZPP = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x + 1, y, zOffset);
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Machines.java b/src/main/java/gregtech/common/blocks/GT_Block_Machines.java
index 993f9baf38..0d673a020e 100644
--- a/src/main/java/gregtech/common/blocks/GT_Block_Machines.java
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Machines.java
@@ -39,13 +39,15 @@ import net.minecraft.world.World;
 import net.minecraftforge.common.util.ForgeDirection;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 import static gregtech.GT_Mod.GT_FML_LOGGER;
 import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
 
 public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlock, ITileEntityProvider {
-    public static ThreadLocal<IGregTechTileEntity> mTemporaryTileEntity = new ThreadLocal();
+    private static final ThreadLocal<IGregTechTileEntity> mTemporaryTileEntity = new ThreadLocal<>();
+    private boolean renderAsNormalBlock;
 
     public GT_Block_Machines() {
         super(GT_Item_Machines.class, "gt.blockmachines", new GT_Material_Machines());
@@ -55,8 +57,11 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo
         setStepSound(soundTypeMetal);
         setCreativeTab(GregTech_API.TAB_GREGTECH);
         this.isBlockContainer = true;
+        this.renderAsNormalBlock = true;
+        this.useNeighborBrightness = true;
     }
 
+    @Override
     public String getHarvestTool(int aMeta) {
         if (aMeta >= 8 && aMeta <= 11) {
             return "cutter";
@@ -64,14 +69,17 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo
         return "wrench";
     }
 
+    @Override
     public int getHarvestLevel(int aMeta) {
         return aMeta % 4;
     }
 
+    @Override
     protected boolean canSilkHarvest() {
         return false;
     }
 
+    @Override
     public void onNeighborChange(IBlockAccess aWorld, int aX, int aY, int aZ, int aTileX, int aTileY, int aTileZ) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
         if ((tTileEntity instanceof BaseTileEntity)) {
@@ -79,6 +87,7 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo
         }
     }
 
+    @Override
     public void onNeighborBlockChange(World aWorld, int aX, int aY, int aZ, Block aBlock) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
         if ((tTileEntity instanceof BaseMetaPipeEntity)) {
@@ -86,6 +95,7 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo
         }
     }
 
+    @Override
     public void onBlockAdded(World aWorld, int aX, int aY, int aZ) {
         super.onBlockAdded(aWorld, aX, aY, aZ);
         if (GregTech_API.isMachineBlock(this, aWorld.getBlockMetadata(aX, aY, aZ))) {
@@ -93,22 +103,27 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo
         }
     }
 
+    @Override
     public String getUnlocalizedName() {
         return "gt.blockmachines";
     }
 
+    @Override
     public String getLocalizedName() {
         return StatCollector.translateToLocal(getUnlocalizedName() + ".name");
     }
 
+    @Override
     public int getFlammability(IBlockAccess aWorld, int aX, int aY, int aZ, ForgeDirection face) {
         return 0;
     }
 
+    @Override
     public int getFireSpreadSpeed(IBlockAccess aWorld, int aX, int aY, int aZ, ForgeDirection face) {
-        return (GregTech_API.sMachineFlammable) && (aWorld.getBlockMetadata(aX, aY, aZ) == 0) ? 100 : 0;
+        return GregTech_API.sMachineFlammable && (aWorld.getBlockMetadata(aX, aY, aZ) == 0) ? 100 : 0;
     }
 
+    @Override
     public int getRenderType() {
         if (GT_Renderer_Block.INSTANCE == null) {
             return super.getRenderType();
@@ -116,80 +131,109 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo
         return GT_Renderer_Block.INSTANCE.mRenderID;
     }
 
+    @Override
     public boolean isFireSource(World aWorld, int aX, int aY, int aZ, ForgeDirection side) {
-        return (GregTech_API.sMachineFlammable) && (aWorld.getBlockMetadata(aX, aY, aZ) == 0);
+        return GregTech_API.sMachineFlammable && (aWorld.getBlockMetadata(aX, aY, aZ) == 0);
     }
 
+    @Override
     public boolean isFlammable(IBlockAccess aWorld, int aX, int aY, int aZ, ForgeDirection face) {
-        return (GregTech_API.sMachineFlammable) && (aWorld.getBlockMetadata(aX, aY, aZ) == 0);
+        return GregTech_API.sMachineFlammable && (aWorld.getBlockMetadata(aX, aY, aZ) == 0);
     }
 
+    @Override
     public boolean canCreatureSpawn(EnumCreatureType type, IBlockAccess aWorld, int aX, int aY, int aZ) {
         return false;
     }
 
+    @Override
     public boolean canConnectRedstone(IBlockAccess var1, int var2, int var3, int var4, int var5) {
         return true;
     }
 
+    @Override
     public boolean canBeReplacedByLeaves(IBlockAccess aWorld, int aX, int aY, int aZ) {
         return false;
     }
 
+    @Override
     public boolean isNormalCube(IBlockAccess aWorld, int aX, int aY, int aZ) {
         return false;
     }
 
+    @Override
     public boolean hasTileEntity(int aMeta) {
         return true;
     }
 
+    @Override
     public boolean hasComparatorInputOverride() {
         return true;
     }
 
+    @Override
     public boolean renderAsNormalBlock() {
-        return false;
+        return renderAsNormalBlock;
+    }
+
+    public GT_Block_Machines setRenderAsNormalBlock(boolean aBool) {
+        renderAsNormalBlock = aBool;
+        return this;
     }
 
+    @Override
     public boolean canProvidePower() {
         return true;
     }
 
+    @Override
     public boolean isOpaqueCube() {
         return false;
     }
 
+    @Override
     public TileEntity createNewTileEntity(World aWorld, int aMeta) {
         return createTileEntity(aWorld, aMeta);
     }
 
+    @SideOnly(Side.CLIENT)
+    @Override
     public IIcon getIcon(IBlockAccess aIBlockAccess, int aX, int aY, int aZ, int aSide) {
         return Textures.BlockIcons.MACHINE_LV_SIDE.getIcon();
     }
 
+    @SideOnly(Side.CLIENT)
+    @Override
     public IIcon getIcon(int aSide, int aMeta) {
         return Textures.BlockIcons.MACHINE_LV_SIDE.getIcon();
     }
 
+    @Override
     public boolean onBlockEventReceived(World aWorld, int aX, int aY, int aZ, int aData1, int aData2) {
         super.onBlockEventReceived(aWorld, aX, aY, aZ, aData1, aData2);
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        return tTileEntity != null ? tTileEntity.receiveClientEvent(aData1, aData2) : false;
+        return tTileEntity != null && tTileEntity.receiveClientEvent(aData1, aData2);
     }
 
-    public void addCollisionBoxesToList(World aWorld, int aX, int aY, int aZ, AxisAlignedBB inputAABB, List outputAABB, Entity collider) {
+    @SuppressWarnings("unchecked") // Old API uses raw List type
+    @Override
+    public void addCollisionBoxesToList(
+            World aWorld, int aX, int aY, int aZ, AxisAlignedBB inputAABB, List outputAABB, Entity collider) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if (((tTileEntity instanceof IGregTechTileEntity)) && (((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null)) {
-            ((IGregTechTileEntity) tTileEntity).addCollisionBoxesToList(aWorld, aX, aY, aZ, inputAABB, outputAABB, collider);
+        if (tTileEntity instanceof IGregTechTileEntity &&
+                ((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null) {
+            ((IGregTechTileEntity) tTileEntity)
+                    .addCollisionBoxesToList(aWorld, aX, aY, aZ, inputAABB, outputAABB, collider);
             return;
         }
         super.addCollisionBoxesToList(aWorld, aX, aY, aZ, inputAABB, outputAABB, collider);
     }
 
+    @Override
     public AxisAlignedBB getCollisionBoundingBoxFromPool(World aWorld, int aX, int aY, int aZ) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if (((tTileEntity instanceof IGregTechTileEntity)) && (((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null)) {
+        if (tTileEntity instanceof IGregTechTileEntity &&
+                ((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null) {
             return ((IGregTechTileEntity) tTileEntity).getCollisionBoundingBoxFromPool(aWorld, aX, aY, aZ);
         }
         return super.getCollisionBoundingBoxFromPool(aWorld, aX, aY, aZ);
@@ -197,10 +241,10 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo
 
     @Override
     @SideOnly(Side.CLIENT)
-    public AxisAlignedBB getSelectedBoundingBoxFromPool(World aWorld, int aX, int aY, int aZ)
-    {
+    public AxisAlignedBB getSelectedBoundingBoxFromPool(World aWorld, int aX, int aY, int aZ) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if (((tTileEntity instanceof IGregTechTileEntity)) && (((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null)) {
+        if (tTileEntity instanceof IGregTechTileEntity &&
+                ((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null) {
             return ((IGregTechTileEntity) tTileEntity).getCollisionBoundingBoxFromPool(aWorld, aX, aY, aZ);
         }
         return super.getSelectedBoundingBoxFromPool(aWorld, aX, aY, aZ);
@@ -209,27 +253,32 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo
     @Override  //THIS
     public void setBlockBoundsBasedOnState(IBlockAccess blockAccess, int aX, int aY, int aZ) {
         TileEntity tTileEntity = blockAccess.getTileEntity(aX, aY, aZ);
-        if (((tTileEntity instanceof IGregTechTileEntity)) && (((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null)) {
-            AxisAlignedBB bbb=((IGregTechTileEntity)tTileEntity).getCollisionBoundingBoxFromPool(((IGregTechTileEntity)tTileEntity).getWorld(), 0, 0, 0);
-            minX=bbb.minX;//This essentially sets block bounds
-            minY=bbb.minY;
-            minZ=bbb.minZ;
-            maxX=bbb.maxX;
-            maxY=bbb.maxY;
-            maxZ=bbb.maxZ;
+        if (tTileEntity instanceof IGregTechTileEntity &&
+                (((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null)) {
+            AxisAlignedBB bbb = ((IGregTechTileEntity) tTileEntity)
+                    .getCollisionBoundingBoxFromPool(
+                            ((IGregTechTileEntity) tTileEntity).getWorld(), 0, 0, 0);
+            minX = bbb.minX; //This essentially sets block bounds
+            minY = bbb.minY;
+            minZ = bbb.minZ;
+            maxX = bbb.maxX;
+            maxY = bbb.maxY;
+            maxZ = bbb.maxZ;
             return;
         }
-        super.setBlockBoundsBasedOnState(blockAccess,aX,aY,aZ);
+        super.setBlockBoundsBasedOnState(blockAccess, aX, aY, aZ);
     }
 
     @Override
     public void setBlockBoundsForItemRender() {
-        super.setBlockBounds(0,0,0,1,1,1);
+        super.setBlockBounds(0, 0, 0, 1, 1, 1);
     }
 
+    @Override
     public void onEntityCollidedWithBlock(World aWorld, int aX, int aY, int aZ, Entity collider) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if (((tTileEntity instanceof IGregTechTileEntity)) && (((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null)) {
+        if (tTileEntity instanceof IGregTechTileEntity &&
+                ((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null) {
             ((IGregTechTileEntity) tTileEntity).onEntityCollidedWithBlock(aWorld, aX, aY, aZ, collider);
             return;
         }
@@ -237,69 +286,74 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo
     }
 
     @SideOnly(Side.CLIENT)
+    @Override
     public void registerBlockIcons(IIconRegister aIconRegister) {
-        if (GregTech_API.sPostloadFinished) {
-            GT_Log.out.println("GT_Mod: Setting up Icon Register for Blocks");
-            GregTech_API.sBlockIcons = aIconRegister;
-
-            GT_Log.out.println("GT_Mod: Registering MetaTileEntity specific Textures");
-            try {
-                for (IMetaTileEntity tMetaTileEntity : GregTech_API.METATILEENTITIES) {
-                    if (tMetaTileEntity != null) {
-                        tMetaTileEntity.registerIcons(aIconRegister);
-                    }
-                }
-            } catch (Throwable e) {e.printStackTrace(GT_Log.err);}
-            GT_Log.out.println("GT_Mod: Registering Crop specific Textures");
-            try {
-                for (GT_BaseCrop tCrop : GT_BaseCrop.sCropList) {
-                    tCrop.registerSprites(aIconRegister);
+        if (!GregTech_API.sPostloadFinished) return;
+        GT_Log.out.println("GT_Mod: Setting up Icon Register for Blocks");
+        GregTech_API.setBlockIconRegister(aIconRegister);
+
+        GT_Log.out.println("GT_Mod: Registering MetaTileEntity specific Textures");
+        try {
+            for (IMetaTileEntity tMetaTileEntity : GregTech_API.METATILEENTITIES) {
+                if (tMetaTileEntity != null) {
+                    tMetaTileEntity.registerIcons(aIconRegister);
                 }
-            } catch (Throwable e) {
-                e.printStackTrace(GT_Log.err);
             }
-            GT_Log.out.println("GT_Mod: Starting Block Icon Load Phase");
-            GT_FML_LOGGER.info("GT_Mod: Starting Block Icon Load Phase");
-            try {
-                for (Runnable tRunnable : GregTech_API.sGTBlockIconload) {
-                    tRunnable.run();
-                }
-            } catch (Throwable e) {e.printStackTrace(GT_Log.err);}
-            GT_Log.out.println("GT_Mod: Finished Block Icon Load Phase");
-            GT_FML_LOGGER.info("GT_Mod: Finished Block Icon Load Phase");
+        } catch (Exception e) {
+            e.printStackTrace(GT_Log.err);
         }
+        GT_Log.out.println("GT_Mod: Registering Crop specific Textures");
+        try {
+            for (GT_BaseCrop tCrop : GT_BaseCrop.sCropList) {
+                tCrop.registerSprites(aIconRegister);
+            }
+        } catch (Exception e) {
+            e.printStackTrace(GT_Log.err);
+        }
+        GT_Log.out.println("GT_Mod: Starting Block Icon Load Phase");
+        GT_FML_LOGGER.info("GT_Mod: Starting Block Icon Load Phase");
+        try {
+            for (Runnable tRunnable : GregTech_API.sGTBlockIconload) {
+                tRunnable.run();
+            }
+        } catch (Exception e) {
+            e.printStackTrace(GT_Log.err);
+        }
+        GT_Log.out.println("GT_Mod: Finished Block Icon Load Phase");
+        GT_FML_LOGGER.info("GT_Mod: Finished Block Icon Load Phase");
     }
 
-    public float getBlockHardness(World aWorld, int aX, int aY, int aZ) {
-        return super.getBlockHardness(aWorld, aX, aY, aZ);
-    }
-
+    @Override
     public float getPlayerRelativeBlockHardness(EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if (((tTileEntity instanceof BaseMetaTileEntity)) && (((BaseMetaTileEntity) tTileEntity).privateAccess()) && (!((BaseMetaTileEntity) tTileEntity).playerOwnsThis(aPlayer, true))) {
-            return -1.0F;
-        }
-        return super.getPlayerRelativeBlockHardness(aPlayer, aWorld, aX, aY, aZ);
+        return tTileEntity instanceof BaseMetaTileEntity &&
+                ((BaseMetaTileEntity) tTileEntity).privateAccess() &&
+                !((BaseMetaTileEntity) tTileEntity).playerOwnsThis(aPlayer, true) ?
+                -1.0F : super.getPlayerRelativeBlockHardness(aPlayer, aWorld, aX, aY, aZ);
     }
 
-    public boolean onBlockActivated(World aWorld, int aX, int aY, int aZ, EntityPlayer aPlayer, int aSide, float par1, float par2, float par3) {
+    @Override
+    public boolean onBlockActivated(
+            World aWorld, int aX, int aY, int aZ, EntityPlayer aPlayer, int aSide, float par1, float par2, float par3) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
         if (tTileEntity == null) {
             return false;
         }
-        if(aPlayer.isSneaking()){
-        	ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem();
-        	if(tCurrentItem!=null){
-        		if(!GT_Utility.isStackInList(tCurrentItem, GregTech_API.sScrewdriverList) && !GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWrenchList) && !GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWireCutterList) && !GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSolderingToolList)){
-        			return false;
-        		}
-        	}
+        if (aPlayer.isSneaking()) {
+            ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem();
+            if (
+                    tCurrentItem != null &&
+                    !GT_Utility.isStackInList(tCurrentItem, GregTech_API.sScrewdriverList) &&
+                    !GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWrenchList) &&
+                    !GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWireCutterList) &&
+                    !GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSolderingToolList)
+            ) return false;
         }
         if ((tTileEntity instanceof IGregTechTileEntity)) {
             if (((IGregTechTileEntity) tTileEntity).getTimer() < 50L) {
                 return false;
             }
-            if ((!aWorld.isRemote) && (!((IGregTechTileEntity) tTileEntity).isUseableByPlayer(aPlayer))) {
+            if ((!aWorld.isRemote) && !((IGregTechTileEntity) tTileEntity).isUseableByPlayer(aPlayer)) {
                 return true;
             }
             return ((IGregTechTileEntity) tTileEntity).onRightclick(aPlayer, (byte) aSide, par1, par2, par3);
@@ -307,46 +361,55 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo
         return false;
     }
 
+    @Override
     public void onBlockClicked(World aWorld, int aX, int aY, int aZ, EntityPlayer aPlayer) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if (((tTileEntity instanceof IGregTechTileEntity))) {
+        if (tTileEntity instanceof IGregTechTileEntity) {
             ((IGregTechTileEntity) tTileEntity).onLeftclick(aPlayer);
         }
     }
 
+    @Override
     public int getDamageValue(World aWorld, int aX, int aY, int aZ) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if ((tTileEntity instanceof IGregTechTileEntity)) {
+        if (tTileEntity instanceof IGregTechTileEntity) {
             return ((IGregTechTileEntity) tTileEntity).getMetaTileID();
         }
         return 0;
     }
 
+    @Override
     public void onBlockExploded(World aWorld, int aX, int aY, int aZ, Explosion aExplosion) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if ((tTileEntity instanceof BaseMetaTileEntity)) {
-            GT_Log.exp.println("Explosion at :"+aX + " | " + aY+ " | "  + aZ +" DIMID: " + aWorld.provider.dimensionId+ " due to near explosion!");
+        if (tTileEntity instanceof BaseMetaTileEntity) {
+            GT_Log.exp.printf("Explosion at : %d | %d | %d DIMID: %s due to near explosion!%n",
+                    aX, aY, aZ, aWorld.provider.dimensionId);
             ((BaseMetaTileEntity) tTileEntity).doEnergyExplosion();
         }
         super.onBlockExploded(aWorld, aX, aY, aZ, aExplosion);
     }
 
+    @Override
     public void breakBlock(World aWorld, int aX, int aY, int aZ, Block par5, int par6) {
         GregTech_API.causeMachineUpdate(aWorld, aX, aY, aZ);
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if ((tTileEntity instanceof IGregTechTileEntity)) {
+        if (tTileEntity instanceof IGregTechTileEntity) {
             IGregTechTileEntity tGregTechTileEntity = (IGregTechTileEntity) tTileEntity;
             mTemporaryTileEntity.set(tGregTechTileEntity);
             for (int i = 0; i < tGregTechTileEntity.getSizeInventory(); i++) {
                 ItemStack tItem = tGregTechTileEntity.getStackInSlot(i);
                 if ((tItem != null) && (tItem.stackSize > 0) && (tGregTechTileEntity.isValidSlot(i))) {
-                    EntityItem tItemEntity = new EntityItem(aWorld, aX + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F, aY + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F, aZ + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F, new ItemStack(tItem.getItem(), tItem.stackSize, tItem.getItemDamage()));
+                    EntityItem tItemEntity = new EntityItem(aWorld,
+                            aX + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
+                            aY + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
+                            aZ + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
+                            new ItemStack(tItem.getItem(), tItem.stackSize, tItem.getItemDamage()));
                     if (tItem.hasTagCompound()) {
                         tItemEntity.getEntityItem().setTagCompound((NBTTagCompound) tItem.getTagCompound().copy());
                     }
-                    tItemEntity.motionX = (XSTR_INSTANCE.nextGaussian() * 0.0500000007450581D);
-                    tItemEntity.motionY = (XSTR_INSTANCE.nextGaussian() * 0.0500000007450581D + 0.2000000029802322D);
-                    tItemEntity.motionZ = (XSTR_INSTANCE.nextGaussian() * 0.0500000007450581D);
+                    tItemEntity.motionX = (XSTR_INSTANCE.nextGaussian() * 0.05D);
+                    tItemEntity.motionY = (XSTR_INSTANCE.nextGaussian() * 0.25D);
+                    tItemEntity.motionZ = (XSTR_INSTANCE.nextGaussian() * 0.05D);
                     aWorld.spawnEntityInWorld(tItemEntity);
                     tItem.stackSize = 0;
                     tGregTechTileEntity.setInventorySlotContents(i, null);
@@ -357,65 +420,76 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo
         aWorld.removeTileEntity(aX, aY, aZ);
     }
 
+    @Override
     public ArrayList<ItemStack> getDrops(World aWorld, int aX, int aY, int aZ, int aMeta, int aFortune) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
         if ((tTileEntity instanceof IGregTechTileEntity)) {
             return ((IGregTechTileEntity) tTileEntity).getDrops();
         }
-        return mTemporaryTileEntity.get() == null ? new ArrayList() : ((IGregTechTileEntity) mTemporaryTileEntity.get()).getDrops();
+        IGregTechTileEntity tGregTechTileEntity = mTemporaryTileEntity.get();
+        ArrayList<ItemStack> tDrops;
+        if (tGregTechTileEntity == null) {
+            tDrops = (ArrayList<ItemStack>) Collections.<ItemStack>emptyList();
+        } else {
+            tDrops = tGregTechTileEntity.getDrops();
+            mTemporaryTileEntity.remove();
+        }
+        return tDrops;
     }
+
     @Override
     public boolean removedByPlayer(World aWorld, EntityPlayer aPlayer, int aX, int aY, int aZ, boolean aWillHarvest) {
-        if (aWillHarvest) {
-            return true; // This delays deletion of the block until after getDrops
-        } else {
-            return super.removedByPlayer(aWorld, aPlayer, aX, aY, aZ, false);
-        }
+        // This delays deletion of the block until after getDrops
+        return aWillHarvest || super.removedByPlayer(aWorld, aPlayer, aX, aY, aZ, false);
     }
 
     @Override
-    public void harvestBlock(World aWorld, EntityPlayer aPlayer, int aX, int aY, int aZ, int aMeta)
-    {
+    public void harvestBlock(World aWorld, EntityPlayer aPlayer, int aX, int aY, int aZ, int aMeta) {
         super.harvestBlock(aWorld, aPlayer, aX, aY, aZ, aMeta);
         aWorld.setBlockToAir(aX, aY, aZ);
     }
-    
+
+    @Override
     public int getComparatorInputOverride(World aWorld, int aX, int aY, int aZ, int aSide) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if (((tTileEntity instanceof IGregTechTileEntity))) {
+        if (tTileEntity instanceof IGregTechTileEntity) {
             return ((IGregTechTileEntity) tTileEntity).getComparatorValue((byte) aSide);
         }
         return 0;
     }
 
+    @Override
     public int isProvidingWeakPower(IBlockAccess aWorld, int aX, int aY, int aZ, int aSide) {
-        if ((aSide < 0) || (aSide > 5)) {
+        if (aSide < 0 || aSide > 5) {
             return 0;
         }
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if (((tTileEntity instanceof IGregTechTileEntity))) {
+        if (tTileEntity instanceof IGregTechTileEntity) {
             return ((IGregTechTileEntity) tTileEntity).getOutputRedstoneSignal(GT_Utility.getOppositeSide(aSide));
         }
         return 0;
     }
 
+    @Override
     public int isProvidingStrongPower(IBlockAccess aWorld, int aX, int aY, int aZ, int aSide) {
-        if ((aSide < 0) || (aSide > 5)) {
+        if (aSide < 0 || aSide > 5) {
             return 0;
         }
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if (((tTileEntity instanceof IGregTechTileEntity))) {
+        if (tTileEntity instanceof IGregTechTileEntity) {
             return ((IGregTechTileEntity) tTileEntity).getStrongOutputRedstoneSignal(GT_Utility.getOppositeSide(aSide));
         }
         return 0;
     }
 
+    @Override
     public void dropBlockAsItemWithChance(World aWorld, int aX, int aY, int aZ, int par5, float chance, int par7) {
         if (!aWorld.isRemote) {
             TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-            if ((tTileEntity != null) && (chance < 1.0F)) {
-                if (((tTileEntity instanceof BaseMetaTileEntity)) && (GregTech_API.sMachineNonWrenchExplosions)) {
-                    GT_Log.exp.println("Explosion at :"+aX + " | " + aY+ " | "  + aZ +" DIMID: "+ aWorld.provider.dimensionId+ " due to NonWrench picking/Rain!");
+            if (tTileEntity != null && (chance < 1.0F)) {
+                if (tTileEntity instanceof BaseMetaTileEntity && (GregTech_API.sMachineNonWrenchExplosions)) {
+                    GT_Log.exp.printf("Explosion at : %d | %d | %d DIMID: %s NonWrench picking/Rain!%n",
+                            aX, aY, aZ, aWorld.provider.dimensionId);
                     ((BaseMetaTileEntity) tTileEntity).doEnergyExplosion();
                 }
             } else {
@@ -424,44 +498,60 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo
         }
     }
 
+    @Override
     public boolean isSideSolid(IBlockAccess aWorld, int aX, int aY, int aZ, ForgeDirection aSide) {
         if (aWorld.getBlockMetadata(aX, aY, aZ) == 0) {
             return true;
         }
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
         if (tTileEntity != null) {
-            if ((tTileEntity instanceof BaseMetaTileEntity)) {
-                return true;
-            }
-            if (((tTileEntity instanceof BaseMetaPipeEntity)) && ((((BaseMetaPipeEntity) tTileEntity).mConnections & 0xFFFFFFC0) != 0)) {
+            if (tTileEntity instanceof BaseMetaTileEntity) {
                 return true;
             }
-            if (((tTileEntity instanceof ICoverable)) && (((ICoverable) tTileEntity).getCoverIDAtSide((byte) aSide.ordinal()) != 0)) {
+            if (tTileEntity instanceof BaseMetaPipeEntity &&
+                    (((BaseMetaPipeEntity) tTileEntity).mConnections & 0xFFFFFFC0) != 0) {
                 return true;
             }
+            return tTileEntity instanceof ICoverable &&
+                    ((ICoverable) tTileEntity).getCoverIDAtSide((byte) aSide.ordinal()) != 0;
         }
         return false;
     }
 
+    @Override
+    public boolean isBlockNormalCube() {
+        return true;
+    }
+
+    /**
+     * Returns the default ambient occlusion value based on block opacity
+     */
+    @SideOnly(Side.CLIENT)
+    @Override
+    public float getAmbientOcclusionLightValue()
+    {
+        return this.renderAsNormalBlock() ? 0.2F : 0.5F;
+    }
+
+    @Override
     public int getLightOpacity(IBlockAccess aWorld, int aX, int aY, int aZ) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if (tTileEntity == null) {
-            return 0;
-        }
-        if ((tTileEntity instanceof IGregTechTileEntity)) {
+        if (tTileEntity instanceof IGregTechTileEntity) {
             return ((IGregTechTileEntity) tTileEntity).getLightOpacity();
         }
         return aWorld.getBlockMetadata(aX, aY, aZ) == 0 ? 255 : 0;
     }
 
+    @Override
     public int getLightValue(IBlockAccess aWorld, int aX, int aY, int aZ) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if ((tTileEntity instanceof BaseMetaTileEntity)) {
+        if (tTileEntity instanceof BaseMetaTileEntity) {
             return ((BaseMetaTileEntity) tTileEntity).getLightValue();
         }
         return 0;
     }
 
+    @Override
     public TileEntity createTileEntity(World aWorld, int aMeta) {
         if (aMeta < 4) {
             return GregTech_API.constructBaseMetaTileEntity();
@@ -469,76 +559,87 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo
         return new BaseMetaPipeEntity();
     }
 
-    public float getExplosionResistance(Entity par1Entity, World aWorld, int aX, int aY, int aZ, double explosionX, double explosionY, double explosionZ) {
+    @Override
+    public float getExplosionResistance(
+            Entity par1Entity, World aWorld, int aX, int aY, int aZ,
+            double explosionX, double explosionY, double explosionZ) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if (((tTileEntity instanceof IGregTechTileEntity))) {
+        if (tTileEntity instanceof IGregTechTileEntity) {
             return ((IGregTechTileEntity) tTileEntity).getBlastResistance((byte) 6);
         }
         return 10.0F;
     }
 
     @SideOnly(Side.CLIENT)
-    public void getSubBlocks(Item par1, CreativeTabs par2CreativeTabs, List par3List) {
+    @Override
+    @SuppressWarnings("unchecked") // Old API uses raw List type
+    public void getSubBlocks(Item par1Item, CreativeTabs par2CreativeTabs, List par3List) {
         for (int i = 1; i < GregTech_API.METATILEENTITIES.length; i++) {
             if (GregTech_API.METATILEENTITIES[i] != null) {
-                par3List.add(new ItemStack(par1, 1, i));
+                par3List.add(new ItemStack(par1Item, 1, i));
             }
         }
     }
 
+    @Override
     public void onBlockPlacedBy(World aWorld, int aX, int aY, int aZ, EntityLivingBase aPlayer, ItemStack aStack) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if (tTileEntity == null) {
+        if (!(tTileEntity instanceof IGregTechTileEntity)) {
             return;
         }
-        if ((tTileEntity instanceof IGregTechTileEntity)) {
-            IGregTechTileEntity var6 = (IGregTechTileEntity) tTileEntity;
-            if (aPlayer == null) {
-                var6.setFrontFacing((byte) 1);
-            } else {
-                int var7 = MathHelper.floor_double(aPlayer.rotationYaw * 4.0F / 360.0F + 0.5D) & 0x3;
-                int var8 = Math.round(aPlayer.rotationPitch);
-                if ((var8 >= 65) && (var6.isValidFacing((byte) 1))) {
-                    var6.setFrontFacing((byte) 1);
-                } else if ((var8 <= -65) && (var6.isValidFacing((byte) 0))) {
-                    var6.setFrontFacing((byte) 0);
-                } else {
-                    switch (var7) {
-                        case 0:
-                            var6.setFrontFacing((byte) 2);
-                            break;
-                        case 1:
-                            var6.setFrontFacing((byte) 5);
-                            break;
-                        case 2:
-                            var6.setFrontFacing((byte) 3);
-                            break;
-                        case 3:
-                            var6.setFrontFacing((byte) 4);
-                    }
-                }
-            }
+        IGregTechTileEntity iGregTechTileEntity = (IGregTechTileEntity) tTileEntity;
+        if (aPlayer == null) {
+            iGregTechTileEntity.setFrontFacing((byte) ForgeDirection.UP.ordinal());
+            return;
+        }
+        int yawQuadrant = MathHelper.floor_double(aPlayer.rotationYaw * 4.0F / 360.0F + 0.5D) & 0x3;
+        int pitch = Math.round(aPlayer.rotationPitch);
+        if (pitch >= 65 && iGregTechTileEntity.isValidFacing((byte) ForgeDirection.UP.ordinal())) {
+            iGregTechTileEntity.setFrontFacing((byte) ForgeDirection.UP.ordinal());
+            return;
+        }
+        if (pitch <= -65 && iGregTechTileEntity.isValidFacing((byte) ForgeDirection.DOWN.ordinal())) {
+            iGregTechTileEntity.setFrontFacing((byte) ForgeDirection.DOWN.ordinal());
+            return;
+        }
+        switch (yawQuadrant) {
+            case 0:
+                iGregTechTileEntity.setFrontFacing((byte) ForgeDirection.NORTH.ordinal());
+                break;
+            case 1:
+                iGregTechTileEntity.setFrontFacing((byte) ForgeDirection.EAST.ordinal());
+                break;
+            case 2:
+                iGregTechTileEntity.setFrontFacing((byte) ForgeDirection.SOUTH.ordinal());
+                break;
+            case 3:
+                iGregTechTileEntity.setFrontFacing((byte) ForgeDirection.WEST.ordinal());
+                break;
+            default:
+                break;
         }
     }
 
-    public ArrayList<String> getDebugInfo(EntityPlayer aPlayer, int aX, int aY, int aZ, int aLogLevel) {
+    @Override
+        public ArrayList<String> getDebugInfo(EntityPlayer aPlayer, int aX, int aY, int aZ, int aLogLevel) {
         TileEntity tTileEntity = aPlayer.worldObj.getTileEntity(aX, aY, aZ);
-        if ((tTileEntity instanceof BaseMetaTileEntity)) {
+        if (tTileEntity instanceof BaseMetaTileEntity) {
             return ((BaseMetaTileEntity) tTileEntity).getDebugInfo(aPlayer, aLogLevel);
         }
-        if ((tTileEntity instanceof BaseMetaPipeEntity)) {
+        if (tTileEntity instanceof BaseMetaPipeEntity) {
             return ((BaseMetaPipeEntity) tTileEntity).getDebugInfo(aPlayer, aLogLevel);
         }
-        return null;
+        return (ArrayList<String>) Collections.<String>emptyList();
     }
 
+    @Override
     public boolean recolourBlock(World aWorld, int aX, int aY, int aZ, ForgeDirection aSide, int aColor) {
         TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if ((tTileEntity instanceof IGregTechTileEntity)) {
-            if (((IGregTechTileEntity) tTileEntity).getColorization() == (byte) ((aColor ^ 0xFFFFFFFF) & 0xF)) {
+        if (tTileEntity instanceof IGregTechTileEntity) {
+            if (((IGregTechTileEntity) tTileEntity).getColorization() == (byte) ((~aColor) & 0xF)) {
                 return false;
             }
-            ((IGregTechTileEntity) tTileEntity).setColorization((byte) ((aColor ^ 0xFFFFFFFF) & 0xF));
+            ((IGregTechTileEntity) tTileEntity).setColorization((byte) ((~aColor) & 0xF));
             return true;
         }
         return false;
diff --git a/src/main/java/gregtech/common/blocks/GT_Material_Machines.java b/src/main/java/gregtech/common/blocks/GT_Material_Machines.java
index 8de7421dc4..b9a78f02b3 100644
--- a/src/main/java/gregtech/common/blocks/GT_Material_Machines.java
+++ b/src/main/java/gregtech/common/blocks/GT_Material_Machines.java
@@ -12,6 +12,6 @@ public class GT_Material_Machines extends Material {
     }
 
     public boolean isOpaque() {
-        return false;
+        return true;
     }
 }
-- 
cgit 


From e6f726c7fa14413b8f57c2a7e2583cfd486fb8d1 Mon Sep 17 00:00:00 2001
From: Léa Gris <lea.gris@noiraude.net>
Date: Tue, 23 Mar 2021 15:11:36 +0100
Subject: fix(rendering): brightness of no-z-fighting offset faces

Ignore the z-fighting offset when detecting if a face uses the block's brightness
or the brightness from the block above.
---
 src/main/java/gregtech/api/util/LightingHelper.java       | 15 ++++++++-------
 .../java/gregtech/common/render/GT_Renderer_Block.java    | 15 ++++++++-------
 2 files changed, 16 insertions(+), 14 deletions(-)

(limited to 'src/main/java/gregtech/api/util/LightingHelper.java')

diff --git a/src/main/java/gregtech/api/util/LightingHelper.java b/src/main/java/gregtech/api/util/LightingHelper.java
index df70ffaeef..027fcd9c6d 100644
--- a/src/main/java/gregtech/api/util/LightingHelper.java
+++ b/src/main/java/gregtech/api/util/LightingHelper.java
@@ -31,6 +31,7 @@ import net.minecraft.client.renderer.Tessellator;
 public class LightingHelper {
     public static final int NORMAL_BRIGHTNESS = 0xff00ff;
     public static final int MAX_BRIGHTNESS = 0xf000f0;
+    public static final float NO_Z_FIGHT_OFFSET = 1.0F / 16384.0F;
     protected static final float[] LIGHTNESS = {0.5F, 1.0F, 0.8F, 0.8F, 0.6F, 0.6F};
     private final RenderBlocks renderBlocks;
     /**
@@ -321,7 +322,7 @@ public class LightingHelper {
 
         if (renderBlocks.enableAO) {
 
-            int xOffset = renderBlocks.renderMinX > 0.0F ? x : x - 1;
+            int xOffset = renderBlocks.renderMinX > 0.0F + NO_Z_FIGHT_OFFSET ? x : x - 1;
 
             int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y, z);
             brightness = mixedBrightness;
@@ -392,7 +393,7 @@ public class LightingHelper {
 
         if (renderBlocks.enableAO) {
 
-            int xOffset = renderBlocks.renderMaxX < 1.0F ? x : x + 1;
+            int xOffset = renderBlocks.renderMaxX < 1.0F - NO_Z_FIGHT_OFFSET ? x : x + 1;
 
             int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, xOffset, y, z);
             brightness = mixedBrightness;
@@ -462,7 +463,7 @@ public class LightingHelper {
 
         if (renderBlocks.enableAO) {
 
-            int yOffset = renderBlocks.renderMinY > 0.0F ? y : y - 1;
+            int yOffset = renderBlocks.renderMinY > 0.0F + NO_Z_FIGHT_OFFSET ? y : y - 1;
 
             int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, yOffset, z);
             brightness = mixedBrightness;
@@ -497,7 +498,7 @@ public class LightingHelper {
             float aoMixedXYZNNN = (renderBlocks.aoLightValueScratchXYNN + renderBlocks.aoLightValueScratchXYZNNN + aoLightValue + renderBlocks.aoLightValueScratchYZNN) / 4.0F;
             float aoMixedXYZNNP = (renderBlocks.aoLightValueScratchXYZNNP + renderBlocks.aoLightValueScratchXYNN + renderBlocks.aoLightValueScratchYZNP + aoLightValue) / 4.0F;
 
-            aoTopLeft  = (float) (aoMixedXYZNNP * renderBlocks.renderMaxZ * (1.0D - renderBlocks.renderMinX) + aoMixedXYZPNP * renderBlocks.renderMaxZ * renderBlocks.renderMinX + aoMixedXYZPNN * (1.0D - renderBlocks.renderMaxZ) * renderBlocks.renderMinX + aoMixedXYZNNN * (1.0D - renderBlocks.renderMaxZ) * (1.0D - renderBlocks.renderMinX));
+            aoTopLeft = (float) (aoMixedXYZNNP * renderBlocks.renderMaxZ * (1.0D - renderBlocks.renderMinX) + aoMixedXYZPNP * renderBlocks.renderMaxZ * renderBlocks.renderMinX + aoMixedXYZPNN * (1.0D - renderBlocks.renderMaxZ) * renderBlocks.renderMinX + aoMixedXYZNNN * (1.0D - renderBlocks.renderMaxZ) * (1.0D - renderBlocks.renderMinX));
             aoBottomLeft = (float) (aoMixedXYZNNP * renderBlocks.renderMinZ * (1.0D - renderBlocks.renderMinX) + aoMixedXYZPNP * renderBlocks.renderMinZ * renderBlocks.renderMinX + aoMixedXYZPNN * (1.0D - renderBlocks.renderMinZ) * renderBlocks.renderMinX + aoMixedXYZNNN * (1.0D - renderBlocks.renderMinZ) * (1.0D - renderBlocks.renderMinX));
             aoBottomRight = (float) (aoMixedXYZNNP * renderBlocks.renderMinZ * (1.0D - renderBlocks.renderMaxX) + aoMixedXYZPNP * renderBlocks.renderMinZ * renderBlocks.renderMaxX + aoMixedXYZPNN * (1.0D - renderBlocks.renderMinZ) * renderBlocks.renderMaxX + aoMixedXYZNNN * (1.0D - renderBlocks.renderMinZ) * (1.0D - renderBlocks.renderMaxX));
             aoTopRight = (float) (aoMixedXYZNNP * renderBlocks.renderMaxZ * (1.0D - renderBlocks.renderMaxX) + aoMixedXYZPNP * renderBlocks.renderMaxZ * renderBlocks.renderMaxX + aoMixedXYZPNN * (1.0D - renderBlocks.renderMaxZ) * renderBlocks.renderMaxX + aoMixedXYZNNN * (1.0D - renderBlocks.renderMaxZ) * (1.0D - renderBlocks.renderMaxX));
@@ -533,7 +534,7 @@ public class LightingHelper {
 
         if (renderBlocks.enableAO) {
 
-            int yOffset = renderBlocks.renderMaxY < 1.0F ? y : y + 1;
+            int yOffset = renderBlocks.renderMaxY < 1.0F - NO_Z_FIGHT_OFFSET ? y : y + 1;
 
             int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, yOffset, z);
             brightness = mixedBrightness;
@@ -602,7 +603,7 @@ public class LightingHelper {
 
         if (renderBlocks.enableAO) {
 
-            int zOffset = renderBlocks.renderMinZ > 0.0F ? z : z - 1;
+            int zOffset = renderBlocks.renderMinZ > 0.0F + NO_Z_FIGHT_OFFSET ? z : z - 1;
 
             int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, y, zOffset);
             brightness = mixedBrightness;
@@ -673,7 +674,7 @@ public class LightingHelper {
 
         if (renderBlocks.enableAO) {
 
-            int zOffset = renderBlocks.renderMaxZ < 1.0F ? z : z + 1;
+            int zOffset = renderBlocks.renderMaxZ < 1.0F - NO_Z_FIGHT_OFFSET ? z : z + 1;
 
             int mixedBrightness = block.getMixedBrightnessForBlock(renderBlocks.blockAccess, x, y, zOffset);
             brightness = mixedBrightness;
diff --git a/src/main/java/gregtech/common/render/GT_Renderer_Block.java b/src/main/java/gregtech/common/render/GT_Renderer_Block.java
index e95f508d80..2f33a80dca 100644
--- a/src/main/java/gregtech/common/render/GT_Renderer_Block.java
+++ b/src/main/java/gregtech/common/render/GT_Renderer_Block.java
@@ -20,8 +20,9 @@ import net.minecraft.tileentity.TileEntity;
 import net.minecraft.world.IBlockAccess;
 import org.lwjgl.opengl.GL11;
 
+import static gregtech.api.util.LightingHelper.NO_Z_FIGHT_OFFSET;
+
 public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
-    private static final float NoZFightOffset = 1.0F / 16384.0F;
     public static GT_Renderer_Block INSTANCE;
     public final int mRenderID;
 
@@ -305,7 +306,7 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
             renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[3], false);
         }
         if (tIsCovered[0]) {
-            aBlock.setBlockBounds(0.0F, 0.0F + NoZFightOffset, 0.0F, 1.0F, 0.125F, 1.0F);
+            aBlock.setBlockBounds(0.0F, 0.0F + NO_Z_FIGHT_OFFSET, 0.0F, 1.0F, 0.125F, 1.0F);
             aRenderer.setRenderBoundsFromBlock(aBlock);
             renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[0], false);
             renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[0], false);
@@ -323,7 +324,7 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
             }
         }
         if (tIsCovered[1]) {
-            aBlock.setBlockBounds(0.0F, 0.875F, 0.0F, 1.0F, 1.0F - NoZFightOffset, 1.0F);
+            aBlock.setBlockBounds(0.0F, 0.875F, 0.0F, 1.0F, 1.0F - NO_Z_FIGHT_OFFSET, 1.0F);
             aRenderer.setRenderBoundsFromBlock(aBlock);
             renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[1], false);
             renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[1], false);
@@ -341,7 +342,7 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
             }
         }
         if (tIsCovered[2]) {
-            aBlock.setBlockBounds(0.0F, 0.0F, 0.0F + NoZFightOffset, 1.0F, 1.0F, 0.125F);
+            aBlock.setBlockBounds(0.0F, 0.0F, 0.0F + NO_Z_FIGHT_OFFSET, 1.0F, 1.0F, 0.125F);
             aRenderer.setRenderBoundsFromBlock(aBlock);
             if (!tIsCovered[0]) {
                 renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[2], false);
@@ -359,7 +360,7 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
             }
         }
         if (tIsCovered[3]) {
-            aBlock.setBlockBounds(0.0F, 0.0F, 0.875F, 1.0F, 1.0F, 1.0F - NoZFightOffset);
+            aBlock.setBlockBounds(0.0F, 0.0F, 0.875F, 1.0F, 1.0F, 1.0F - NO_Z_FIGHT_OFFSET);
             aRenderer.setRenderBoundsFromBlock(aBlock);
             if (!tIsCovered[0]) {
                 renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[3], false);
@@ -377,7 +378,7 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
             }
         }
         if (tIsCovered[4]) {
-            aBlock.setBlockBounds(0.0F + NoZFightOffset, 0.0F, 0.0F, 0.125F, 1.0F, 1.0F);
+            aBlock.setBlockBounds(0.0F + NO_Z_FIGHT_OFFSET, 0.0F, 0.0F, 0.125F, 1.0F, 1.0F);
             aRenderer.setRenderBoundsFromBlock(aBlock);
             if (!tIsCovered[0]) {
                 renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[4], false);
@@ -395,7 +396,7 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
             renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[4], false);
         }
         if (tIsCovered[5]) {
-            aBlock.setBlockBounds(0.875F, 0.0F, 0.0F, 1.0F - NoZFightOffset, 1.0F, 1.0F);
+            aBlock.setBlockBounds(0.875F, 0.0F, 0.0F, 1.0F - NO_Z_FIGHT_OFFSET, 1.0F, 1.0F);
             aRenderer.setRenderBoundsFromBlock(aBlock);
             if (!tIsCovered[0]) {
                 renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[5], false);
-- 
cgit 


From 4fb771c07cefad013da8588db27a46ed0311e367 Mon Sep 17 00:00:00 2001
From: Léa Gris <lea.gris@noiraude.net>
Date: Sun, 4 Apr 2021 22:01:11 +0200
Subject: fix(rendering): multiple rendering fixes and refactor (#494)

* fix(rendering): multiple rendering fixes and refactor

- Fix rendering gregtech machines in inventory with correct orientation and lighting.
- Fix rendering of pipes connected through covers, no longer z-fight at a distance.
- Fix updating of textures when un/holding a soldering-iron.
- Refactor of the GT_Renderer_Block class with properly named constants replacing raw literals.
---
 .../interfaces/metatileentity/IConnectable.java    |  12 +
 .../tileentity/IPipeRenderedTileEntity.java        |   3 +-
 .../api/metatileentity/BaseMetaPipeEntity.java     |  30 +-
 .../api/metatileentity/MetaPipeEntity.java         |  13 +-
 .../api/metatileentity/MetaTileEntity.java         |  25 +-
 .../implementations/GT_MetaPipeEntity_Cable.java   |   2 +-
 .../implementations/GT_MetaPipeEntity_Fluid.java   |   2 +-
 .../implementations/GT_MetaPipeEntity_Item.java    |   2 +-
 .../java/gregtech/api/util/LightingHelper.java     |   2 +-
 src/main/java/gregtech/common/GT_Client.java       |   5 +
 .../gregtech/common/render/GT_Renderer_Block.java  | 864 ++++++++++++---------
 11 files changed, 558 insertions(+), 402 deletions(-)

(limited to 'src/main/java/gregtech/api/util/LightingHelper.java')

diff --git a/src/main/java/gregtech/api/interfaces/metatileentity/IConnectable.java b/src/main/java/gregtech/api/interfaces/metatileentity/IConnectable.java
index bc822250fd..cffcb4c4ab 100644
--- a/src/main/java/gregtech/api/interfaces/metatileentity/IConnectable.java
+++ b/src/main/java/gregtech/api/interfaces/metatileentity/IConnectable.java
@@ -4,6 +4,18 @@ package gregtech.api.interfaces.metatileentity;
  * For pipes, wires, and other MetaTiles which need to be decided whether they should connect to the block at each side.
  */
 public interface IConnectable {
+    int NO_CONNECTION    = 0b00000000;
+    int CONNECTED_DOWN   = 0b00000001;
+    int CONNECTED_UP     = 0b00000010;
+    int CONNECTED_NORTH  = 0b00000100;
+    int CONNECTED_SOUTH  = 0b00001000;
+    int CONNECTED_WEST   = 0b00010000;
+    int CONNECTED_EAST   = 0b00100000;
+    int CONNECTED_ALL    = 0b00111111;
+    int HAS_FRESHFOAM    = 0b01000000;
+    int HAS_HARDENEDFOAM = 0b10000000;
+    int HAS_FOAM         = 0b11000000;
+
     /**
      * Try to connect to the Block at the specified side
      * returns the connection state. Non-positive values for failed, others for succeeded.
diff --git a/src/main/java/gregtech/api/interfaces/tileentity/IPipeRenderedTileEntity.java b/src/main/java/gregtech/api/interfaces/tileentity/IPipeRenderedTileEntity.java
index 8392616f34..de3cf3ec99 100644
--- a/src/main/java/gregtech/api/interfaces/tileentity/IPipeRenderedTileEntity.java
+++ b/src/main/java/gregtech/api/interfaces/tileentity/IPipeRenderedTileEntity.java
@@ -1,7 +1,6 @@
 package gregtech.api.interfaces.tileentity;
 
 import gregtech.api.interfaces.ITexture;
-import net.minecraft.block.Block;
 
 public interface IPipeRenderedTileEntity extends ICoverable, ITexturedTileEntity {
     float getThickNess();
@@ -12,5 +11,5 @@ public interface IPipeRenderedTileEntity extends ICoverable, ITexturedTileEntity
 
     default ITexture[] getTextureCovered(byte aSide) {
         return getTextureUncovered(aSide);
-    };
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java b/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java
index 908dd88984..0fd8779244 100644
--- a/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java
+++ b/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java
@@ -13,12 +13,12 @@ import gregtech.api.GregTech_API;
 import gregtech.api.enums.Textures;
 import gregtech.api.enums.Textures.BlockIcons;
 import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IConnectable;
 import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
 import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
 import gregtech.api.interfaces.tileentity.IPipeRenderedTileEntity;
 import gregtech.api.net.GT_Packet_TileEntity;
 import gregtech.api.objects.GT_ItemStack;
-import gregtech.api.objects.GT_StdRenderedTexture;
 import gregtech.api.util.GT_CoverBehavior;
 import gregtech.api.util.GT_Log;
 import gregtech.api.util.GT_ModHandler;
@@ -52,7 +52,7 @@ import net.minecraftforge.fluids.IFluidHandler;
  */
 public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileEntity, IPipeRenderedTileEntity {
     private final GT_CoverBehavior[] mCoverBehaviors = new GT_CoverBehavior[]{GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior};
-    public byte mConnections = 0;
+    public byte mConnections = IConnectable.NO_CONNECTION;
     protected MetaPipeEntity mMetaTileEntity;
     private byte[] mSidedRedstone = new byte[]{0, 0, 0, 0, 0, 0};
     private int[] mCoverSides = new int[]{0, 0, 0, 0, 0, 0}, mCoverData = new int[]{0, 0, 0, 0, 0, 0}, mTimeStatistics = new int[GregTech_API.TICKS_FOR_LAG_AVERAGING];
@@ -262,9 +262,11 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE
                                         if (!hasValidMetaTileEntity()) return;
                                     }
                                 }
-                            mConnections = (byte) (mMetaTileEntity.mConnections | (mConnections & ~63));
-                            if ((mConnections & -64) == 64 && getRandomNumber(1000) == 0) {
-                                mConnections = (byte) ((mConnections & ~64) | -128);
+                            // Mask-out Connection direction bits to keep only Foam related connections
+                            mConnections = (byte) (mMetaTileEntity.mConnections | (mConnections & ~IConnectable.CONNECTED_ALL));
+                            // If foam not hardened, tries roll chance to harden
+                            if ((mConnections & IConnectable.HAS_FOAM) == IConnectable.HAS_FRESHFOAM && getRandomNumber(1000) == 0) {
+                                mConnections = (byte) ((mConnections & ~IConnectable.HAS_FRESHFOAM) | IConnectable.HAS_HARDENEDFOAM);
                             }
                         }
                     case 8:
@@ -807,15 +809,17 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE
 
     @Override
     public ITexture[] getTextureUncovered(byte aSide) {
-        if ((mConnections & 64) != 0) return Textures.BlockIcons.FRESHFOAM;
-        if ((mConnections & -128) != 0) return Textures.BlockIcons.HARDENEDFOAMS[mColor];
-        if ((mConnections & -64) != 0) return Textures.BlockIcons.ERROR_RENDERING;
+        if ((mConnections & IConnectable.HAS_FRESHFOAM) != 0) return Textures.BlockIcons.FRESHFOAM;
+        if ((mConnections & IConnectable.HAS_HARDENEDFOAM) != 0) return Textures.BlockIcons.HARDENEDFOAMS[mColor];
+        if ((mConnections & IConnectable.HAS_FOAM) != 0) return Textures.BlockIcons.ERROR_RENDERING;
         byte tConnections = mConnections;
-        if (tConnections == 1 || tConnections == 2) tConnections = 3;
-        else if (tConnections == 4 || tConnections == 8) tConnections = 12;
-        else if (tConnections == 16 || tConnections == 32) tConnections = 48;
+        if (tConnections == IConnectable.CONNECTED_WEST || tConnections == IConnectable.CONNECTED_EAST) tConnections = (byte) (IConnectable.CONNECTED_WEST | IConnectable.CONNECTED_EAST);
+        else if (tConnections == IConnectable.CONNECTED_DOWN || tConnections == IConnectable.CONNECTED_UP) tConnections = (byte) (IConnectable.CONNECTED_DOWN | IConnectable.CONNECTED_UP);
+        else if (tConnections == IConnectable.CONNECTED_NORTH || tConnections == IConnectable.CONNECTED_SOUTH) tConnections = (byte) (IConnectable.CONNECTED_NORTH | IConnectable.CONNECTED_SOUTH);
         if (hasValidMetaTileEntity())
-            return mMetaTileEntity.getTexture(this, aSide, tConnections, (byte) (mColor - 1), tConnections == 0 || (tConnections & (1 << aSide)) != 0, getOutputRedstoneSignal(aSide) > 0);
+            return mMetaTileEntity.getTexture(this, aSide, tConnections, (byte) (mColor - 1),
+                    tConnections == 0 || (tConnections & (1 << aSide)) != 0,
+                    getOutputRedstoneSignal(aSide) > 0);
         return Textures.BlockIcons.ERROR_RENDERING;
     }
 
@@ -1409,7 +1413,7 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE
 
     @Override
     public float getBlastResistance(byte aSide) {
-        return (mConnections & 192) != 0 ? 50.0F : 5.0F;
+        return (mConnections & IConnectable.HAS_FOAM) != 0 ? 50.0F : 5.0F;
     }
 
     @Override
diff --git a/src/main/java/gregtech/api/metatileentity/MetaPipeEntity.java b/src/main/java/gregtech/api/metatileentity/MetaPipeEntity.java
index 0716d84bd6..8fe4c93639 100644
--- a/src/main/java/gregtech/api/metatileentity/MetaPipeEntity.java
+++ b/src/main/java/gregtech/api/metatileentity/MetaPipeEntity.java
@@ -9,11 +9,12 @@ import gregtech.api.interfaces.tileentity.IColoredTileEntity;
 import gregtech.api.interfaces.tileentity.ICoverable;
 import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
 import gregtech.api.objects.GT_ItemStack;
-import gregtech.api.util.WorldSpawnedEventBuilder;
 import gregtech.api.util.GT_Config;
 import gregtech.api.util.GT_CoverBehavior;
 import gregtech.api.util.GT_LanguageManager;
 import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder;
+import gregtech.common.GT_Client;
 import net.minecraft.block.Block;
 import net.minecraft.client.renderer.RenderBlocks;
 import net.minecraft.client.renderer.texture.IIconRegister;
@@ -244,7 +245,15 @@ public abstract class MetaPipeEntity implements IMetaTileEntity, IConnectable {
     public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {/*Do nothing*/}
 
     @Override
-    public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {/*Do nothing*/}
+    public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+        if (aBaseMetaTileEntity.isClientSide() && GT_Client.changeDetected == 4) {
+            /* Client tick counter that is set to 5 on hiding pipes and covers.
+             * It triggers a texture update next client tick when reaching 4, with provision for 3 more update tasks,
+             * spreading client change detection related work and network traffic on different ticks, until it reaches 0.
+             */
+            aBaseMetaTileEntity.issueTextureUpdate();
+        }
+    }
 
     @Override
     public void inValidate() {/*Do nothing*/}
diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java
index c9d75dad1a..730ec264f3 100644
--- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java
+++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java
@@ -2,7 +2,6 @@ package gregtech.api.metatileentity;
 
 import appeng.api.util.AECableType;
 import appeng.me.helpers.AENetworkProxy;
-import appeng.me.helpers.IGridProxyable;
 import cpw.mods.fml.common.Optional;
 import cpw.mods.fml.relauncher.Side;
 import cpw.mods.fml.relauncher.SideOnly;
@@ -11,7 +10,12 @@ import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
 import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
 import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Cable;
 import gregtech.api.objects.GT_ItemStack;
-import gregtech.api.util.*;
+import gregtech.api.util.GT_Config;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.GT_Client;
 import net.minecraft.block.Block;
 import net.minecraft.client.renderer.RenderBlocks;
 import net.minecraft.client.renderer.texture.IIconRegister;
@@ -47,6 +51,7 @@ import static gregtech.api.enums.GT_Values.V;
  * Call the Constructor like the following example inside the Load Phase, to register it.
  * "new GT_MetaTileEntity_E_Furnace(54, "GT_E_Furnace", "Automatic E-Furnace");"
  */
+@SuppressWarnings("unused")
 public abstract class MetaTileEntity implements IMetaTileEntity {
     /**
      * Only assigned for the MetaTileEntity in the List! Also only used to get the localized Name for the ItemStack and for getInvName.
@@ -85,7 +90,7 @@ public abstract class MetaTileEntity implements IMetaTileEntity {
         } else {
             throw new IllegalArgumentException("MetaMachine-Slot Nr. " + aID + " is already occupied!");
         }
-        mName = aBasicName.replaceAll(" ", "_").toLowerCase(Locale.ENGLISH);
+        mName = aBasicName.replace(" ", "_").toLowerCase(Locale.ENGLISH);
         setBaseMetaTileEntity(GregTech_API.constructBaseMetaTileEntity());
         getBaseMetaTileEntity().setMetaTileID((short) aID);
         GT_LanguageManager.addStringLocalization("gt.blockmachines." + mName + ".name", aRegionalName);
@@ -175,7 +180,7 @@ public abstract class MetaTileEntity implements IMetaTileEntity {
         if(!aPlayer.isSneaking()) return false;
         byte tSide = GT_Utility.getOppositeSide(aWrenchingSide);
         TileEntity tTileEntity = getBaseMetaTileEntity().getTileEntityAtSide(aWrenchingSide);
-        if (tTileEntity != null && (tTileEntity instanceof IGregTechTileEntity) && (((IGregTechTileEntity) tTileEntity).getMetaTileEntity() instanceof GT_MetaPipeEntity_Cable)) {
+        if ((tTileEntity instanceof IGregTechTileEntity) && (((IGregTechTileEntity) tTileEntity).getMetaTileEntity() instanceof GT_MetaPipeEntity_Cable)) {
             // The tile entity we're facing is a cable, let's try to connect to it
             return ((IGregTechTileEntity) tTileEntity).getMetaTileEntity().onWireCutterRightClick(aWrenchingSide, tSide, aPlayer, aX, aY, aZ);
         }
@@ -187,7 +192,7 @@ public abstract class MetaTileEntity implements IMetaTileEntity {
         if(!aPlayer.isSneaking()) return false;
         byte tSide = GT_Utility.getOppositeSide(aWrenchingSide);
         TileEntity tTileEntity = getBaseMetaTileEntity().getTileEntityAtSide(aWrenchingSide);
-        if (tTileEntity != null && (tTileEntity instanceof IGregTechTileEntity) && (((IGregTechTileEntity) tTileEntity).getMetaTileEntity() instanceof GT_MetaPipeEntity_Cable)) {
+        if ((tTileEntity instanceof IGregTechTileEntity) && (((IGregTechTileEntity) tTileEntity).getMetaTileEntity() instanceof GT_MetaPipeEntity_Cable)) {
             // The tile entity we're facing is a cable, let's try to connect to it
             return ((IGregTechTileEntity) tTileEntity).getMetaTileEntity().onSolderingToolRightClick(aWrenchingSide, tSide, aPlayer, aX, aY, aZ);
         }
@@ -206,7 +211,15 @@ public abstract class MetaTileEntity implements IMetaTileEntity {
     public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {/*Do nothing*/}
 
     @Override
-    public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {/*Do nothing*/}
+    public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+        if (aBaseMetaTileEntity.isClientSide() && GT_Client.changeDetected == 4) {
+            /* Client tick counter that is set to 5 on hiding pipes and covers.
+             * It triggers a texture update next client tick when reaching 4, with provision for 3 more update tasks,
+             * spreading client change detection related work and network traffic on different ticks, until it reaches 0.
+             */
+            aBaseMetaTileEntity.issueTextureUpdate();
+        }
+    }
 
     @Override
     public void inValidate() {/*Do nothing*/}
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java
index 02d6752bdd..e69e13b67a 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java
@@ -358,7 +358,7 @@ public class GT_MetaPipeEntity_Cable extends MetaPipeEntity implements IMetaTile
                 mTransferredAmperageLast20 = 0;
                 if (!GT_Mod.gregtechproxy.gt6Cable || mCheckConnections) checkConnections();
             }
-        } else if(aBaseMetaTileEntity.isClientSide() && GT_Client.changeDetected==4) aBaseMetaTileEntity.issueTextureUpdate();
+        }
     }
 
     @Override
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Fluid.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Fluid.java
index e6c24ec4b1..8c88f0e3bd 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Fluid.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Fluid.java
@@ -256,7 +256,7 @@ public class GT_MetaPipeEntity_Fluid extends MetaPipeEntity {
 
             oLastReceivedFrom = mLastReceivedFrom;
 
-        } else if(aBaseMetaTileEntity.isClientSide() && GT_Client.changeDetected==4) aBaseMetaTileEntity.issueTextureUpdate();
+        }
     }
 
     private boolean checkEnvironment(int index, IGregTechTileEntity aBaseMetaTileEntity) {
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Item.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Item.java
index 6ed5a9edd0..64064875ab 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Item.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Item.java
@@ -181,7 +181,7 @@ public class GT_MetaPipeEntity_Item extends MetaPipeEntity implements IMetaTileE
 
             if (isInventoryEmpty()) mLastReceivedFrom = 6;
             oLastReceivedFrom = mLastReceivedFrom;
-        }else if(aBaseMetaTileEntity.isClientSide() && GT_Client.changeDetected==4) aBaseMetaTileEntity.issueTextureUpdate();
+        }
     }
 
     @Override
diff --git a/src/main/java/gregtech/api/util/LightingHelper.java b/src/main/java/gregtech/api/util/LightingHelper.java
index 027fcd9c6d..48c316d0cc 100644
--- a/src/main/java/gregtech/api/util/LightingHelper.java
+++ b/src/main/java/gregtech/api/util/LightingHelper.java
@@ -31,7 +31,7 @@ import net.minecraft.client.renderer.Tessellator;
 public class LightingHelper {
     public static final int NORMAL_BRIGHTNESS = 0xff00ff;
     public static final int MAX_BRIGHTNESS = 0xf000f0;
-    public static final float NO_Z_FIGHT_OFFSET = 1.0F / 16384.0F;
+    public static final float NO_Z_FIGHT_OFFSET = 1.0F / 1024.0F;
     protected static final float[] LIGHTNESS = {0.5F, 1.0F, 0.8F, 0.8F, 0.6F, 0.6F};
     private final RenderBlocks renderBlocks;
     /**
diff --git a/src/main/java/gregtech/common/GT_Client.java b/src/main/java/gregtech/common/GT_Client.java
index b820c3b53a..6ce360c017 100644
--- a/src/main/java/gregtech/common/GT_Client.java
+++ b/src/main/java/gregtech/common/GT_Client.java
@@ -649,6 +649,11 @@ public class GT_Client extends GT_Proxy
     }
 
     public static int hideValue=0;
+
+    /** <p>Client tick counter that is set to 5 on hiding pipes and covers.</p>
+     * <p>It triggers a texture update next client tick when reaching 4, with provision for 3 more update tasks,
+     * spreading client change detection related work and network traffic on different ticks, until it reaches 0.</p>
+     */
     public static int changeDetected=0;
 
     private static int shouldHeldItemHideThings() {
diff --git a/src/main/java/gregtech/common/render/GT_Renderer_Block.java b/src/main/java/gregtech/common/render/GT_Renderer_Block.java
index 2f33a80dca..51e0b8fd6f 100644
--- a/src/main/java/gregtech/common/render/GT_Renderer_Block.java
+++ b/src/main/java/gregtech/common/render/GT_Renderer_Block.java
@@ -20,9 +20,29 @@ import net.minecraft.tileentity.TileEntity;
 import net.minecraft.world.IBlockAccess;
 import org.lwjgl.opengl.GL11;
 
-import static gregtech.api.util.LightingHelper.NO_Z_FIGHT_OFFSET;
+import static gregtech.api.interfaces.metatileentity.IConnectable.CONNECTED_DOWN;
+import static gregtech.api.interfaces.metatileentity.IConnectable.CONNECTED_EAST;
+import static gregtech.api.interfaces.metatileentity.IConnectable.CONNECTED_NORTH;
+import static gregtech.api.interfaces.metatileentity.IConnectable.CONNECTED_SOUTH;
+import static gregtech.api.interfaces.metatileentity.IConnectable.CONNECTED_UP;
+import static gregtech.api.interfaces.metatileentity.IConnectable.CONNECTED_WEST;
+import static gregtech.api.interfaces.metatileentity.IConnectable.HAS_FRESHFOAM;
+import static gregtech.api.interfaces.metatileentity.IConnectable.HAS_HARDENEDFOAM;
+import static gregtech.api.interfaces.metatileentity.IConnectable.NO_CONNECTION;
+import static net.minecraftforge.common.util.ForgeDirection.DOWN;
+import static net.minecraftforge.common.util.ForgeDirection.EAST;
+import static net.minecraftforge.common.util.ForgeDirection.NORTH;
+import static net.minecraftforge.common.util.ForgeDirection.SOUTH;
+import static net.minecraftforge.common.util.ForgeDirection.UP;
+import static net.minecraftforge.common.util.ForgeDirection.VALID_DIRECTIONS;
+import static net.minecraftforge.common.util.ForgeDirection.WEST;
 
 public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
+    public static final float blockMin = 0.0F;
+    public static final float blockMax = 1.0F;
+    private static final float coverThickness = blockMax / 8.0F;
+    private static final float coverInnerMin = blockMin + coverThickness;
+    private static final float coverInnerMax = blockMax - coverThickness;
     public static GT_Renderer_Block INSTANCE;
     public final int mRenderID;
 
@@ -32,6 +52,453 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
         RenderingRegistry.registerBlockHandler(this);
     }
 
+    public static boolean renderStandardBlock(IBlockAccess aWorld, int aX, int aY, int aZ, Block aBlock, RenderBlocks aRenderer) {
+        TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+        if ((tTileEntity instanceof IPipeRenderedTileEntity)) {
+            return renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer, new ITexture[][]{
+                    ((IPipeRenderedTileEntity) tTileEntity).getTextureCovered((byte) DOWN.ordinal()),
+                    ((IPipeRenderedTileEntity) tTileEntity).getTextureCovered((byte) UP.ordinal()),
+                    ((IPipeRenderedTileEntity) tTileEntity).getTextureCovered((byte) NORTH.ordinal()),
+                    ((IPipeRenderedTileEntity) tTileEntity).getTextureCovered((byte) SOUTH.ordinal()),
+                    ((IPipeRenderedTileEntity) tTileEntity).getTextureCovered((byte) WEST.ordinal()),
+                    ((IPipeRenderedTileEntity) tTileEntity).getTextureCovered((byte) EAST.ordinal())});
+        }
+        if ((tTileEntity instanceof ITexturedTileEntity)) {
+            return renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer, new ITexture[][]{
+                    ((ITexturedTileEntity) tTileEntity).getTexture(aBlock, (byte) DOWN.ordinal()),
+                    ((ITexturedTileEntity) tTileEntity).getTexture(aBlock, (byte) UP.ordinal()),
+                    ((ITexturedTileEntity) tTileEntity).getTexture(aBlock, (byte) NORTH.ordinal()),
+                    ((ITexturedTileEntity) tTileEntity).getTexture(aBlock, (byte) SOUTH.ordinal()),
+                    ((ITexturedTileEntity) tTileEntity).getTexture(aBlock, (byte) WEST.ordinal()),
+                    ((ITexturedTileEntity) tTileEntity).getTexture(aBlock, (byte) EAST.ordinal())});
+        }
+        return false;
+    }
+
+    public static boolean renderStandardBlock(IBlockAccess aWorld, int aX, int aY, int aZ, Block aBlock, RenderBlocks aRenderer, ITexture[][] aTextures) {
+        aBlock.setBlockBounds(blockMin, blockMin, blockMin, blockMax, blockMax, blockMax);
+        aRenderer.setRenderBoundsFromBlock(aBlock);
+
+        renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[DOWN.ordinal()], true);
+        renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[UP.ordinal()], true);
+        renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[NORTH.ordinal()], true);
+        renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[SOUTH.ordinal()], true);
+        renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[WEST.ordinal()], true);
+        renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[EAST.ordinal()], true);
+        return true;
+    }
+
+    public static boolean renderPipeBlock(IBlockAccess aWorld, int aX, int aY, int aZ, Block aBlock, IPipeRenderedTileEntity aTileEntity, RenderBlocks aRenderer) {
+        final byte aConnections = aTileEntity.getConnections();
+        if ((aConnections & (HAS_FRESHFOAM | HAS_HARDENEDFOAM)) != 0) {
+            return renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer);
+        }
+        final float thickness = aTileEntity.getThickNess();
+        if (thickness >= 0.99F) {
+            return renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer);
+        }
+        // Range of block occupied by pipe
+        final float pipeMin = (blockMax - thickness) / 2.0F;
+        final float pipeMax = blockMax - pipeMin;
+        final boolean[] tIsCovered = new boolean[VALID_DIRECTIONS.length];
+        for (int i = 0; i < VALID_DIRECTIONS.length; i++) {
+            tIsCovered[i] = (aTileEntity.getCoverIDAtSide((byte) i) != 0);
+        }
+
+        final ITexture[][] tIcons = new ITexture[VALID_DIRECTIONS.length][];
+        final ITexture[][] tCovers = new ITexture[VALID_DIRECTIONS.length][];
+        for (int i = 0; i < VALID_DIRECTIONS.length; i++) {
+            tCovers[i] = aTileEntity.getTexture(aBlock, (byte) i);
+            tIcons[i] = aTileEntity.getTextureUncovered((byte) i);
+        }
+
+        switch (aConnections) {
+            case NO_CONNECTION:
+                aBlock.setBlockBounds(pipeMin, pipeMin, pipeMin, pipeMax, pipeMax, pipeMax);
+                aRenderer.setRenderBoundsFromBlock(aBlock);
+                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[DOWN.ordinal()], false);
+                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[UP.ordinal()], false);
+                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[NORTH.ordinal()], false);
+                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SOUTH.ordinal()], false);
+                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[WEST.ordinal()], false);
+                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[EAST.ordinal()], false);
+                break;
+            case CONNECTED_EAST | CONNECTED_WEST:
+                // EAST - WEST Pipe Sides
+                aBlock.setBlockBounds(blockMin, pipeMin, pipeMin, blockMax, pipeMax, pipeMax);
+                aRenderer.setRenderBoundsFromBlock(aBlock);
+                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[DOWN.ordinal()], false);
+                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[UP.ordinal()], false);
+                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[NORTH.ordinal()], false);
+                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SOUTH.ordinal()], false);
+
+                // EAST - WEST Pipe Ends
+                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[WEST.ordinal()], false);
+                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[EAST.ordinal()], false);
+                break;
+            case CONNECTED_DOWN | CONNECTED_UP:
+                // UP - DOWN Pipe Sides
+                aBlock.setBlockBounds(pipeMin, blockMin, pipeMin, pipeMax, blockMax, pipeMax);
+                aRenderer.setRenderBoundsFromBlock(aBlock);
+                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[NORTH.ordinal()], false);
+                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SOUTH.ordinal()], false);
+                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[WEST.ordinal()], false);
+                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[EAST.ordinal()], false);
+
+                // UP - DOWN Pipe Ends
+                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[DOWN.ordinal()], false);
+                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[UP.ordinal()], false);
+                break;
+            case CONNECTED_NORTH | CONNECTED_SOUTH:
+                // NORTH - SOUTH Pipe Sides
+                aBlock.setBlockBounds(pipeMin, pipeMin, blockMin, pipeMax, pipeMax, blockMax);
+                aRenderer.setRenderBoundsFromBlock(aBlock);
+                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[DOWN.ordinal()], false);
+                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[UP.ordinal()], false);
+                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[WEST.ordinal()], false);
+                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[EAST.ordinal()], false);
+
+                // NORTH - SOUTH Pipe Ends
+                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[NORTH.ordinal()], false);
+                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SOUTH.ordinal()], false);
+                break;
+            default:
+                if ((aConnections & CONNECTED_WEST) == 0) {
+                    aBlock.setBlockBounds(pipeMin, pipeMin, pipeMin, pipeMax, pipeMax, pipeMax);
+                    aRenderer.setRenderBoundsFromBlock(aBlock);
+                } else {
+                    aBlock.setBlockBounds(blockMin, pipeMin, pipeMin, pipeMin, pipeMax, pipeMax);
+                    aRenderer.setRenderBoundsFromBlock(aBlock);
+                    renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[DOWN.ordinal()], false);
+                    renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[UP.ordinal()], false);
+                    renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[NORTH.ordinal()], false);
+                    renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SOUTH.ordinal()], false);
+                }
+                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[WEST.ordinal()], false);
+
+                if ((aConnections & CONNECTED_EAST) == 0) {
+                    aBlock.setBlockBounds(pipeMin, pipeMin, pipeMin, pipeMax, pipeMax, pipeMax);
+                    aRenderer.setRenderBoundsFromBlock(aBlock);
+                } else {
+                    aBlock.setBlockBounds(pipeMax, pipeMin, pipeMin, blockMax, pipeMax, pipeMax);
+                    aRenderer.setRenderBoundsFromBlock(aBlock);
+                    renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[DOWN.ordinal()], false);
+                    renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[UP.ordinal()], false);
+                    renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[NORTH.ordinal()], false);
+                    renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SOUTH.ordinal()], false);
+                }
+                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[EAST.ordinal()], false);
+
+                if ((aConnections & CONNECTED_DOWN) == 0) {
+                    aBlock.setBlockBounds(pipeMin, pipeMin, pipeMin, pipeMax, pipeMax, pipeMax);
+                    aRenderer.setRenderBoundsFromBlock(aBlock);
+                } else {
+                    aBlock.setBlockBounds(pipeMin, blockMin, pipeMin, pipeMax, pipeMin, pipeMax);
+                    aRenderer.setRenderBoundsFromBlock(aBlock);
+                    renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[NORTH.ordinal()], false);
+                    renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SOUTH.ordinal()], false);
+                    renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[WEST.ordinal()], false);
+                    renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[EAST.ordinal()], false);
+                }
+                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[DOWN.ordinal()], false);
+
+                if ((aConnections & CONNECTED_UP) == 0) {
+                    aBlock.setBlockBounds(pipeMin, pipeMin, pipeMin, pipeMax, pipeMax, pipeMax);
+                    aRenderer.setRenderBoundsFromBlock(aBlock);
+                } else {
+                    aBlock.setBlockBounds(pipeMin, pipeMax, pipeMin, pipeMax, blockMax, pipeMax);
+                    aRenderer.setRenderBoundsFromBlock(aBlock);
+                    renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[NORTH.ordinal()], false);
+                    renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SOUTH.ordinal()], false);
+                    renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[WEST.ordinal()], false);
+                    renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[EAST.ordinal()], false);
+                }
+                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[UP.ordinal()], false);
+
+                if ((aConnections & CONNECTED_NORTH) == 0) {
+                    aBlock.setBlockBounds(pipeMin, pipeMin, pipeMin, pipeMax, pipeMax, pipeMax);
+                    aRenderer.setRenderBoundsFromBlock(aBlock);
+                } else {
+                    aBlock.setBlockBounds(pipeMin, pipeMin, blockMin, pipeMax, pipeMax, pipeMin);
+                    aRenderer.setRenderBoundsFromBlock(aBlock);
+                    renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[DOWN.ordinal()], false);
+                    renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[UP.ordinal()], false);
+                    renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[WEST.ordinal()], false);
+                    renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[EAST.ordinal()], false);
+                }
+                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[NORTH.ordinal()], false);
+
+                if ((aConnections & CONNECTED_SOUTH) == 0) {
+                    aBlock.setBlockBounds(pipeMin, pipeMin, pipeMin, pipeMax, pipeMax, pipeMax);
+                    aRenderer.setRenderBoundsFromBlock(aBlock);
+                } else {
+                    aBlock.setBlockBounds(pipeMin, pipeMin, pipeMax, pipeMax, pipeMax, blockMax);
+                    aRenderer.setRenderBoundsFromBlock(aBlock);
+                    renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[DOWN.ordinal()], false);
+                    renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[UP.ordinal()], false);
+                    renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[WEST.ordinal()], false);
+                    renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[EAST.ordinal()], false);
+                }
+                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SOUTH.ordinal()], false);
+                break;
+        }
+
+        // Render covers on pipes
+        if (tIsCovered[DOWN.ordinal()]) {
+            aBlock.setBlockBounds(blockMin, blockMin, blockMin, blockMax, coverInnerMin, blockMax);
+            aRenderer.setRenderBoundsFromBlock(aBlock);
+            if (!tIsCovered[NORTH.ordinal()]) {
+                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[DOWN.ordinal()], false);
+            }
+            if (!tIsCovered[SOUTH.ordinal()]) {
+                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[DOWN.ordinal()], false);
+            }
+            if (!tIsCovered[WEST.ordinal()]) {
+                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[DOWN.ordinal()], false);
+            }
+            if (!tIsCovered[EAST.ordinal()]) {
+                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[DOWN.ordinal()], false);
+            }
+            renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[DOWN.ordinal()], false);
+            if ((aConnections & CONNECTED_DOWN) != 0) {
+                // Split outer face to leave hole for pipe
+                // Lower panel
+                aRenderer.setRenderBounds(blockMin, blockMin, blockMin, blockMax, blockMin, pipeMin);
+                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[DOWN.ordinal()], false);
+                // Upper panel
+                aRenderer.setRenderBounds(blockMin, blockMin, pipeMax, blockMax, blockMin, blockMax);
+                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[DOWN.ordinal()], false);
+                // Middle left panel
+                aRenderer.setRenderBounds(blockMin, blockMin, pipeMin, pipeMin, blockMin, pipeMax);
+                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[DOWN.ordinal()], false);
+                // Middle right panel
+                aRenderer.setRenderBounds(pipeMax, blockMin, pipeMin, blockMax, blockMin, pipeMax);
+            }
+            renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[DOWN.ordinal()], false);
+        }
+
+        if (tIsCovered[UP.ordinal()]) {
+            aBlock.setBlockBounds(blockMin, coverInnerMax, blockMin, blockMax, blockMax, blockMax);
+            aRenderer.setRenderBoundsFromBlock(aBlock);
+            if (!tIsCovered[NORTH.ordinal()]) {
+                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[UP.ordinal()], false);
+            }
+            if (!tIsCovered[SOUTH.ordinal()]) {
+                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[UP.ordinal()], false);
+            }
+            if (!tIsCovered[WEST.ordinal()]) {
+                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[UP.ordinal()], false);
+            }
+            if (!tIsCovered[EAST.ordinal()]) {
+                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[UP.ordinal()], false);
+            }
+            renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[UP.ordinal()], false);
+            if ((aConnections & CONNECTED_UP) != 0) {
+                // Split outer face to leave hole for pipe
+                // Lower panel
+                aRenderer.setRenderBounds(blockMin, blockMax, blockMin, blockMax, blockMax, pipeMin);
+                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[UP.ordinal()], false);
+                // Upper panel
+                aRenderer.setRenderBounds(blockMin, blockMax, pipeMax, blockMax, blockMax, blockMax);
+                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[UP.ordinal()], false);
+                // Middle left panel
+                aRenderer.setRenderBounds(blockMin, blockMax, pipeMin, pipeMin, blockMax, pipeMax);
+                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[UP.ordinal()], false);
+                // Middle right panel
+                aRenderer.setRenderBounds(pipeMax, blockMax, pipeMin, blockMax, blockMax, pipeMax);
+            }
+            renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[UP.ordinal()], false);
+        }
+
+        if (tIsCovered[NORTH.ordinal()]) {
+            aBlock.setBlockBounds(blockMin, blockMin, blockMin, blockMax, blockMax, coverInnerMin);
+            aRenderer.setRenderBoundsFromBlock(aBlock);
+            if (!tIsCovered[DOWN.ordinal()]) {
+                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[NORTH.ordinal()], false);
+            }
+            if (!tIsCovered[UP.ordinal()]) {
+                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[NORTH.ordinal()], false);
+            }
+            if (!tIsCovered[WEST.ordinal()]) {
+                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[NORTH.ordinal()], false);
+            }
+            if (!tIsCovered[EAST.ordinal()]) {
+                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[NORTH.ordinal()], false);
+            }
+            renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[NORTH.ordinal()], false);
+            if ((aConnections & CONNECTED_NORTH) != 0) {
+                // Split outer face to leave hole for pipe
+                // Lower panel
+                aRenderer.setRenderBounds(blockMin, blockMin, blockMin, blockMax, pipeMin, blockMin);
+                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[NORTH.ordinal()], false);
+                // Upper panel
+                aRenderer.setRenderBounds(blockMin, pipeMax, blockMin, blockMax, blockMax, blockMin);
+                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[NORTH.ordinal()], false);
+                // Middle left panel
+                aRenderer.setRenderBounds(blockMin, pipeMin, blockMin, pipeMin, pipeMax, blockMin);
+                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[NORTH.ordinal()], false);
+                // Middle right panel
+                aRenderer.setRenderBounds(pipeMax, pipeMin, blockMin, blockMax, pipeMax, blockMin);
+            }
+            renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[NORTH.ordinal()], false);
+        }
+
+        if (tIsCovered[SOUTH.ordinal()]) {
+            aBlock.setBlockBounds(blockMin, blockMin, coverInnerMax, blockMax, blockMax, blockMax);
+            aRenderer.setRenderBoundsFromBlock(aBlock);
+            if (!tIsCovered[DOWN.ordinal()]) {
+                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SOUTH.ordinal()], false);
+            }
+            if (!tIsCovered[UP.ordinal()]) {
+                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SOUTH.ordinal()], false);
+            }
+            if (!tIsCovered[WEST.ordinal()]) {
+                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SOUTH.ordinal()], false);
+            }
+            if (!tIsCovered[EAST.ordinal()]) {
+                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SOUTH.ordinal()], false);
+            }
+            renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SOUTH.ordinal()], false);
+            if ((aConnections & CONNECTED_SOUTH) != 0) {
+                // Split outer face to leave hole for pipe
+                // Lower panel
+                aRenderer.setRenderBounds(blockMin, blockMin, blockMax, blockMax, pipeMin, blockMax);
+                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SOUTH.ordinal()], false);
+                // Upper panel
+                aRenderer.setRenderBounds(blockMin, pipeMax, blockMax, blockMax, blockMax, blockMax);
+                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SOUTH.ordinal()], false);
+                // Middle left panel
+                aRenderer.setRenderBounds(blockMin, pipeMin, blockMax, pipeMin, pipeMax, blockMax);
+                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SOUTH.ordinal()], false);
+                // Middle right panel
+                aRenderer.setRenderBounds(pipeMax, pipeMin, blockMax, blockMax, pipeMax, blockMax);
+            }
+            renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SOUTH.ordinal()], false);
+        }
+
+        if (tIsCovered[WEST.ordinal()]) {
+            aBlock.setBlockBounds(blockMin, blockMin, blockMin, coverInnerMin, blockMax, blockMax);
+            aRenderer.setRenderBoundsFromBlock(aBlock);
+            if (!tIsCovered[DOWN.ordinal()]) {
+                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[WEST.ordinal()], false);
+            }
+            if (!tIsCovered[UP.ordinal()]) {
+                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[WEST.ordinal()], false);
+            }
+            if (!tIsCovered[NORTH.ordinal()]) {
+                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[WEST.ordinal()], false);
+            }
+            if (!tIsCovered[SOUTH.ordinal()]) {
+                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[WEST.ordinal()], false);
+            }
+            renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[WEST.ordinal()], false);
+            if ((aConnections & CONNECTED_WEST) != 0) {
+                // Split outer face to leave hole for pipe
+                // Lower panel
+                aRenderer.setRenderBounds(blockMin, blockMin, blockMin, blockMin, pipeMin, blockMax);
+                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[WEST.ordinal()], false);
+                // Upper panel
+                aRenderer.setRenderBounds(blockMin, pipeMax, blockMin, blockMin, blockMax, blockMax);
+                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[WEST.ordinal()], false);
+                // Middle left panel
+                aRenderer.setRenderBounds(blockMin, pipeMin, blockMin, blockMin, pipeMax, pipeMin);
+                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[WEST.ordinal()], false);
+                // Middle right panel
+                aRenderer.setRenderBounds(blockMin, pipeMin, pipeMax, blockMin, pipeMax, blockMax);
+            }
+            renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[WEST.ordinal()], false);
+        }
+
+        if (tIsCovered[EAST.ordinal()]) {
+            aBlock.setBlockBounds(coverInnerMax, blockMin, blockMin, blockMax, blockMax, blockMax);
+            aRenderer.setRenderBoundsFromBlock(aBlock);
+            if (!tIsCovered[DOWN.ordinal()]) {
+                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[EAST.ordinal()], false);
+            }
+            if (!tIsCovered[UP.ordinal()]) {
+                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[EAST.ordinal()], false);
+            }
+            if (!tIsCovered[NORTH.ordinal()]) {
+                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[EAST.ordinal()], false);
+            }
+            if (!tIsCovered[SOUTH.ordinal()]) {
+                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[EAST.ordinal()], false);
+            }
+            renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[EAST.ordinal()], false);
+
+            if ((aConnections & CONNECTED_EAST) != 0) {
+                // Split outer face to leave hole for pipe
+                // Lower panel
+                aRenderer.setRenderBounds(blockMax, blockMin, blockMin, blockMax, pipeMin, blockMax);
+                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[EAST.ordinal()], false);
+                // Upper panel
+                aRenderer.setRenderBounds(blockMax, pipeMax, blockMin, blockMax, blockMax, blockMax);
+                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[EAST.ordinal()], false);
+                // Middle left panel
+                aRenderer.setRenderBounds(blockMax, pipeMin, blockMin, blockMax, pipeMax, pipeMin);
+                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[EAST.ordinal()], false);
+                // Middle right panel
+                aRenderer.setRenderBounds(blockMax, pipeMin, pipeMax, blockMax, pipeMax, blockMax);
+            }
+            renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[EAST.ordinal()], false);
+        }
+        aBlock.setBlockBounds(blockMin, blockMin, blockMin, blockMax, blockMax, blockMax);
+        aRenderer.setRenderBoundsFromBlock(aBlock);
+
+        return true;
+    }
+
+    public void renderInventoryBlock(Block aBlock, int aMeta, int aModelID, RenderBlocks aRenderer) {
+        aRenderer.enableAO = false;
+        if ((aBlock instanceof GT_Block_Machines)) {
+            if ((aMeta > 0) && (aMeta < GregTech_API.METATILEENTITIES.length) && (GregTech_API.METATILEENTITIES[aMeta] != null) &&
+                    (!GregTech_API.METATILEENTITIES[aMeta].renderInInventory(aBlock, aMeta, aRenderer))) {
+                renderNormalInventoryMetaTileEntity(aBlock, aMeta, aRenderer);
+            }
+        } else if ((aBlock instanceof GT_Block_Ores_Abstract)) {
+            GT_TileEntity_Ores tTileEntity = new GT_TileEntity_Ores();
+            tTileEntity.mMetaData = ((short) aMeta);
+
+            aBlock.setBlockBoundsForItemRender();
+            aRenderer.setRenderBoundsFromBlock(aBlock);
+
+            GL11.glTranslatef(-0.5F, -0.5F, -0.5F);
+
+            Tessellator.instance.startDrawingQuads();
+            Tessellator.instance.setNormal(0.0F, -1.0F, 0.0F);
+            renderNegativeYFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 0), true);
+            Tessellator.instance.draw();
+
+            Tessellator.instance.startDrawingQuads();
+            Tessellator.instance.setNormal(0.0F, 1.0F, 0.0F);
+            renderPositiveYFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 1), true);
+            Tessellator.instance.draw();
+
+            Tessellator.instance.startDrawingQuads();
+            Tessellator.instance.setNormal(0.0F, 0.0F, -1.0F);
+            renderNegativeZFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 2), true);
+            Tessellator.instance.draw();
+
+            Tessellator.instance.startDrawingQuads();
+            Tessellator.instance.setNormal(0.0F, 0.0F, 1.0F);
+            renderPositiveZFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 3), true);
+            Tessellator.instance.draw();
+
+            Tessellator.instance.startDrawingQuads();
+            Tessellator.instance.setNormal(-1.0F, 0.0F, 0.0F);
+            renderNegativeXFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 4), true);
+            Tessellator.instance.draw();
+
+            Tessellator.instance.startDrawingQuads();
+            Tessellator.instance.setNormal(1.0F, 0.0F, 0.0F);
+            renderPositiveXFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 5), true);
+            Tessellator.instance.draw();
+        }
+        aBlock.setBlockBounds(blockMin, blockMin, blockMin, 1.0F, 1.0F, 1.0F);
+        aRenderer.setRenderBoundsFromBlock(aBlock);
+        GL11.glTranslatef(0.5F, 0.5F, 0.5F);
+    }
+
     private static void renderNormalInventoryMetaTileEntity(Block aBlock, int aMeta, RenderBlocks aRenderer) {
         if ((aMeta <= 0) || (aMeta >= GregTech_API.METATILEENTITIES.length)) {
             return;
@@ -43,382 +510,81 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
         aBlock.setBlockBoundsForItemRender();
         aRenderer.setRenderBoundsFromBlock(aBlock);
 
-        GL11.glRotatef(90.0F, 0.0F, 1.0F, 0.0F);
+        final IGregTechTileEntity iGregTechTileEntity = tMetaTileEntity.getBaseMetaTileEntity();
+
         GL11.glTranslatef(-0.5F, -0.5F, -0.5F);
-        if ((tMetaTileEntity.getBaseMetaTileEntity() instanceof IPipeRenderedTileEntity)) {
-            float tThickness = ((IPipeRenderedTileEntity) tMetaTileEntity.getBaseMetaTileEntity()).getThickNess();
-            float sp = (1.0F - tThickness) / 2.0F;
+        if ((iGregTechTileEntity instanceof IPipeRenderedTileEntity)) {
+            final float tThickness = ((IPipeRenderedTileEntity) iGregTechTileEntity).getThickNess();
+            final float pipeMin = (blockMax - tThickness) / 2.0F;
+            final float pipeMax = blockMax - pipeMin;
 
-            aBlock.setBlockBounds(0.0F, sp, sp, 1.0F, sp + tThickness, sp + tThickness);
+            aBlock.setBlockBounds(blockMin, pipeMin, pipeMin, blockMax, pipeMax, pipeMax);
             aRenderer.setRenderBoundsFromBlock(aBlock);
 
             Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, -1.0F, 0.0F);
-            renderNegativeYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(tMetaTileEntity.getBaseMetaTileEntity(), (byte) 0, (byte) 9, (byte) -1, false, false), true);
+            renderNegativeYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) DOWN.ordinal(), (byte) (CONNECTED_WEST | CONNECTED_EAST), (byte) -1, false, false), true);
             Tessellator.instance.draw();
 
             Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 1.0F, 0.0F);
-            renderPositiveYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(tMetaTileEntity.getBaseMetaTileEntity(), (byte) 1, (byte) 9, (byte) -1, false, false), true);
+            renderPositiveYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) UP.ordinal(), (byte) (CONNECTED_WEST | CONNECTED_EAST), (byte) -1, false, false), true);
             Tessellator.instance.draw();
 
             Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 0.0F, -1.0F);
-            renderNegativeZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(tMetaTileEntity.getBaseMetaTileEntity(), (byte) 2, (byte) 9, (byte) -1, false, false), true);
+            renderNegativeZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) NORTH.ordinal(), (byte) (CONNECTED_WEST | CONNECTED_EAST), (byte) -1, false, false), true);
             Tessellator.instance.draw();
 
             Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 0.0F, 1.0F);
-            renderPositiveZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(tMetaTileEntity.getBaseMetaTileEntity(), (byte) 3, (byte) 9, (byte) -1, false, false), true);
+            renderPositiveZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) SOUTH.ordinal(), (byte) (CONNECTED_WEST | CONNECTED_EAST), (byte) -1, false, false), true);
             Tessellator.instance.draw();
 
             Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(-1.0F, 0.0F, 0.0F);
-            renderNegativeXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(tMetaTileEntity.getBaseMetaTileEntity(), (byte) 4, (byte) 9, (byte) -1, true, false), true);
+            renderNegativeXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) WEST.ordinal(), (byte) (CONNECTED_WEST | CONNECTED_EAST), (byte) -1, true, false), true);
             Tessellator.instance.draw();
 
             Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(1.0F, 0.0F, 0.0F);
-            renderPositiveXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(tMetaTileEntity.getBaseMetaTileEntity(), (byte) 5, (byte) 9, (byte) -1, true, false), true);
-            Tessellator.instance.draw();
+            renderPositiveXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) EAST.ordinal(), (byte) (CONNECTED_WEST | CONNECTED_EAST), (byte) -1, true, false), true);
         } else {
             Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, -1.0F, 0.0F);
-            renderNegativeYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(tMetaTileEntity.getBaseMetaTileEntity(), (byte) 0, (byte) 4, (byte) -1, true, false), true);
+            renderNegativeYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) DOWN.ordinal(), (byte) EAST.ordinal(), (byte) -1, true, false), true);
             Tessellator.instance.draw();
 
             Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 1.0F, 0.0F);
-            renderPositiveYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(tMetaTileEntity.getBaseMetaTileEntity(), (byte) 1, (byte) 4, (byte) -1, true, false), true);
+            renderPositiveYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) UP.ordinal(), (byte) EAST.ordinal(), (byte) -1, true, false), true);
             Tessellator.instance.draw();
 
             Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 0.0F, -1.0F);
-            renderNegativeZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(tMetaTileEntity.getBaseMetaTileEntity(), (byte) 2, (byte) 4, (byte) -1, true, false), true);
+            renderNegativeZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) NORTH.ordinal(), (byte) EAST.ordinal(), (byte) -1, true, false), true);
             Tessellator.instance.draw();
 
             Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 0.0F, 1.0F);
-            renderPositiveZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(tMetaTileEntity.getBaseMetaTileEntity(), (byte) 3, (byte) 4, (byte) -1, true, false), true);
+            renderPositiveZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) SOUTH.ordinal(), (byte) EAST.ordinal(), (byte) -1, true, false), true);
             Tessellator.instance.draw();
 
             Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(-1.0F, 0.0F, 0.0F);
-            renderNegativeXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(tMetaTileEntity.getBaseMetaTileEntity(), (byte) 4, (byte) 4, (byte) -1, true, false), true);
+            renderNegativeXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) WEST.ordinal(), (byte) EAST.ordinal(), (byte) -1, true, false), true);
             Tessellator.instance.draw();
 
             Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(1.0F, 0.0F, 0.0F);
-            renderPositiveXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(tMetaTileEntity.getBaseMetaTileEntity(), (byte) 5, (byte) 4, (byte) -1, true, false), true);
-            Tessellator.instance.draw();
+            renderPositiveXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) EAST.ordinal(), (byte) EAST.ordinal(), (byte) -1, true, false), true);
         }
-        aBlock.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+        Tessellator.instance.draw();
+        aBlock.setBlockBounds(blockMin, blockMin, blockMin, blockMax, blockMax, blockMax);
         aRenderer.setRenderBoundsFromBlock(aBlock);
         GL11.glTranslatef(0.5F, 0.5F, 0.5F);
     }
 
-    public static boolean renderStandardBlock(IBlockAccess aWorld, int aX, int aY, int aZ, Block aBlock, RenderBlocks aRenderer) {
-        TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
-        if ((tTileEntity instanceof IPipeRenderedTileEntity)) {
-            return renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer, new ITexture[][]{
-                    ((IPipeRenderedTileEntity) tTileEntity).getTextureCovered((byte) 0),
-                    ((IPipeRenderedTileEntity) tTileEntity).getTextureCovered((byte) 1),
-                    ((IPipeRenderedTileEntity) tTileEntity).getTextureCovered((byte) 2),
-                    ((IPipeRenderedTileEntity) tTileEntity).getTextureCovered((byte) 3),
-                    ((IPipeRenderedTileEntity) tTileEntity).getTextureCovered((byte) 4),
-                    ((IPipeRenderedTileEntity) tTileEntity).getTextureCovered((byte) 5)});
-        }
-        if ((tTileEntity instanceof ITexturedTileEntity)) {
-            return renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer, new ITexture[][]{
-                    ((ITexturedTileEntity) tTileEntity).getTexture(aBlock, (byte) 0),
-                    ((ITexturedTileEntity) tTileEntity).getTexture(aBlock, (byte) 1),
-                    ((ITexturedTileEntity) tTileEntity).getTexture(aBlock, (byte) 2),
-                    ((ITexturedTileEntity) tTileEntity).getTexture(aBlock, (byte) 3),
-                    ((ITexturedTileEntity) tTileEntity).getTexture(aBlock, (byte) 4),
-                    ((ITexturedTileEntity) tTileEntity).getTexture(aBlock, (byte) 5)});
-        }
-        return false;
-    }
-
-    public static boolean renderStandardBlock(IBlockAccess aWorld, int aX, int aY, int aZ, Block aBlock, RenderBlocks aRenderer, ITexture[][] aTextures) {
-        aBlock.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
-        aRenderer.setRenderBoundsFromBlock(aBlock);
-
-        renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[0], true);
-        renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[1], true);
-        renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[2], true);
-        renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[3], true);
-        renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[4], true);
-        renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[5], true);
-        return true;
-    }
-
-    public static boolean renderPipeBlock(IBlockAccess aWorld, int aX, int aY, int aZ, Block aBlock, IPipeRenderedTileEntity aTileEntity, RenderBlocks aRenderer) {
-        byte aConnections = aTileEntity.getConnections();
-        if ((aConnections & 0xC0) != 0) {
-            return renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer);
-        }
-        float tThickness = aTileEntity.getThickNess();
-        if (tThickness >= 0.99F) {
-            return renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer);
-        }
-        float sp = (1.0F - tThickness) / 2.0F;
-
-        byte tConnections = 0;
-        for (byte i = 0; i < 6; i = (byte) (i + 1)) {
-            if ((aConnections & 1 << i) != 0) {
-                tConnections = (byte) (tConnections | 1 << (i + 2) % 6);
-            }
-        }
-        boolean[] tIsCovered = new boolean[6];
-        for (byte i = 0; i < 6; i = (byte) (i + 1)) {
-            tIsCovered[i] = (aTileEntity.getCoverIDAtSide(i) != 0);
-        }
-        if ((tIsCovered[0]) && (tIsCovered[1]) && (tIsCovered[2]) && (tIsCovered[3]) && (tIsCovered[4]) && (tIsCovered[5])) {
-            return renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer);
-        }
-        ITexture[][] tIcons = new ITexture[6][];
-        ITexture[][] tCovers = new ITexture[6][];
-        for (byte i = 0; i < 6; i = (byte) (i + 1)) {
-            tCovers[i] = aTileEntity.getTexture(aBlock, i);
-            tIcons[i] = aTileEntity.getTextureUncovered(i);
-        }
-        if (tConnections == 0) {
-            aBlock.setBlockBounds(sp, sp, sp, sp + tThickness, sp + tThickness, sp + tThickness);
-            aRenderer.setRenderBoundsFromBlock(aBlock);
-            renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[0], false);
-            renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[1], false);
-            renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[2], false);
-            renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[3], false);
-            renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[4], false);
-            renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[5], false);
-        } else if (tConnections == 3) {
-            aBlock.setBlockBounds(0.0F, sp, sp, 1.0F, sp + tThickness, sp + tThickness);
-            aRenderer.setRenderBoundsFromBlock(aBlock);
-            renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[0], false);
-            renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[1], false);
-            renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[2], false);
-            renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[3], false);
-
-            renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[4], false);
-            renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[5], false);
-
-        } else if (tConnections == 12) {
-            aBlock.setBlockBounds(sp, 0.0F, sp, sp + tThickness, 1.0F, sp + tThickness);
-            aRenderer.setRenderBoundsFromBlock(aBlock);
-            renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[2], false);
-            renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[3], false);
-            renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[4], false);
-            renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[5], false);
-
-            renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[0], false);
-            renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[1], false);
-
-        } else if (tConnections == 48) {
-            aBlock.setBlockBounds(sp, sp, 0.0F, sp + tThickness, sp + tThickness, 1.0F);
-            aRenderer.setRenderBoundsFromBlock(aBlock);
-            renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[0], false);
-            renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[1], false);
-            renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[4], false);
-            renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[5], false);
-
-            renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[2], false);
-            renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[3], false);
-
-        } else {
-            if ((tConnections & 0x1) == 0) {
-                aBlock.setBlockBounds(sp, sp, sp, sp + tThickness, sp + tThickness, sp + tThickness);
-                aRenderer.setRenderBoundsFromBlock(aBlock);
-            } else {
-                aBlock.setBlockBounds(0.0F, sp, sp, sp, sp + tThickness, sp + tThickness);
-                aRenderer.setRenderBoundsFromBlock(aBlock);
-                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[0], false);
-                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[1], false);
-                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[2], false);
-                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[3], false);
-
-            }
-            renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[4], false);
-            if ((tConnections & 0x2) == 0) {
-                aBlock.setBlockBounds(sp, sp, sp, sp + tThickness, sp + tThickness, sp + tThickness);
-                aRenderer.setRenderBoundsFromBlock(aBlock);
-            } else {
-                aBlock.setBlockBounds(sp + tThickness, sp, sp, 1.0F, sp + tThickness, sp + tThickness);
-                aRenderer.setRenderBoundsFromBlock(aBlock);
-                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[0], false);
-                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[1], false);
-                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[2], false);
-                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[3], false);
-
-            }
-            renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[5], false);
-            if ((tConnections & 0x4) == 0) {
-                aBlock.setBlockBounds(sp, sp, sp, sp + tThickness, sp + tThickness, sp + tThickness);
-                aRenderer.setRenderBoundsFromBlock(aBlock);
-            } else {
-                aBlock.setBlockBounds(sp, 0.0F, sp, sp + tThickness, sp, sp + tThickness);
-                aRenderer.setRenderBoundsFromBlock(aBlock);
-                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[2], false);
-                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[3], false);
-                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[4], false);
-                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[5], false);
-
-            }
-            renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[0], false);
-            if ((tConnections & 0x8) == 0) {
-                aBlock.setBlockBounds(sp, sp, sp, sp + tThickness, sp + tThickness, sp + tThickness);
-                aRenderer.setRenderBoundsFromBlock(aBlock);
-            } else {
-                aBlock.setBlockBounds(sp, sp + tThickness, sp, sp + tThickness, 1.0F, sp + tThickness);
-                aRenderer.setRenderBoundsFromBlock(aBlock);
-                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[2], false);
-                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[3], false);
-                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[4], false);
-                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[5], false);
-
-            }
-            renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[1], false);
-            if ((tConnections & 0x10) == 0) {
-                aBlock.setBlockBounds(sp, sp, sp, sp + tThickness, sp + tThickness, sp + tThickness);
-                aRenderer.setRenderBoundsFromBlock(aBlock);
-            } else {
-                aBlock.setBlockBounds(sp, sp, 0.0F, sp + tThickness, sp + tThickness, sp);
-                aRenderer.setRenderBoundsFromBlock(aBlock);
-                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[0], false);
-                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[1], false);
-                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[4], false);
-                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[5], false);
-
-            }
-            renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[2], false);
-            if ((tConnections & 0x20) == 0) {
-                aBlock.setBlockBounds(sp, sp, sp, sp + tThickness, sp + tThickness, sp + tThickness);
-                aRenderer.setRenderBoundsFromBlock(aBlock);
-            } else {
-                aBlock.setBlockBounds(sp, sp, sp + tThickness, sp + tThickness, sp + tThickness, 1.0F);
-                aRenderer.setRenderBoundsFromBlock(aBlock);
-                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[0], false);
-                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[1], false);
-                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[4], false);
-                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[5], false);
-
-            }
-            renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[3], false);
-        }
-        if (tIsCovered[0]) {
-            aBlock.setBlockBounds(0.0F, 0.0F + NO_Z_FIGHT_OFFSET, 0.0F, 1.0F, 0.125F, 1.0F);
-            aRenderer.setRenderBoundsFromBlock(aBlock);
-            renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[0], false);
-            renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[0], false);
-            if (!tIsCovered[2]) {
-                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[0], false);
-            }
-            if (!tIsCovered[3]) {
-                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[0], false);
-            }
-            if (!tIsCovered[4]) {
-                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[0], false);
-            }
-            if (!tIsCovered[5]) {
-                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[0], false);
-            }
-        }
-        if (tIsCovered[1]) {
-            aBlock.setBlockBounds(0.0F, 0.875F, 0.0F, 1.0F, 1.0F - NO_Z_FIGHT_OFFSET, 1.0F);
-            aRenderer.setRenderBoundsFromBlock(aBlock);
-            renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[1], false);
-            renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[1], false);
-            if (!tIsCovered[2]) {
-                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[1], false);
-            }
-            if (!tIsCovered[3]) {
-                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[1], false);
-            }
-            if (!tIsCovered[4]) {
-                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[1], false);
-            }
-            if (!tIsCovered[5]) {
-                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[1], false);
-            }
-        }
-        if (tIsCovered[2]) {
-            aBlock.setBlockBounds(0.0F, 0.0F, 0.0F + NO_Z_FIGHT_OFFSET, 1.0F, 1.0F, 0.125F);
-            aRenderer.setRenderBoundsFromBlock(aBlock);
-            if (!tIsCovered[0]) {
-                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[2], false);
-            }
-            if (!tIsCovered[1]) {
-                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[2], false);
-            }
-            renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[2], false);
-            renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[2], false);
-            if (!tIsCovered[4]) {
-                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[2], false);
-            }
-            if (!tIsCovered[5]) {
-                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[2], false);
-            }
-        }
-        if (tIsCovered[3]) {
-            aBlock.setBlockBounds(0.0F, 0.0F, 0.875F, 1.0F, 1.0F, 1.0F - NO_Z_FIGHT_OFFSET);
-            aRenderer.setRenderBoundsFromBlock(aBlock);
-            if (!tIsCovered[0]) {
-                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[3], false);
-            }
-            if (!tIsCovered[1]) {
-                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[3], false);
-            }
-            renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[3], false);
-            renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[3], false);
-            if (!tIsCovered[4]) {
-                renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[3], false);
-            }
-            if (!tIsCovered[5]) {
-                renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[3], false);
-            }
-        }
-        if (tIsCovered[4]) {
-            aBlock.setBlockBounds(0.0F + NO_Z_FIGHT_OFFSET, 0.0F, 0.0F, 0.125F, 1.0F, 1.0F);
-            aRenderer.setRenderBoundsFromBlock(aBlock);
-            if (!tIsCovered[0]) {
-                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[4], false);
-            }
-            if (!tIsCovered[1]) {
-                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[4], false);
-            }
-            if (!tIsCovered[2]) {
-                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[4], false);
-            }
-            if (!tIsCovered[3]) {
-                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[4], false);
-            }
-            renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[4], false);
-            renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[4], false);
-        }
-        if (tIsCovered[5]) {
-            aBlock.setBlockBounds(0.875F, 0.0F, 0.0F, 1.0F - NO_Z_FIGHT_OFFSET, 1.0F, 1.0F);
-            aRenderer.setRenderBoundsFromBlock(aBlock);
-            if (!tIsCovered[0]) {
-                renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[5], false);
-            }
-            if (!tIsCovered[1]) {
-                renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[5], false);
-            }
-            if (!tIsCovered[2]) {
-                renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[5], false);
-            }
-            if (!tIsCovered[3]) {
-                renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[5], false);
-            }
-            renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[5], false);
-            renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[5], false);
-        }
-        aBlock.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
-        aRenderer.setRenderBoundsFromBlock(aBlock);
-
-        return true;
-    }
-
     public static void renderNegativeYFacing(IBlockAccess aWorld, RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ, ITexture[] aIcon, boolean aFullBlock) {
         if (aWorld != null) {
             if ((aFullBlock) && (!aBlock.shouldSideBeRendered(aWorld, aX, aY - 1, aZ, 0))) return;
@@ -497,58 +663,6 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
         }
     }
 
-    public void renderInventoryBlock(Block aBlock, int aMeta, int aModelID, RenderBlocks aRenderer) {
-        aRenderer.enableAO = false;
-        if ((aBlock instanceof GT_Block_Machines)) {
-            if ((aMeta > 0) && (aMeta < GregTech_API.METATILEENTITIES.length) && (GregTech_API.METATILEENTITIES[aMeta] != null) &&
-                    (!GregTech_API.METATILEENTITIES[aMeta].renderInInventory(aBlock, aMeta, aRenderer))) {
-                renderNormalInventoryMetaTileEntity(aBlock, aMeta, aRenderer);
-            }
-        } else if ((aBlock instanceof GT_Block_Ores_Abstract)) {
-            GT_TileEntity_Ores tTileEntity = new GT_TileEntity_Ores();
-            tTileEntity.mMetaData = ((short) aMeta);
-
-            aBlock.setBlockBoundsForItemRender();
-            aRenderer.setRenderBoundsFromBlock(aBlock);
-
-            GL11.glRotatef(90.0F, 0.0F, 1.0F, 0.0F);
-            GL11.glTranslatef(-0.5F, -0.5F, -0.5F);
-
-            Tessellator.instance.startDrawingQuads();
-            Tessellator.instance.setNormal(0.0F, -1.0F, 0.0F);
-            renderNegativeYFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 0), true);
-            Tessellator.instance.draw();
-
-            Tessellator.instance.startDrawingQuads();
-            Tessellator.instance.setNormal(0.0F, 1.0F, 0.0F);
-            renderPositiveYFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 1), true);
-            Tessellator.instance.draw();
-
-            Tessellator.instance.startDrawingQuads();
-            Tessellator.instance.setNormal(0.0F, 0.0F, -1.0F);
-            renderNegativeZFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 2), true);
-            Tessellator.instance.draw();
-
-            Tessellator.instance.startDrawingQuads();
-            Tessellator.instance.setNormal(0.0F, 0.0F, 1.0F);
-            renderPositiveZFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 3), true);
-            Tessellator.instance.draw();
-
-            Tessellator.instance.startDrawingQuads();
-            Tessellator.instance.setNormal(-1.0F, 0.0F, 0.0F);
-            renderNegativeXFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 4), true);
-            Tessellator.instance.draw();
-
-            Tessellator.instance.startDrawingQuads();
-            Tessellator.instance.setNormal(1.0F, 0.0F, 0.0F);
-            renderPositiveXFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 5), true);
-            Tessellator.instance.draw();
-        }
-        aBlock.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
-        aRenderer.setRenderBoundsFromBlock(aBlock);
-        GL11.glTranslatef(0.5F, 0.5F, 0.5F);
-    }
-
     public boolean renderWorldBlock(IBlockAccess aWorld, int aX, int aY, int aZ, Block aBlock, int aModelID, RenderBlocks aRenderer) {
         aRenderer.enableAO = Minecraft.isAmbientOcclusionEnabled() && GT_Mod.gregtechproxy.mRenderTileAmbientOcclusion;
         TileEntity tileEntity = aWorld.getTileEntity(aX, aY, aZ);
-- 
cgit 


From 8217982caf5d94cf5ea003bc06c8eb26eec48eef Mon Sep 17 00:00:00 2001
From: Léa Gris <lea.gris@noiraude.net>
Date: Wed, 21 Apr 2021 01:32:43 +0200
Subject: fix(rendering): itemblocks inventory brightness and orientation

- Fix itemblock brightness and orientation to be exactly same as vanilla blocks
  in inventory.
- Revert machine front facing to the brighter left side as it eases
  differentiating them.
- Optimise inventory itemblock rendering to issue a draw quads only once
  for the entire block, rather than for each side.
---
 .../java/gregtech/api/util/LightingHelper.java     |  4 +
 .../gregtech/common/render/GT_Renderer_Block.java  | 86 ++++++++--------------
 2 files changed, 34 insertions(+), 56 deletions(-)

(limited to 'src/main/java/gregtech/api/util/LightingHelper.java')

diff --git a/src/main/java/gregtech/api/util/LightingHelper.java b/src/main/java/gregtech/api/util/LightingHelper.java
index 48c316d0cc..598253b7d7 100644
--- a/src/main/java/gregtech/api/util/LightingHelper.java
+++ b/src/main/java/gregtech/api/util/LightingHelper.java
@@ -56,6 +56,10 @@ public class LightingHelper {
      */
     public LightingHelper(RenderBlocks renderBlocks) {
         this.renderBlocks = renderBlocks;
+        if (renderBlocks.useInventoryTint) {
+            // Block will be rendered in an inventory, so it needs its lightness maxed
+            setLightnessOverride(1.0F);
+        }
     }
 
     /**
diff --git a/src/main/java/gregtech/common/render/GT_Renderer_Block.java b/src/main/java/gregtech/common/render/GT_Renderer_Block.java
index 51e0b8fd6f..1055991cad 100644
--- a/src/main/java/gregtech/common/render/GT_Renderer_Block.java
+++ b/src/main/java/gregtech/common/render/GT_Renderer_Block.java
@@ -450,9 +450,18 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
 
     public void renderInventoryBlock(Block aBlock, int aMeta, int aModelID, RenderBlocks aRenderer) {
         aRenderer.enableAO = false;
+        aRenderer.useInventoryTint = true;
+
+        GL11.glRotatef(90.0F, 0.0F, 1.0F, 0.0F);
+        GL11.glTranslatef(-0.5F, -0.5F, -0.5F);
+
+        Tessellator.instance.startDrawingQuads();
+
         if ((aBlock instanceof GT_Block_Machines)) {
-            if ((aMeta > 0) && (aMeta < GregTech_API.METATILEENTITIES.length) && (GregTech_API.METATILEENTITIES[aMeta] != null) &&
-                    (!GregTech_API.METATILEENTITIES[aMeta].renderInInventory(aBlock, aMeta, aRenderer))) {
+            if ((aMeta > 0)
+                    && (aMeta < GregTech_API.METATILEENTITIES.length)
+                    && (GregTech_API.METATILEENTITIES[aMeta] != null)
+                    && (!GregTech_API.METATILEENTITIES[aMeta].renderInInventory(aBlock, aMeta, aRenderer))) {
                 renderNormalInventoryMetaTileEntity(aBlock, aMeta, aRenderer);
             }
         } else if ((aBlock instanceof GT_Block_Ores_Abstract)) {
@@ -462,41 +471,32 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
             aBlock.setBlockBoundsForItemRender();
             aRenderer.setRenderBoundsFromBlock(aBlock);
 
-            GL11.glTranslatef(-0.5F, -0.5F, -0.5F);
-
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, -1.0F, 0.0F);
-            renderNegativeYFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 0), true);
-            Tessellator.instance.draw();
+            renderNegativeYFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) DOWN.ordinal()), true);
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 1.0F, 0.0F);
-            renderPositiveYFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 1), true);
-            Tessellator.instance.draw();
+            renderPositiveYFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) UP.ordinal()), true);
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 0.0F, -1.0F);
-            renderNegativeZFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 2), true);
-            Tessellator.instance.draw();
+            renderNegativeZFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) NORTH.ordinal()), true);
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 0.0F, 1.0F);
-            renderPositiveZFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 3), true);
-            Tessellator.instance.draw();
+            renderPositiveZFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) SOUTH.ordinal()), true);
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(-1.0F, 0.0F, 0.0F);
-            renderNegativeXFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 4), true);
-            Tessellator.instance.draw();
+            renderNegativeXFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) WEST.ordinal()), true);
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(1.0F, 0.0F, 0.0F);
-            renderPositiveXFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) 5), true);
-            Tessellator.instance.draw();
+            renderPositiveXFacing(null, aRenderer, aBlock, 0, 0, 0, tTileEntity.getTexture(aBlock, (byte) EAST.ordinal()), true);
+
         }
-        aBlock.setBlockBounds(blockMin, blockMin, blockMin, 1.0F, 1.0F, 1.0F);
+        Tessellator.instance.draw();
+
+        aBlock.setBlockBounds(blockMin, blockMin, blockMin, blockMax, blockMax, blockMax);
         aRenderer.setRenderBoundsFromBlock(aBlock);
+
         GL11.glTranslatef(0.5F, 0.5F, 0.5F);
+        aRenderer.useInventoryTint = false;
     }
 
     private static void renderNormalInventoryMetaTileEntity(Block aBlock, int aMeta, RenderBlocks aRenderer) {
@@ -512,7 +512,6 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
 
         final IGregTechTileEntity iGregTechTileEntity = tMetaTileEntity.getBaseMetaTileEntity();
 
-        GL11.glTranslatef(-0.5F, -0.5F, -0.5F);
         if ((iGregTechTileEntity instanceof IPipeRenderedTileEntity)) {
             final float tThickness = ((IPipeRenderedTileEntity) iGregTechTileEntity).getThickNess();
             final float pipeMin = (blockMax - tThickness) / 2.0F;
@@ -521,68 +520,42 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
             aBlock.setBlockBounds(blockMin, pipeMin, pipeMin, blockMax, pipeMax, pipeMax);
             aRenderer.setRenderBoundsFromBlock(aBlock);
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, -1.0F, 0.0F);
             renderNegativeYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) DOWN.ordinal(), (byte) (CONNECTED_WEST | CONNECTED_EAST), (byte) -1, false, false), true);
-            Tessellator.instance.draw();
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 1.0F, 0.0F);
             renderPositiveYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) UP.ordinal(), (byte) (CONNECTED_WEST | CONNECTED_EAST), (byte) -1, false, false), true);
-            Tessellator.instance.draw();
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 0.0F, -1.0F);
             renderNegativeZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) NORTH.ordinal(), (byte) (CONNECTED_WEST | CONNECTED_EAST), (byte) -1, false, false), true);
-            Tessellator.instance.draw();
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 0.0F, 1.0F);
             renderPositiveZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) SOUTH.ordinal(), (byte) (CONNECTED_WEST | CONNECTED_EAST), (byte) -1, false, false), true);
-            Tessellator.instance.draw();
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(-1.0F, 0.0F, 0.0F);
             renderNegativeXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) WEST.ordinal(), (byte) (CONNECTED_WEST | CONNECTED_EAST), (byte) -1, true, false), true);
-            Tessellator.instance.draw();
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(1.0F, 0.0F, 0.0F);
             renderPositiveXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) EAST.ordinal(), (byte) (CONNECTED_WEST | CONNECTED_EAST), (byte) -1, true, false), true);
         } else {
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, -1.0F, 0.0F);
-            renderNegativeYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) DOWN.ordinal(), (byte) EAST.ordinal(), (byte) -1, true, false), true);
-            Tessellator.instance.draw();
+            renderNegativeYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) DOWN.ordinal(), (byte) WEST.ordinal(), (byte) -1, true, false), true);
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 1.0F, 0.0F);
-            renderPositiveYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) UP.ordinal(), (byte) EAST.ordinal(), (byte) -1, true, false), true);
-            Tessellator.instance.draw();
+            renderPositiveYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) UP.ordinal(), (byte) WEST.ordinal(), (byte) -1, true, false), true);
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 0.0F, -1.0F);
-            renderNegativeZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) NORTH.ordinal(), (byte) EAST.ordinal(), (byte) -1, true, false), true);
-            Tessellator.instance.draw();
+            renderNegativeZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) NORTH.ordinal(), (byte) WEST.ordinal(), (byte) -1, true, false), true);
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(0.0F, 0.0F, 1.0F);
-            renderPositiveZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) SOUTH.ordinal(), (byte) EAST.ordinal(), (byte) -1, true, false), true);
-            Tessellator.instance.draw();
+            renderPositiveZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) SOUTH.ordinal(), (byte) WEST.ordinal(), (byte) -1, true, false), true);
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(-1.0F, 0.0F, 0.0F);
-            renderNegativeXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) WEST.ordinal(), (byte) EAST.ordinal(), (byte) -1, true, false), true);
-            Tessellator.instance.draw();
+            renderNegativeXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) WEST.ordinal(), (byte) WEST.ordinal(), (byte) -1, true, false), true);
 
-            Tessellator.instance.startDrawingQuads();
             Tessellator.instance.setNormal(1.0F, 0.0F, 0.0F);
-            renderPositiveXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) EAST.ordinal(), (byte) EAST.ordinal(), (byte) -1, true, false), true);
+            renderPositiveXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, (byte) EAST.ordinal(), (byte) WEST.ordinal(), (byte) -1, true, false), true);
         }
-        Tessellator.instance.draw();
-        aBlock.setBlockBounds(blockMin, blockMin, blockMin, blockMax, blockMax, blockMax);
-        aRenderer.setRenderBoundsFromBlock(aBlock);
-        GL11.glTranslatef(0.5F, 0.5F, 0.5F);
     }
 
     public static void renderNegativeYFacing(IBlockAccess aWorld, RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ, ITexture[] aIcon, boolean aFullBlock) {
@@ -665,6 +638,7 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
 
     public boolean renderWorldBlock(IBlockAccess aWorld, int aX, int aY, int aZ, Block aBlock, int aModelID, RenderBlocks aRenderer) {
         aRenderer.enableAO = Minecraft.isAmbientOcclusionEnabled() && GT_Mod.gregtechproxy.mRenderTileAmbientOcclusion;
+        aRenderer.useInventoryTint = false;
         TileEntity tileEntity = aWorld.getTileEntity(aX, aY, aZ);
         if (tileEntity == null) return false;
         if (tileEntity instanceof IGregTechTileEntity) {
-- 
cgit 


From 86f69a4300e0bdb5c9921f37c84bb446e464ec78 Mon Sep 17 00:00:00 2001
From: Léa Gris <lea.gris@noiraude.net>
Date: Mon, 31 May 2021 10:13:56 +0200
Subject: feat(texture API): integrate ExtendedFacing rotation

Add ExtendedFacing rotation to the texture API.
Rotatable ExtendedFacing textures can be created with:
```java
TextureFactory.builder().addIcon(IICon).extFacing().build();
```

Improve and unify internal implementation of standard oriented and glow textures.
---
 src/main/java/gregtech/GT_Mod.java                 |   3 +-
 .../gregtech/api/interfaces/ITextureBuilder.java   |   8 +
 .../java/gregtech/api/util/LightingHelper.java     |   1 +
 .../common/render/GT_RenderedGlowTexture.java      | 213 ------------
 .../gregtech/common/render/GT_RenderedTexture.java | 383 +++++++++++++++------
 .../common/render/GT_StdRenderedTexture.java       |  36 --
 .../gregtech/common/render/GT_TextureBuilder.java  |  11 +-
 7 files changed, 290 insertions(+), 365 deletions(-)
 delete mode 100644 src/main/java/gregtech/common/render/GT_RenderedGlowTexture.java
 delete mode 100644 src/main/java/gregtech/common/render/GT_StdRenderedTexture.java

(limited to 'src/main/java/gregtech/api/util/LightingHelper.java')

diff --git a/src/main/java/gregtech/GT_Mod.java b/src/main/java/gregtech/GT_Mod.java
index d9a8d72ecd..278908b9a0 100644
--- a/src/main/java/gregtech/GT_Mod.java
+++ b/src/main/java/gregtech/GT_Mod.java
@@ -1,6 +1,7 @@
 package gregtech;
 
 import com.google.common.base.Stopwatch;
+import com.gtnewhorizon.structurelib.StructureLib;
 import cpw.mods.fml.common.*;
 import cpw.mods.fml.common.event.*;
 import cpw.mods.fml.common.registry.EntityRegistry;
@@ -74,7 +75,7 @@ import static gregtech.api.enums.GT_Values.MOD_ID_FR;
 @SuppressWarnings("ALL")
 @Mod(modid = "gregtech", name = "GregTech", version = "MC1710", useMetadata = false,
         dependencies = " required-after:IC2;" +
-                " required-after:structurelib;" +
+                " required-after:" + StructureLib.MOD_ID + ";" +
                 " after:dreamcraft;" +
                 " after:Forestry;" +
                 " after:PFAAGeologica;" +
diff --git a/src/main/java/gregtech/api/interfaces/ITextureBuilder.java b/src/main/java/gregtech/api/interfaces/ITextureBuilder.java
index 8a4d715ccb..d72b538243 100644
--- a/src/main/java/gregtech/api/interfaces/ITextureBuilder.java
+++ b/src/main/java/gregtech/api/interfaces/ITextureBuilder.java
@@ -1,5 +1,6 @@
 package gregtech.api.interfaces;
 
+import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
 import gregtech.api.render.TextureFactory;
 import net.minecraft.block.Block;
 import net.minecraftforge.common.util.ForgeDirection;
@@ -63,6 +64,13 @@ public interface ITextureBuilder {
      */
     ITextureBuilder stdOrient();
 
+    /**
+     * Texture will orientate from block's {@link ExtendedFacing}
+     *
+     * @return {@link ITextureBuilder} for chaining
+     */
+    ITextureBuilder extFacing();
+
     /**
      * Texture always render with full brightness to glow in the dark
      *
diff --git a/src/main/java/gregtech/api/util/LightingHelper.java b/src/main/java/gregtech/api/util/LightingHelper.java
index 598253b7d7..f131ef74a0 100644
--- a/src/main/java/gregtech/api/util/LightingHelper.java
+++ b/src/main/java/gregtech/api/util/LightingHelper.java
@@ -255,6 +255,7 @@ public class LightingHelper {
 
         } else {
 
+            if (hasBrightnessOverride) tessellator.setBrightness(brightnessOverride);
             tessellator.setColorOpaque_F(rgb[0] * lightness, rgb[1] * lightness, rgb[2] * lightness);
 
         }
diff --git a/src/main/java/gregtech/common/render/GT_RenderedGlowTexture.java b/src/main/java/gregtech/common/render/GT_RenderedGlowTexture.java
deleted file mode 100644
index 899e4d7c5d..0000000000
--- a/src/main/java/gregtech/common/render/GT_RenderedGlowTexture.java
+++ /dev/null
@@ -1,213 +0,0 @@
-package gregtech.common.render;
-
-import gregtech.GT_Mod;
-import gregtech.api.enums.Textures.BlockIcons;
-import gregtech.api.interfaces.IColorModulationContainer;
-import gregtech.api.interfaces.IIconContainer;
-import gregtech.api.interfaces.ITexture;
-import net.minecraft.block.Block;
-import net.minecraft.client.renderer.RenderBlocks;
-import net.minecraft.client.renderer.Tessellator;
-import net.minecraft.util.IIcon;
-
-import static gregtech.api.util.LightingHelper.MAX_BRIGHTNESS;
-
-/**
- * This {@link ITexture} implementation renders texture with max brightness to glow in the dark.
- */
-
-class GT_RenderedGlowTexture implements ITexture, IColorModulationContainer {
-    protected final IIconContainer mIconContainer;
-    private final short[] mRGBa;
-
-    GT_RenderedGlowTexture(IIconContainer aIcon, short[] aRGBa, boolean allowAlpha) {
-        if (aRGBa.length != 4) throw new IllegalArgumentException("RGBa doesn't have 4 Values @ GT_RenderedTexture");
-        mIconContainer = GT_Mod.gregtechproxy.mRenderGlowTextures ? aIcon : BlockIcons.VOID;
-        mRGBa = aRGBa;
-    }
-
-    @Override
-    public short[] getRGBA() {
-        return mRGBa;
-    }
-
-    @Override
-    public void renderXNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
-        if (aRenderer.useInventoryTint) return; // TODO: Remove this once all addons have migrated to the new Texture API
-        if (!GT_Mod.gregtechproxy.mRenderGlowTextures) return;
-        final boolean enableAO = aRenderer.enableAO;
-        aRenderer.enableAO = false;
-        // TODO: Uncomment this once all addons have migrated to the new Texture API
-        //startDrawingQuads(aRenderer, -1.0f, 0.0f, 0.0f);
-        Tessellator.instance.setBrightness(MAX_BRIGHTNESS);
-        Tessellator.instance.setColorOpaque(mRGBa[0], mRGBa[1], mRGBa[2]);
-        aRenderer.renderFaceXNeg(aBlock, aX, aY, aZ, mIconContainer.getIcon());
-        if (mIconContainer.getOverlayIcon() != null) {
-            Tessellator.instance.setColorOpaque(255, 255, 255);
-            aRenderer.renderFaceXNeg(aBlock, aX, aY, aZ, mIconContainer.getOverlayIcon());
-        }
-        // TODO: Uncomment this once all addons have migrated to the new Texture API
-        //draw(aRenderer);
-        aRenderer.enableAO = enableAO;
-    }
-
-    @Override
-    public void renderXPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
-        if (aRenderer.useInventoryTint) return; // TODO: Remove this once all addons have migrated to the new Texture API
-        if (!GT_Mod.gregtechproxy.mRenderGlowTextures) return;
-        aRenderer.field_152631_f = true;
-        final boolean enableAO = aRenderer.enableAO;
-        aRenderer.enableAO = false;
-        // TODO: Uncomment this once all addons have migrated to the new Texture API
-        //startDrawingQuads(aRenderer, 1.0f, 0.0f, 0.0f);
-        Tessellator.instance.setBrightness(MAX_BRIGHTNESS);
-        Tessellator.instance.setColorOpaque(mRGBa[0], mRGBa[1], mRGBa[2]);
-        aRenderer.renderFaceXPos(aBlock, aX, aY, aZ, mIconContainer.getIcon());
-        if (mIconContainer.getOverlayIcon() != null) {
-            Tessellator.instance.setColorOpaque(255, 255, 255);
-            aRenderer.renderFaceXPos(aBlock, aX, aY, aZ, mIconContainer.getOverlayIcon());
-        }
-        // TODO: Uncomment this once all addons have migrated to the new Texture API
-        //draw(aRenderer);
-        aRenderer.field_152631_f = false;
-        aRenderer.enableAO = enableAO;
-    }
-
-    @Override
-    public void renderYNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
-        if (aRenderer.useInventoryTint) return; // TODO: Remove this once all addons have migrated to the new Texture API
-        if (!GT_Mod.gregtechproxy.mRenderGlowTextures) return;
-        final boolean enableAO = aRenderer.enableAO;
-        // TODO: Uncomment this once all addons have migrated to the new Texture API
-        //startDrawingQuads(aRenderer, 0.0f, -1.0f, 0.0f);
-        final Tessellator tessellator = Tessellator.instance;
-        IIcon aIcon = mIconContainer.getIcon();
-
-        float minU = aIcon.getInterpolatedU((1.0D - aRenderer.renderMaxX) * 16.0D);
-        float maxU = aIcon.getInterpolatedU((1.0D - aRenderer.renderMinX) * 16.0D);
-        float minV = aIcon.getInterpolatedV(aRenderer.renderMinZ * 16.0D);
-        float maxV = aIcon.getInterpolatedV(aRenderer.renderMaxZ * 16.0D);
-
-        if (aRenderer.renderMinX < 0.0D || aRenderer.renderMaxX > 1.0D) {
-            minU = 16.0F - aIcon.getMaxU();
-            maxU = 16.0F - aIcon.getMinU();
-        }
-
-        if (aRenderer.renderMinZ < 0.0D || aRenderer.renderMaxZ > 1.0D) {
-            minV = aIcon.getMinV();
-            maxV = aIcon.getMaxV();
-        }
-
-        double minX = aX + aRenderer.renderMinX;
-        double maxX = aX + aRenderer.renderMaxX;
-        double minY = aY + aRenderer.renderMinY;
-        double minZ = aZ + aRenderer.renderMinZ;
-        double maxZ = aZ + aRenderer.renderMaxZ;
-
-        Tessellator.instance.setBrightness(MAX_BRIGHTNESS);
-        Tessellator.instance.setColorOpaque(mRGBa[0], mRGBa[1], mRGBa[2]);
-
-        tessellator.addVertexWithUV(minX, minY, maxZ, maxU, maxV);
-        tessellator.addVertexWithUV(minX, minY, minZ, maxU, minV);
-        tessellator.addVertexWithUV(maxX, minY, minZ, minU, minV);
-        tessellator.addVertexWithUV(maxX, minY, maxZ, minU, maxV);
-
-        if (mIconContainer.getOverlayIcon() != null) {
-            minU = aIcon.getInterpolatedU((1.0D - aRenderer.renderMaxX) * 16.0D);
-            maxU = aIcon.getInterpolatedU((1.0D - aRenderer.renderMinX) * 16.0D);
-            minV = aIcon.getInterpolatedV(aRenderer.renderMinZ * 16.0D);
-            maxV = aIcon.getInterpolatedV(aRenderer.renderMaxZ * 16.0D);
-
-            if (aRenderer.renderMinX < 0.0D || aRenderer.renderMaxX > 1.0D) {
-                minU = 16.0F - aIcon.getMaxU();
-                maxU = 16.0F - aIcon.getMinU();
-            }
-
-            if (aRenderer.renderMinZ < 0.0D || aRenderer.renderMaxZ > 1.0D) {
-                minV = aIcon.getMinV();
-                maxV = aIcon.getMaxV();
-            }
-
-            minX = aX + (float) aRenderer.renderMinX;
-            maxX = aX + (float) aRenderer.renderMaxX;
-            minY = aY + (float) aRenderer.renderMinY;
-            minZ = aZ + (float) aRenderer.renderMinZ;
-            maxZ = aZ + (float) aRenderer.renderMaxZ;
-
-            Tessellator.instance.setColorOpaque(255, 255, 255);
-            tessellator.addVertexWithUV(minX, minY, maxZ, maxU, maxV);
-            tessellator.addVertexWithUV(minX, minY, minZ, maxU, minV);
-            tessellator.addVertexWithUV(maxX, minY, minZ, minU, minV);
-            tessellator.addVertexWithUV(maxX, minY, maxZ, minU, maxV);
-        }
-        // TODO: Uncomment this once all addons have migrated to the new Texture API
-        //draw(aRenderer);
-        aRenderer.enableAO = enableAO;
-    }
-
-    @Override
-    public void renderYPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
-        if (aRenderer.useInventoryTint) return; // TODO: Remove this once all addons have migrated to the new Texture API
-        if (!GT_Mod.gregtechproxy.mRenderGlowTextures) return;
-        final boolean enableAO = aRenderer.enableAO;
-        aRenderer.enableAO = false;
-        // TODO: Uncomment this once all addons have migrated to the new Texture API
-        //startDrawingQuads(aRenderer, 0.0f, 1.0f, 0.0f);
-        Tessellator.instance.setBrightness(MAX_BRIGHTNESS);
-        Tessellator.instance.setColorOpaque(mRGBa[0], mRGBa[1], mRGBa[2]);
-        aRenderer.renderFaceYPos(aBlock, aX, aY, aZ, mIconContainer.getIcon());
-        if (mIconContainer.getOverlayIcon() != null) {
-            Tessellator.instance.setColorOpaque(255, 255, 255);
-            aRenderer.renderFaceYPos(aBlock, aX, aY, aZ, mIconContainer.getOverlayIcon());
-        }
-        // TODO: Uncomment this once all addons have migrated to the new Texture API
-        //draw(aRenderer);
-        aRenderer.enableAO = enableAO;
-    }
-
-    @Override
-    public void renderZNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
-        if (aRenderer.useInventoryTint) return; // TODO: Remove this once all addons have migrated to the new Texture API
-        if (!GT_Mod.gregtechproxy.mRenderGlowTextures) return;
-        final boolean enableAO = aRenderer.enableAO;
-        aRenderer.enableAO = false;
-        aRenderer.field_152631_f = true;
-        // TODO: Uncomment this once all addons have migrated to the new Texture API
-        //startDrawingQuads(aRenderer, 0.0f, 0.0f, -1.0f);
-        Tessellator.instance.setBrightness(MAX_BRIGHTNESS);
-        Tessellator.instance.setColorOpaque(mRGBa[0], mRGBa[1], mRGBa[2]);
-        aRenderer.renderFaceZNeg(aBlock, aX, aY, aZ, mIconContainer.getIcon());
-        if (mIconContainer.getOverlayIcon() != null) {
-            Tessellator.instance.setColorOpaque(255, 255, 255);
-            aRenderer.renderFaceZNeg(aBlock, aX, aY, aZ, mIconContainer.getOverlayIcon());
-        }
-        // TODO: Uncomment this once all addons have migrated to the new Texture API
-        //draw(aRenderer);
-        aRenderer.field_152631_f = false;
-        aRenderer.enableAO = enableAO;
-    }
-
-    @Override
-    public void renderZPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
-        if (aRenderer.useInventoryTint) return; // TODO: Remove this once all addons have migrated to the new Texture API
-        if (!GT_Mod.gregtechproxy.mRenderGlowTextures) return;
-        final boolean enableAO = aRenderer.enableAO;
-        aRenderer.enableAO = false;
-        // TODO: Uncomment this once all addons have migrated to the new Texture API
-        //startDrawingQuads(aRenderer, 0.0f, 0.0f, 1.0f);
-        Tessellator.instance.setBrightness(MAX_BRIGHTNESS);
-        Tessellator.instance.setColorOpaque(mRGBa[0], mRGBa[1], mRGBa[2]);
-        aRenderer.renderFaceZPos(aBlock, aX, aY, aZ, mIconContainer.getIcon());
-        if (mIconContainer.getOverlayIcon() != null) {
-            aRenderer.renderFaceZPos(aBlock, aX, aY, aZ, mIconContainer.getOverlayIcon());
-        }
-        // TODO: Uncomment this once all addons have migrated to the new Texture API
-        //draw(aRenderer);
-        aRenderer.enableAO = enableAO;
-    }
-
-    @Override
-    public boolean isValidTexture() {
-        return mIconContainer != null;
-    }
-}
diff --git a/src/main/java/gregtech/common/render/GT_RenderedTexture.java b/src/main/java/gregtech/common/render/GT_RenderedTexture.java
index 9e76634385..135ebf28c6 100644
--- a/src/main/java/gregtech/common/render/GT_RenderedTexture.java
+++ b/src/main/java/gregtech/common/render/GT_RenderedTexture.java
@@ -1,55 +1,92 @@
 package gregtech.common.render;
 
+import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider;
+import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
+import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation;
+import gregtech.GT_Mod;
 import gregtech.api.interfaces.IColorModulationContainer;
 import gregtech.api.interfaces.IIconContainer;
 import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
 import gregtech.api.util.LightingHelper;
 import net.minecraft.block.Block;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.IconFlipped;
 import net.minecraft.client.renderer.RenderBlocks;
 import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.init.Blocks;
+import net.minecraft.tileentity.TileEntity;
 import net.minecraft.util.IIcon;
+import net.minecraft.world.World;
 import net.minecraftforge.common.util.ForgeDirection;
 
+import static gregtech.api.util.LightingHelper.MAX_BRIGHTNESS;
+
 class GT_RenderedTexture implements ITexture, IColorModulationContainer {
     protected final IIconContainer mIconContainer;
     private final short[] mRGBa;
+    private final boolean glow;
+    private final boolean stdOrient;
+    private final boolean useExtFacing;
 
-    GT_RenderedTexture(IIconContainer aIcon, short[] aRGBa, boolean allowAlpha) {
+    GT_RenderedTexture(IIconContainer aIcon, short[] aRGBa, boolean allowAlpha, boolean glow, boolean stdOrient, boolean extFacing) {
         if (aRGBa.length != 4) throw new IllegalArgumentException("RGBa doesn't have 4 Values @ GT_RenderedTexture");
         mIconContainer = aIcon;
         mRGBa = aRGBa;
+        this.glow = glow;
+        this.stdOrient = stdOrient;
+        this.useExtFacing = extFacing;
     }
 
     @Override
     public void renderXPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
-        aRenderer.field_152631_f = true;
         // TODO: Uncomment this once all addons have migrated to the new Texture API
         //startDrawingQuads(aRenderer, 1.0f, 0.0f, 0.0f);
+        final boolean enableAO = aRenderer.enableAO;
         LightingHelper lighting = new LightingHelper(aRenderer);
-        lighting.setupLightingXPos(aBlock, aX, aY, aZ)
-                .setupColor(ForgeDirection.EAST.ordinal(), mRGBa);
-        aRenderer.renderFaceXPos(aBlock, aX, aY, aZ, mIconContainer.getIcon());
+        if (glow) {
+            if (aRenderer.useInventoryTint)
+                return; // TODO: Remove this once all addons have migrated to the new Texture API
+            if (!GT_Mod.gregtechproxy.mRenderGlowTextures) return;
+            aRenderer.enableAO = false;
+            lighting.setLightnessOverride(1.0F);
+            if (enableAO) lighting.setBrightnessOverride(MAX_BRIGHTNESS);
+        }
+        lighting.setupLightingXPos(aBlock, aX, aY, aZ).setupColor(ForgeDirection.EAST.ordinal(), mRGBa);
+        ExtendedFacing rotation = getExtendedFacing(aX, aY, aZ);
+        renderFaceXPos(aRenderer, aX, aY, aZ, mIconContainer.getIcon(), rotation);
         if (mIconContainer.getOverlayIcon() != null) {
             lighting.setupColor(ForgeDirection.EAST.ordinal(), 0xffffff);
-            aRenderer.renderFaceXPos(aBlock, aX, aY, aZ, mIconContainer.getOverlayIcon());
+            renderFaceXPos(aRenderer, aX, aY, aZ, mIconContainer.getOverlayIcon(), rotation);
         }
+        aRenderer.enableAO = enableAO;
         // TODO: Uncomment this once all addons have migrated to the new Texture API
         //draw(aRenderer);
-        aRenderer.field_152631_f = false;
     }
 
     @Override
     public void renderXNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
         // TODO: Uncomment this once all addons have migrated to the new Texture API
         //startDrawingQuads(aRenderer, -1.0f, 0.0f, 0.0f);
+        final boolean enableAO = aRenderer.enableAO;
         LightingHelper lighting = new LightingHelper(aRenderer);
-        lighting.setupLightingXNeg(aBlock, aX, aY, aZ)
-                .setupColor(ForgeDirection.WEST.ordinal(), mRGBa);
-        aRenderer.renderFaceXNeg(aBlock, aX, aY, aZ, mIconContainer.getIcon());
+        if (glow) {
+            if (aRenderer.useInventoryTint)
+                return; // TODO: Remove this once all addons have migrated to the new Texture API
+            if (!GT_Mod.gregtechproxy.mRenderGlowTextures) return;
+            aRenderer.enableAO = false;
+            lighting.setLightnessOverride(1.0F);
+            if (enableAO) lighting.setBrightnessOverride(MAX_BRIGHTNESS);
+        }
+        lighting.setupLightingXNeg(aBlock, aX, aY, aZ).setupColor(ForgeDirection.WEST.ordinal(), mRGBa);
+        ExtendedFacing rotation = getExtendedFacing(aX, aY, aZ);
+        renderFaceXNeg(aRenderer, aX, aY, aZ, mIconContainer.getIcon(), rotation);
         if (mIconContainer.getOverlayIcon() != null) {
             lighting.setupColor(ForgeDirection.WEST.ordinal(), 0xffffff);
-            aRenderer.renderFaceXNeg(aBlock, aX, aY, aZ, mIconContainer.getOverlayIcon());
+            renderFaceXNeg(aRenderer, aX, aY, aZ, mIconContainer.getOverlayIcon(), rotation);
         }
+        aRenderer.enableAO = enableAO;
         // TODO: Uncomment this once all addons have migrated to the new Texture API
         //draw(aRenderer);
     }
@@ -58,14 +95,24 @@ class GT_RenderedTexture implements ITexture, IColorModulationContainer {
     public void renderYPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
         // TODO: Uncomment this once all addons have migrated to the new Texture API
         //startDrawingQuads(aRenderer, 0.0f, 1.0f, 0.0f);
+        final boolean enableAO = aRenderer.enableAO;
         LightingHelper lighting = new LightingHelper(aRenderer);
-        lighting.setupLightingYPos(aBlock, aX, aY, aZ)
-                .setupColor(ForgeDirection.UP.ordinal(), mRGBa);
-        aRenderer.renderFaceYPos(aBlock, aX, aY, aZ, mIconContainer.getIcon());
+        if (glow) {
+            if (aRenderer.useInventoryTint)
+                return; // TODO: Remove this once all addons have migrated to the new Texture API
+            if (!GT_Mod.gregtechproxy.mRenderGlowTextures) return;
+            aRenderer.enableAO = false;
+            lighting.setLightnessOverride(1.0F);
+            if (enableAO) lighting.setBrightnessOverride(MAX_BRIGHTNESS);
+        }
+        lighting.setupLightingYPos(aBlock, aX, aY, aZ).setupColor(ForgeDirection.UP.ordinal(), mRGBa);
+        ExtendedFacing rotation = getExtendedFacing(aX, aY, aZ);
+        renderFaceYPos(aRenderer, aX, aY, aZ, mIconContainer.getIcon(), rotation);
         if (mIconContainer.getOverlayIcon() != null) {
             lighting.setupColor(ForgeDirection.UP.ordinal(), 0xffffff);
-            aRenderer.renderFaceYPos(aBlock, aX, aY, aZ, mIconContainer.getOverlayIcon());
+            renderFaceYPos(aRenderer, aX, aY, aZ, mIconContainer.getOverlayIcon(), rotation);
         }
+        aRenderer.enableAO = enableAO;
         // TODO: Uncomment this once all addons have migrated to the new Texture API
         //draw(aRenderer);
     }
@@ -74,96 +121,24 @@ class GT_RenderedTexture implements ITexture, IColorModulationContainer {
     public void renderYNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
         // TODO: Uncomment this once all addons have migrated to the new Texture API
         //startDrawingQuads(aRenderer, 0.0f, -1.0f, 0.0f);
-        final Tessellator tessellator = Tessellator.instance;
-        IIcon aIcon = mIconContainer.getIcon();
-
-        float minU = aIcon.getInterpolatedU((1.0D - aRenderer.renderMaxX) * 16.0D);
-        float maxU = aIcon.getInterpolatedU((1.0D - aRenderer.renderMinX) * 16.0D);
-        float minV = aIcon.getInterpolatedV(aRenderer.renderMinZ * 16.0D);
-        float maxV = aIcon.getInterpolatedV(aRenderer.renderMaxZ * 16.0D);
-
-        if (aRenderer.renderMinX < 0.0D || aRenderer.renderMaxX > 1.0D) {
-            minU = 16.0F - aIcon.getMaxU();
-            maxU = 16.0F - aIcon.getMinU();
-        }
-
-        if (aRenderer.renderMinZ < 0.0D || aRenderer.renderMaxZ > 1.0D) {
-            minV = aIcon.getMinV();
-            maxV = aIcon.getMaxV();
-        }
-
-        double minX = aX + aRenderer.renderMinX;
-        double maxX = aX + aRenderer.renderMaxX;
-        double minY = aY + aRenderer.renderMinY;
-        double minZ = aZ + aRenderer.renderMinZ;
-        double maxZ = aZ + aRenderer.renderMaxZ;
-
+        final boolean enableAO = aRenderer.enableAO;
         LightingHelper lighting = new LightingHelper(aRenderer);
-        lighting.setupLightingYNeg(aBlock, aX, aY, aZ)
-                .setupColor(ForgeDirection.DOWN.ordinal(), mRGBa);
-
-        if (aRenderer.enableAO) {
-            tessellator.setColorOpaque_F(aRenderer.colorRedTopLeft, aRenderer.colorGreenTopLeft, aRenderer.colorBlueTopLeft);
-            tessellator.setBrightness(aRenderer.brightnessTopLeft);
-            tessellator.addVertexWithUV(minX, minY, maxZ, maxU, maxV);
-            tessellator.setColorOpaque_F(aRenderer.colorRedBottomLeft, aRenderer.colorGreenBottomLeft, aRenderer.colorBlueBottomLeft);
-            tessellator.setBrightness(aRenderer.brightnessBottomLeft);
-            tessellator.addVertexWithUV(minX, minY, minZ, maxU, minV);
-            tessellator.setColorOpaque_F(aRenderer.colorRedBottomRight, aRenderer.colorGreenBottomRight, aRenderer.colorBlueBottomRight);
-            tessellator.setBrightness(aRenderer.brightnessBottomRight);
-            tessellator.addVertexWithUV(maxX, minY, minZ, minU, minV);
-            tessellator.setColorOpaque_F(aRenderer.colorRedTopRight, aRenderer.colorGreenTopRight, aRenderer.colorBlueTopRight);
-            tessellator.setBrightness(aRenderer.brightnessTopRight);
-        } else {
-            tessellator.addVertexWithUV(minX, minY, maxZ, maxU, maxV);
-            tessellator.addVertexWithUV(minX, minY, minZ, maxU, minV);
-            tessellator.addVertexWithUV(maxX, minY, minZ, minU, minV);
-        }
-        tessellator.addVertexWithUV(maxX, minY, maxZ, minU, maxV);
-
+        if (glow) {
+            if (aRenderer.useInventoryTint)
+                return; // TODO: Remove this once all addons have migrated to the new Texture API
+            if (!GT_Mod.gregtechproxy.mRenderGlowTextures) return;
+            aRenderer.enableAO = false;
+            lighting.setLightnessOverride(1.0F);
+            if (enableAO) lighting.setBrightnessOverride(MAX_BRIGHTNESS);
+        }
+        lighting.setupLightingYNeg(aBlock, aX, aY, aZ).setupColor(ForgeDirection.DOWN.ordinal(), mRGBa);
+        ExtendedFacing rotation = getExtendedFacing(aX, aY, aZ);
+        renderFaceYNeg(aRenderer, aX, aY, aZ, mIconContainer.getIcon(), rotation);
         if (mIconContainer.getOverlayIcon() != null) {
-            minU = aIcon.getInterpolatedU((1.0D - aRenderer.renderMaxX) * 16.0D);
-            maxU = aIcon.getInterpolatedU((1.0D - aRenderer.renderMinX) * 16.0D);
-            minV = aIcon.getInterpolatedV(aRenderer.renderMinZ * 16.0D);
-            maxV = aIcon.getInterpolatedV(aRenderer.renderMaxZ * 16.0D);
-
-            if (aRenderer.renderMinX < 0.0D || aRenderer.renderMaxX > 1.0D) {
-                minU = 16.0F - aIcon.getMaxU();
-                maxU = 16.0F - aIcon.getMinU();
-            }
-
-            if (aRenderer.renderMinZ < 0.0D || aRenderer.renderMaxZ > 1.0D) {
-                minV = aIcon.getMinV();
-                maxV = aIcon.getMaxV();
-            }
-
-            minX = aX + (float)aRenderer.renderMinX;
-            maxX = aX + (float)aRenderer.renderMaxX;
-            minY = aY + (float)aRenderer.renderMinY;
-            minZ = aZ + (float)aRenderer.renderMinZ;
-            maxZ = aZ + (float)aRenderer.renderMaxZ;
-
-            lighting.setupColor(ForgeDirection.DOWN.ordinal(), 0xffffff);
-
-            if (aRenderer.enableAO) {
-                tessellator.setColorOpaque_F(aRenderer.colorRedTopLeft, aRenderer.colorGreenTopLeft, aRenderer.colorBlueTopLeft);
-                tessellator.setBrightness(aRenderer.brightnessTopLeft);
-                tessellator.addVertexWithUV(minX, minY, maxZ, maxU, maxV);
-                tessellator.setColorOpaque_F(aRenderer.colorRedBottomLeft, aRenderer.colorGreenBottomLeft, aRenderer.colorBlueBottomLeft);
-                tessellator.setBrightness(aRenderer.brightnessBottomLeft);
-                tessellator.addVertexWithUV(minX, minY, minZ, maxU, minV);
-                tessellator.setColorOpaque_F(aRenderer.colorRedBottomRight, aRenderer.colorGreenBottomRight, aRenderer.colorBlueBottomRight);
-                tessellator.setBrightness(aRenderer.brightnessBottomRight);
-                tessellator.addVertexWithUV(maxX, minY, minZ, minU, minV);
-                tessellator.setColorOpaque_F(aRenderer.colorRedTopRight, aRenderer.colorGreenTopRight, aRenderer.colorBlueTopRight);
-                tessellator.setBrightness(aRenderer.brightnessTopRight);
-            } else {
-                tessellator.addVertexWithUV(minX, minY, maxZ, maxU, maxV);
-                tessellator.addVertexWithUV(minX, minY, minZ, maxU, minV);
-                tessellator.addVertexWithUV(maxX, minY, minZ, minU, minV);
-            }
-            tessellator.addVertexWithUV(maxX, minY, maxZ, minU, maxV);
+            Tessellator.instance.setColorRGBA(255, 255, 255, 255);
+            renderFaceYNeg(aRenderer, aX, aY, aZ, mIconContainer.getOverlayIcon(), rotation);
         }
+        aRenderer.enableAO = enableAO;
         // TODO: Uncomment this once all addons have migrated to the new Texture API
         //draw(aRenderer);
     }
@@ -172,14 +147,24 @@ class GT_RenderedTexture implements ITexture, IColorModulationContainer {
     public void renderZPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
         // TODO: Uncomment this once all addons have migrated to the new Texture API
         //startDrawingQuads(aRenderer, 0.0f, 0.0f, 1.0f);
+        final boolean enableAO = aRenderer.enableAO;
         LightingHelper lighting = new LightingHelper(aRenderer);
-        lighting.setupLightingZPos(aBlock, aX, aY, aZ)
-                .setupColor(ForgeDirection.SOUTH.ordinal(), mRGBa);
-        aRenderer.renderFaceZPos(aBlock, aX, aY, aZ, mIconContainer.getIcon());
+        if (glow) {
+            if (aRenderer.useInventoryTint)
+                return; // TODO: Remove this once all addons have migrated to the new Texture API
+            if (!GT_Mod.gregtechproxy.mRenderGlowTextures) return;
+            aRenderer.enableAO = false;
+            lighting.setLightnessOverride(1.0F);
+            if (enableAO) lighting.setBrightnessOverride(MAX_BRIGHTNESS);
+        }
+        lighting.setupLightingZPos(aBlock, aX, aY, aZ).setupColor(ForgeDirection.SOUTH.ordinal(), mRGBa);
+        ExtendedFacing rotation = getExtendedFacing(aX, aY, aZ);
+        renderFaceZPos(aRenderer, aX, aY, aZ, mIconContainer.getIcon(), rotation);
         if (mIconContainer.getOverlayIcon() != null) {
             lighting.setupColor(ForgeDirection.SOUTH.ordinal(), 0xffffff);
-            aRenderer.renderFaceZPos(aBlock, aX, aY, aZ, mIconContainer.getOverlayIcon());
+            renderFaceZPos(aRenderer, aX, aY, aZ, mIconContainer.getOverlayIcon(), rotation);
         }
+        aRenderer.enableAO = enableAO;
         // TODO: Uncomment this once all addons have migrated to the new Texture API
         //draw(aRenderer);
     }
@@ -188,18 +173,26 @@ class GT_RenderedTexture implements ITexture, IColorModulationContainer {
     public void renderZNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
         // TODO: Uncomment this once all addons have migrated to the new Texture API
         //startDrawingQuads(aRenderer, 0.0f, 0.0f, -1.0f);
-        aRenderer.field_152631_f = true;
+        final boolean enableAO = aRenderer.enableAO;
         LightingHelper lighting = new LightingHelper(aRenderer);
-        lighting.setupLightingZNeg(aBlock, aX, aY, aZ)
-                .setupColor(ForgeDirection.NORTH.ordinal(), mRGBa);
-        aRenderer.renderFaceZNeg(aBlock, aX, aY, aZ, mIconContainer.getIcon());
+        if (glow) {
+            if (aRenderer.useInventoryTint)
+                return; // TODO: Remove this once all addons have migrated to the new Texture API
+            if (!GT_Mod.gregtechproxy.mRenderGlowTextures) return;
+            aRenderer.enableAO = false;
+            lighting.setLightnessOverride(1.0F);
+            if (enableAO) lighting.setBrightnessOverride(MAX_BRIGHTNESS);
+        }
+        lighting.setupLightingZNeg(aBlock, aX, aY, aZ).setupColor(ForgeDirection.NORTH.ordinal(), mRGBa);
+        ExtendedFacing rotation = getExtendedFacing(aX, aY, aZ);
+        renderFaceZNeg(aRenderer, aX, aY, aZ, mIconContainer.getIcon(), rotation);
         if (mIconContainer.getOverlayIcon() != null) {
             lighting.setupColor(ForgeDirection.NORTH.ordinal(), 0xffffff);
-            aRenderer.renderFaceZNeg(aBlock, aX, aY, aZ, mIconContainer.getOverlayIcon());
+            renderFaceZNeg(aRenderer, aX, aY, aZ, mIconContainer.getOverlayIcon(), rotation);
         }
+        aRenderer.enableAO = enableAO;
         // TODO: Uncomment this once all addons have migrated to the new Texture API
         //draw(aRenderer);
-        aRenderer.field_152631_f = false;
     }
 
     @Override
@@ -211,4 +204,170 @@ class GT_RenderedTexture implements ITexture, IColorModulationContainer {
     public boolean isValidTexture() {
         return mIconContainer != null;
     }
+
+    /**
+     * Renders the given texture to the bottom face of the block. Args: block, x, y, z, texture
+     */
+    protected void renderFaceYNeg(RenderBlocks aRenderer, double x, double y, double z, IIcon icon, ExtendedFacing extendedFacing) {
+
+        switch (useExtFacing ? extendedFacing.getRotation() : Rotation.NORMAL) {
+            case COUNTER_CLOCKWISE:
+                aRenderer.uvRotateBottom = 2;
+                break;
+            case CLOCKWISE:
+                aRenderer.uvRotateBottom = 1;
+                break;
+            case UPSIDE_DOWN:
+                aRenderer.uvRotateBottom = 3;
+                break;
+            default:
+                aRenderer.uvRotateBottom = 0;
+                break;
+        }
+
+        aRenderer.renderFaceYNeg(Blocks.air, x, y, z, new IconFlipped(icon, !stdOrient, false));
+        aRenderer.uvRotateBottom = 0;
+    }
+
+    /**
+     * Renders the given texture to the top face of the block. Args: block, x, y, z, texture
+     */
+    protected void renderFaceYPos(RenderBlocks aRenderer, double x, double y, double z, IIcon icon, ExtendedFacing extendedFacing) {
+
+        switch (useExtFacing ? extendedFacing.getRotation() : Rotation.NORMAL) {
+            case COUNTER_CLOCKWISE:
+                aRenderer.uvRotateTop = 2;
+                break;
+            case CLOCKWISE:
+                aRenderer.uvRotateTop = 1;
+                break;
+            case UPSIDE_DOWN:
+                aRenderer.uvRotateTop = 3;
+                break;
+            default:
+                aRenderer.uvRotateTop = 0;
+                break;
+        }
+
+        aRenderer.renderFaceYPos(Blocks.air, x, y, z, icon);
+        aRenderer.uvRotateTop = 0;
+    }
+
+    /**
+     * Renders the given texture to the north (z-negative) face of the block.  Args: block, x, y, z, texture
+     */
+    protected void renderFaceZNeg(RenderBlocks aRenderer, double x, double y, double z, IIcon icon, ExtendedFacing extendedFacing) {
+        aRenderer.field_152631_f = true;
+        // **NOT A BUG**: aRenderer.uvRotateEast REALLY CONTROLS THE ROTATION OF THE NORTH SIDE
+        switch (useExtFacing ? extendedFacing.getRotation() : Rotation.NORMAL) {
+            case COUNTER_CLOCKWISE:
+                aRenderer.uvRotateEast = 2;
+                break;
+            case CLOCKWISE:
+                aRenderer.uvRotateEast = 1;
+                break;
+            case UPSIDE_DOWN:
+                aRenderer.uvRotateEast = 3;
+                break;
+            default:
+                aRenderer.uvRotateEast = 0;
+                break;
+        }
+
+        aRenderer.renderFaceZNeg(Blocks.air, x, y, z, icon);
+        aRenderer.uvRotateEast = 0;
+        aRenderer.field_152631_f = false;
+    }
+
+    /**
+     * Renders the given texture to the south (z-positive) face of the block.  Args: block, x, y, z, texture
+     */
+    protected void renderFaceZPos(RenderBlocks aRenderer, double x, double y, double z, IIcon icon, ExtendedFacing extendedFacing) {
+        // **NOT A BUG**: aRenderer.uvRotateWest REALLY CONTROLS THE ROTATION OF THE SOUTH SIDE
+        switch (useExtFacing ? extendedFacing.getRotation() : Rotation.NORMAL) {
+            case COUNTER_CLOCKWISE:
+                aRenderer.uvRotateWest = 2;
+                break;
+            case CLOCKWISE:
+                aRenderer.uvRotateWest = 1;
+                break;
+            case UPSIDE_DOWN:
+                aRenderer.uvRotateWest = 3;
+                break;
+            default:
+                aRenderer.uvRotateWest = 0;
+                break;
+        }
+
+        aRenderer.renderFaceZPos(Blocks.air, x, y, z, icon);
+        aRenderer.uvRotateWest = 0;
+    }
+
+    /**
+     * Renders the given texture to the west (x-negative) face of the block.  Args: block, x, y, z, texture
+     */
+    protected void renderFaceXNeg(RenderBlocks aRenderer, double x, double y, double z, IIcon icon, ExtendedFacing extendedFacing) {
+        // **NOT A BUG**: aRenderer.uvRotateNorth REALLY CONTROLS THE ROTATION OF THE WEST SIDE
+        switch (useExtFacing ? extendedFacing.getRotation() : Rotation.NORMAL) {
+            case COUNTER_CLOCKWISE:
+                aRenderer.uvRotateNorth = 2;
+                break;
+            case CLOCKWISE:
+                aRenderer.uvRotateNorth = 1;
+                break;
+            case UPSIDE_DOWN:
+                aRenderer.uvRotateNorth = 3;
+                break;
+            default:
+                aRenderer.uvRotateNorth = 0;
+                break;
+        }
+
+        aRenderer.renderFaceXNeg(Blocks.air, x, y, z, icon);
+        aRenderer.uvRotateNorth = 0;
+    }
+
+    /**
+     * Renders the given texture to the east (x-positive) face of the block.  Args: block, x, y, z, texture
+     */
+    protected void renderFaceXPos(RenderBlocks aRenderer, double x, double y, double z, IIcon icon, ExtendedFacing extendedFacing) {
+        aRenderer.field_152631_f = true;
+        // **NOT A BUG**: aRenderer.uvRotateSouth REALLY CONTROLS THE ROTATION OF THE EAST SIDE
+        switch (useExtFacing ? extendedFacing.getRotation() : Rotation.NORMAL) {
+            case COUNTER_CLOCKWISE:
+                aRenderer.uvRotateSouth = 2;
+                break;
+            case CLOCKWISE:
+                aRenderer.uvRotateSouth = 1;
+                break;
+            case UPSIDE_DOWN:
+                aRenderer.uvRotateSouth = 3;
+                break;
+            default:
+                aRenderer.uvRotateSouth = 0;
+                break;
+        }
+
+        aRenderer.renderFaceXPos(Blocks.air, x, y, z, icon);
+        aRenderer.uvRotateSouth = 0;
+        aRenderer.field_152631_f = false;
+    }
+
+    private ExtendedFacing getExtendedFacing(int x, int y, int z) {
+        if (stdOrient) return ExtendedFacing.DEFAULT;
+        World w = Minecraft.getMinecraft().theWorld;
+        if (w == null) return ExtendedFacing.DEFAULT;
+        TileEntity te = w.getTileEntity(x, y, z);
+        if (te instanceof IGregTechTileEntity) {
+            IMetaTileEntity meta = ((IGregTechTileEntity) te).getMetaTileEntity();
+            if (meta instanceof IAlignmentProvider) {
+                return ((IAlignmentProvider) meta).getAlignment().getExtendedFacing();
+            } else if (meta != null) {
+                return ExtendedFacing.of(ForgeDirection.getOrientation(meta.getBaseMetaTileEntity().getFrontFacing()));
+            }
+        } else if (te instanceof IAlignmentProvider) {
+            return ((IAlignmentProvider) te).getAlignment().getExtendedFacing();
+        }
+        return ExtendedFacing.DEFAULT;
+    }
 }
diff --git a/src/main/java/gregtech/common/render/GT_StdRenderedTexture.java b/src/main/java/gregtech/common/render/GT_StdRenderedTexture.java
deleted file mode 100644
index ba0f9d3a91..0000000000
--- a/src/main/java/gregtech/common/render/GT_StdRenderedTexture.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package gregtech.common.render;
-
-import gregtech.api.interfaces.IIconContainer;
-import gregtech.api.util.LightingHelper;
-import net.minecraft.block.Block;
-import net.minecraft.client.renderer.RenderBlocks;
-import net.minecraftforge.common.util.ForgeDirection;
-
-/**
- * This ITexture implementation extends the GT_RenderedTexture class
- * to render with bottom side flipped as with dumb blocks rendering.
- * It is used in Ore blocks rendering so they better blends with dumb block ores
- * from vanilla or other mods, when seen from bottom.
- */
-class GT_StdRenderedTexture extends GT_RenderedTexture{
-
-    GT_StdRenderedTexture(IIconContainer aIcon, short[] aRGBa, boolean allowAlpha) {
-        super(aIcon, aRGBa, allowAlpha);
-    }
-
-    @Override
-    public void renderYNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
-        // TODO: Uncomment this once all addons have migrated to the new Texture API
-        //startDrawingQuads(aRenderer, 0.0f, -1.0f, 0.0f);
-        LightingHelper lighting = new LightingHelper(aRenderer);
-        lighting.setupLightingYNeg(aBlock, aX, aY, aZ)
-                .setupColor(ForgeDirection.DOWN.ordinal(), getRGBA());
-        aRenderer.renderFaceYNeg(aBlock, aX, aY, aZ, mIconContainer.getIcon());
-        if (mIconContainer.getOverlayIcon() != null) {
-            lighting.setupColor(ForgeDirection.DOWN.ordinal(), 0xffffff);
-            aRenderer.renderFaceYNeg(aBlock, aX, aY, aZ, mIconContainer.getOverlayIcon());
-        }
-        // TODO: Uncomment this once all addons have migrated to the new Texture API
-        //draw(aRenderer);
-    }
-}
diff --git a/src/main/java/gregtech/common/render/GT_TextureBuilder.java b/src/main/java/gregtech/common/render/GT_TextureBuilder.java
index 22446f99a5..82bce4c8c4 100644
--- a/src/main/java/gregtech/common/render/GT_TextureBuilder.java
+++ b/src/main/java/gregtech/common/render/GT_TextureBuilder.java
@@ -21,6 +21,7 @@ public class GT_TextureBuilder implements ITextureBuilder {
     private short[] rgba;
     private boolean allowAlpha;
     private boolean stdOrient;
+    private boolean extFacing;
     private boolean glow;
 
     public GT_TextureBuilder() {
@@ -76,6 +77,12 @@ public class GT_TextureBuilder implements ITextureBuilder {
         return this;
     }
 
+    @Override
+    public ITextureBuilder extFacing() {
+        this.extFacing = true;
+        return this;
+    }
+
     @Override
     public ITextureBuilder glow() {
         glow = true;
@@ -88,9 +95,7 @@ public class GT_TextureBuilder implements ITextureBuilder {
         if (!textureLayers.isEmpty()) return new GT_MultiTexture(textureLayers.toArray(new ITexture[0]));
         switch (iconContainerList.size()) {
             case 1:
-                if (stdOrient) return new GT_StdRenderedTexture(iconContainerList.get(0), rgba, allowAlpha);
-                if (glow) return new GT_RenderedGlowTexture(iconContainerList.get(0), rgba, allowAlpha);
-                return new GT_RenderedTexture(iconContainerList.get(0), rgba, allowAlpha);
+                return new GT_RenderedTexture(iconContainerList.get(0), rgba, allowAlpha, glow, stdOrient, extFacing);
             case 6:
                 return new GT_SidedTexture(
                         iconContainerList.get(ForgeDirection.DOWN.ordinal()),
-- 
cgit