buildcraft.transport.render.RenderPipe.java Source code

Java tutorial

Introduction

Here is the source code for buildcraft.transport.render.RenderPipe.java

Source

/**
 * Copyright (c) SpaceToad, 2011
 * http://www.mod-buildcraft.com
 *
 * BuildCraft is distributed under the terms of the Minecraft Mod Public
 * License 1.0, or MMPL. Please check the contents of the license located in
 * http://www.mod-buildcraft.com/MMPL-1.0.txt
 */

package buildcraft.transport.render;

import java.util.HashMap;

import net.minecraft.block.Block;
import net.minecraft.client.renderer.GLAllocation;
import net.minecraft.client.renderer.entity.RenderItem;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.liquids.LiquidStack;

import org.lwjgl.opengl.GL11;

import buildcraft.BuildCraftCore;
import buildcraft.BuildCraftCore.RenderMode;
import buildcraft.api.transport.IPipedItem;
import buildcraft.core.DefaultProps;
import buildcraft.core.render.RenderEntityBlock;
import buildcraft.core.render.RenderEntityBlock.BlockInterface;
import buildcraft.core.utils.Utils;
import buildcraft.transport.EntityData;
import buildcraft.transport.Pipe;
import buildcraft.transport.PipeTransportItems;
import buildcraft.transport.PipeTransportLiquids;
import buildcraft.transport.PipeTransportPower;
import buildcraft.transport.TileGenericPipe;

public class RenderPipe extends TileEntitySpecialRenderer {

    final static private int LIQUID_STAGES = 40;

    final static private int MAX_ITEMS_TO_RENDER = 10;

    private final EntityItem dummyEntityItem = new EntityItem(null);

    private final RenderItem customRenderItem;

    private class DisplayLiquidList {

        public int[] sideHorizontal = new int[LIQUID_STAGES];
        public int[] sideVertical = new int[LIQUID_STAGES];
        public int[] centerHorizontal = new int[LIQUID_STAGES];
        public int[] centerVertical = new int[LIQUID_STAGES];
    }

    private HashMap<Integer, HashMap<Integer, DisplayLiquidList>> displayLiquidLists = new HashMap<Integer, HashMap<Integer, DisplayLiquidList>>();

    private final int[] angleY = { 0, 0, 270, 90, 0, 180 };
    private final int[] angleZ = { 90, 270, 0, 0, 0, 0 };

    final static private int POWER_STAGES = 100;

    public int[] displayPowerList = new int[POWER_STAGES];
    public int[] displayPowerListOverload = new int[POWER_STAGES];

    public RenderPipe() {
        customRenderItem = new RenderItem() {
            public boolean shouldBob() {
                return false;
            };

            public boolean shouldSpreadItems() {
                return false;
            };
        };
        customRenderItem.setRenderManager(RenderManager.instance);
    }

    private DisplayLiquidList getDisplayLiquidLists(int liquidId, int meta, World world) {
        if (displayLiquidLists.containsKey(liquidId)) {
            HashMap<Integer, DisplayLiquidList> x = displayLiquidLists.get(liquidId);
            if (x.containsKey(meta))
                return x.get(meta);
        } else {
            displayLiquidLists.put(liquidId, new HashMap<Integer, DisplayLiquidList>());
        }

        DisplayLiquidList d = new DisplayLiquidList();
        displayLiquidLists.get(liquidId).put(meta, d);

        BlockInterface block = new BlockInterface();
        if (liquidId < Block.blocksList.length && Block.blocksList[liquidId] != null) {
            block.texture = Block.blocksList[liquidId].getBlockTextureFromSideAndMetadata(0, meta);
        } else {
            block.texture = Item.itemsList[liquidId].getIconFromDamage(meta);
        }

        float size = Utils.pipeMaxPos - Utils.pipeMinPos;

        // render size

        for (int s = 0; s < LIQUID_STAGES; ++s) {
            float ratio = (float) s / (float) LIQUID_STAGES;

            // SIDE HORIZONTAL

            d.sideHorizontal[s] = GLAllocation.generateDisplayLists(1);
            GL11.glNewList(d.sideHorizontal[s], 4864 /* GL_COMPILE */);

            block.minX = 0.0F;
            block.minZ = Utils.pipeMinPos + 0.01F;

            block.maxX = block.minX + size / 2F + 0.01F;
            block.maxZ = block.minZ + size - 0.02F;

            block.minY = Utils.pipeMinPos + 0.01F;
            block.maxY = block.minY + (size - 0.02F) * ratio;

            RenderEntityBlock.renderBlock(block, world, 0, 0, 0, false, true);

            GL11.glEndList();

            // SIDE VERTICAL

            d.sideVertical[s] = GLAllocation.generateDisplayLists(1);
            GL11.glNewList(d.sideVertical[s], 4864 /* GL_COMPILE */);

            block.minY = Utils.pipeMaxPos - 0.01;
            block.maxY = 1;

            block.minX = 0.5 - (size / 2 - 0.01) * ratio;
            block.maxX = 0.5 + (size / 2 - 0.01) * ratio;

            block.minZ = 0.5 - (size / 2 - 0.01) * ratio;
            block.maxZ = 0.5 + (size / 2 - 0.01) * ratio;

            RenderEntityBlock.renderBlock(block, world, 0, 0, 0, false, true);

            GL11.glEndList();

            // CENTER HORIZONTAL

            d.centerHorizontal[s] = GLAllocation.generateDisplayLists(1);
            GL11.glNewList(d.centerHorizontal[s], 4864 /* GL_COMPILE */);

            block.minX = Utils.pipeMinPos + 0.01;
            block.minZ = Utils.pipeMinPos + 0.01;

            block.maxX = block.minX + size - 0.02;
            block.maxZ = block.minZ + size - 0.02;

            block.minY = Utils.pipeMinPos + 0.01;
            block.maxY = block.minY + (size - 0.02F) * ratio;

            RenderEntityBlock.renderBlock(block, world, 0, 0, 0, false, true);

            GL11.glEndList();

            // CENTER VERTICAL

            d.centerVertical[s] = GLAllocation.generateDisplayLists(1);
            GL11.glNewList(d.centerVertical[s], 4864 /* GL_COMPILE */);

            block.minY = Utils.pipeMinPos + 0.01;
            block.maxY = Utils.pipeMaxPos - 0.01;

            block.minX = 0.5 - (size / 2 - 0.02) * ratio;
            block.maxX = 0.5 + (size / 2 - 0.02) * ratio;

            block.minZ = 0.5 - (size / 2 - 0.02) * ratio;
            block.maxZ = 0.5 + (size / 2 - 0.02) * ratio;

            RenderEntityBlock.renderBlock(block, world, 0, 0, 0, false, true);

            GL11.glEndList();

        }

        return d;
    }

    boolean initialized = false;

    private void initializeDisplayPowerList(World world) {
        if (initialized)
            return;

        initialized = true;

        BlockInterface block = new BlockInterface();
        block.texture = 4;

        float size = Utils.pipeMaxPos - Utils.pipeMinPos;

        for (int s = 0; s < POWER_STAGES; ++s) {
            displayPowerList[s] = GLAllocation.generateDisplayLists(1);
            GL11.glNewList(displayPowerList[s], 4864 /* GL_COMPILE */);

            float minSize = 0.005F;

            float unit = (size - minSize) / 2F / POWER_STAGES;

            block.minY = 0.5 - (minSize / 2F) - unit * s;
            block.maxY = 0.5 + (minSize / 2F) + unit * s;

            block.minZ = 0.5 - (minSize / 2F) - unit * s;
            block.maxZ = 0.5 + (minSize / 2F) + unit * s;

            block.minX = 0;
            block.maxX = 0.5 + (minSize / 2F) + unit * s;

            RenderEntityBlock.renderBlock(block, world, 0, 0, 0, false, true);

            GL11.glEndList();
        }

        block.texture = 6;

        size = Utils.pipeMaxPos - Utils.pipeMinPos;

        for (int s = 0; s < POWER_STAGES; ++s) {
            displayPowerListOverload[s] = GLAllocation.generateDisplayLists(1);
            GL11.glNewList(displayPowerListOverload[s], 4864 /* GL_COMPILE */);

            float minSize = 0.005F;

            float unit = (size - minSize) / 2F / POWER_STAGES;

            block.minY = 0.5 - (minSize / 2F) - unit * s;
            block.maxY = 0.5 + (minSize / 2F) + unit * s;

            block.minZ = 0.5 - (minSize / 2F) - unit * s;
            block.maxZ = 0.5 + (minSize / 2F) + unit * s;

            block.minX = 0;
            block.maxX = 0.5 + (minSize / 2F) + unit * s;

            RenderEntityBlock.renderBlock(block, world, 0, 0, 0, false, true);

            GL11.glEndList();
        }
    }

    @Override
    public void renderTileEntityAt(TileEntity tileentity, double x, double y, double z, float f) {

        if (BuildCraftCore.render == RenderMode.NoDynamic)
            return;

        initializeDisplayPowerList(tileentity.worldObj);

        TileGenericPipe pipe = ((TileGenericPipe) tileentity);

        if (pipe.pipe == null)
            return;

        if (pipe.pipe.transport instanceof PipeTransportItems) {
            renderSolids(pipe.pipe, x, y, z);
        } else if (pipe.pipe.transport instanceof PipeTransportLiquids) {
            renderLiquids(pipe.pipe, x, y, z);
        } else if (pipe.pipe.transport instanceof PipeTransportPower) {
            renderPower(pipe.pipe, x, y, z);
        }

    }

    private void renderPower(Pipe pipe, double x, double y, double z) {
        PipeTransportPower pow = (PipeTransportPower) pipe.transport;

        GL11.glPushMatrix();
        GL11.glDisable(2896 /* GL_LIGHTING */);

        ForgeHooksClient.bindTexture(DefaultProps.TEXTURE_BLOCKS, 0);

        GL11.glTranslatef((float) x + 0.5F, (float) y + 0.5F, (float) z + 0.5F);

        int[] displayList = pow.overload ? displayPowerListOverload : displayPowerList;

        for (int i = 0; i < 6; ++i) {
            GL11.glPushMatrix();

            GL11.glRotatef(angleY[i], 0, 1, 0);
            GL11.glRotatef(angleZ[i], 0, 0, 1);

            if (pow.displayPower[i] >= 1.0) {
                short stage = pow.displayPower[i];

                if (stage < displayList.length) {
                    GL11.glCallList(displayList[stage]);
                } else {
                    GL11.glCallList(displayList[displayList.length - 1]);
                }
            }

            GL11.glPopMatrix();
        }

        GL11.glEnable(2896 /* GL_LIGHTING */);
        GL11.glPopMatrix();
    }

    private void renderLiquids(Pipe pipe, double x, double y, double z) {
        PipeTransportLiquids liq = (PipeTransportLiquids) pipe.transport;

        GL11.glPushMatrix();
        GL11.glDisable(2896 /* GL_LIGHTING */);

        GL11.glTranslatef((float) x + 0.5F, (float) y + 0.5F, (float) z + 0.5F);

        // sides

        boolean sides = false, above = false;

        for (int i = 0; i < 6; ++i) {
            // ILiquidTank tank = liq.getTanks()[i];
            // LiquidStack liquid = tank.getLiquid();
            LiquidStack liquid = liq.renderCache[i];
            // int amount = liquid != null ? liquid.amount : 0;
            // int amount = liquid != null ? liq.renderAmmount[i] : 0;

            if (liquid != null && liquid.amount > 0) {
                DisplayLiquidList d = getListFromBuffer(liquid, pipe.worldObj);

                if (d == null) {
                    continue;
                }

                int stage = (int) ((float) liquid.amount / (float) (liq.getCapacity()) * (LIQUID_STAGES - 1));

                GL11.glPushMatrix();
                int list = 0;

                switch (ForgeDirection.VALID_DIRECTIONS[i]) {
                case UP:
                    above = true;
                    list = d.sideVertical[stage];
                    break;
                case DOWN:
                    GL11.glTranslatef(0, -0.75F, 0);
                    list = d.sideVertical[stage];
                    break;
                case EAST:
                case WEST:
                case SOUTH:
                case NORTH:
                    sides = true;
                    GL11.glRotatef(angleY[i], 0, 1, 0);
                    GL11.glRotatef(angleZ[i], 0, 0, 1);
                    list = d.sideHorizontal[stage];
                    break;
                default:
                }

                GL11.glCallList(list);
                GL11.glPopMatrix();
            }
        }
        // CENTER
        // ILiquidTank tank = liq.getTanks()[ForgeDirection.Unknown.ordinal()];
        // LiquidStack liquid = tank.getLiquid();
        LiquidStack liquid = liq.renderCache[ForgeDirection.UNKNOWN.ordinal()];

        // int amount = liquid != null ? liquid.amount : 0;
        // int amount = liquid != null ? liq.renderAmmount[ForgeDirection.Unknown.ordinal()] : 0;
        if (liquid != null && liquid.amount > 0) {
            // DisplayLiquidList d = getListFromBuffer(liq.getTanks()[ForgeDirection.Unknown.ordinal()].getLiquid(), pipe.worldObj);
            DisplayLiquidList d = getListFromBuffer(liquid, pipe.worldObj);

            if (d != null) {
                int stage = (int) ((float) liquid.amount / (float) (liq.getCapacity()) * (LIQUID_STAGES - 1));

                if (above) {
                    GL11.glCallList(d.centerVertical[stage]);
                }

                if (!above || sides) {
                    GL11.glCallList(d.centerHorizontal[stage]);
                }
            }

        }

        GL11.glEnable(2896 /* GL_LIGHTING */);
        GL11.glPopMatrix();
    }

    private DisplayLiquidList getListFromBuffer(LiquidStack stack, World world) {

        int liquidId = stack.itemID;

        if (liquidId == 0)
            return null;

        if (liquidId < Block.blocksList.length && Block.blocksList[liquidId] != null) {
            ForgeHooksClient.bindTexture(Block.blocksList[liquidId].getTextureFile(), 0);
        } else if (Item.itemsList[liquidId] != null) {
            ForgeHooksClient.bindTexture(Item.itemsList[liquidId].getTextureFile(), 0);
        } else
            return null;
        return getDisplayLiquidLists(liquidId, stack.itemMeta, world);
    }

    private void renderSolids(Pipe pipe, double x, double y, double z) {
        GL11.glPushMatrix();
        GL11.glDisable(2896 /* GL_LIGHTING */);

        float light = pipe.worldObj.getLightBrightness(pipe.xCoord, pipe.yCoord, pipe.zCoord);

        int count = 0;
        for (EntityData data : ((PipeTransportItems) pipe.transport).travelingEntities.values()) {
            if (count >= MAX_ITEMS_TO_RENDER) {
                break;
            }

            doRenderItem(data.item, x + data.item.getPosition().x - pipe.xCoord,
                    y + data.item.getPosition().y - pipe.yCoord, z + data.item.getPosition().z - pipe.zCoord,
                    light);
            count++;
        }

        GL11.glEnable(2896 /* GL_LIGHTING */);
        GL11.glPopMatrix();
    }

    public void doRenderItem(IPipedItem entityitem, double d, double d1, double d2, float f1) {

        if (entityitem == null || entityitem.getItemStack() == null)
            return;

        float renderScale = 0.7f;
        ItemStack itemstack = entityitem.getItemStack();
        GL11.glPushMatrix();
        GL11.glTranslatef((float) d, (float) d1, (float) d2);
        GL11.glTranslatef(0, 0.25F, 0);
        GL11.glScalef(renderScale, renderScale, renderScale);
        dummyEntityItem.func_92058_a(itemstack);
        customRenderItem.doRenderItem(dummyEntityItem, 0, 0, 0, 0, 0);
        GL11.glPopMatrix();
    }
}