blusunrize.immersiveengineering.client.models.ModelConveyor.java Source code

Java tutorial

Introduction

Here is the source code for blusunrize.immersiveengineering.client.models.ModelConveyor.java

Source

/*
 * BluSunrize
 * Copyright (c) 2017
 *
 * This code is licensed under "Blu's License of Common Sense"
 * Details can be found in the license file in the root folder of this project
 */

package blusunrize.immersiveengineering.client.models;

import blusunrize.immersiveengineering.ImmersiveEngineering;
import blusunrize.immersiveengineering.api.IEProperties;
import blusunrize.immersiveengineering.api.tool.ConveyorHandler;
import blusunrize.immersiveengineering.api.tool.ConveyorHandler.ConveyorDirection;
import blusunrize.immersiveengineering.api.tool.ConveyorHandler.IConveyorBelt;
import blusunrize.immersiveengineering.client.ClientUtils;
import blusunrize.immersiveengineering.common.blocks.metal.BlockConveyor;
import blusunrize.immersiveengineering.common.util.ItemNBTHelper;
import blusunrize.immersiveengineering.common.util.Utils;
import blusunrize.immersiveengineering.common.util.chickenbones.Matrix4;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.block.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.common.model.TRSRTransformation;
import net.minecraftforge.common.property.IExtendedBlockState;
import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.util.vector.Vector3f;

import javax.annotation.Nullable;
import javax.vecmath.Matrix4f;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

@SuppressWarnings("deprecation")
public class ModelConveyor implements IBakedModel {
    static List<BakedQuad> emptyQuads = Lists.newArrayList();
    public static HashMap<String, List<BakedQuad>> modelCache = new HashMap<>();
    public static ResourceLocation[] rl_casing = {
            new ResourceLocation(ImmersiveEngineering.MODID, "blocks/conveyor_casing_top"),
            new ResourceLocation(ImmersiveEngineering.MODID, "blocks/conveyor_casing_side"),
            new ResourceLocation(ImmersiveEngineering.MODID, "blocks/conveyor_casing_walls") };

    @Nullable
    final IConveyorBelt defaultBelt;

    public ModelConveyor(IConveyorBelt defaultBelt) {
        this.defaultBelt = defaultBelt;
    }

    public ModelConveyor() {
        this(null);
    }

    @Override
    public List<BakedQuad> getQuads(@Nullable IBlockState blockState, @Nullable EnumFacing side, long rand) {
        TileEntity tile = null;
        String key = "default";
        EnumFacing facing = EnumFacing.NORTH;
        IConveyorBelt conveyor = defaultBelt;
        if (blockState == null)
            key = conveyor != null ? ConveyorHandler.reverseClassRegistry.get(conveyor.getClass()).toString()
                    : "immersiveengineering:conveyor";
        else {
            facing = blockState.getValue(IEProperties.FACING_ALL);
            if (blockState instanceof IExtendedBlockState) {
                IExtendedBlockState exState = (IExtendedBlockState) blockState;
                if (exState.getUnlistedNames().contains(BlockConveyor.ICONEYOR_PASSTHROUGH))
                    conveyor = ((IExtendedBlockState) blockState).getValue(BlockConveyor.ICONEYOR_PASSTHROUGH);
                if (exState.getUnlistedNames().contains(IEProperties.TILEENTITY_PASSTHROUGH))
                    tile = ((IExtendedBlockState) blockState).getValue(IEProperties.TILEENTITY_PASSTHROUGH);
                if (conveyor != null && tile != null)
                    key = conveyor.getModelCacheKey(tile, facing);
            }
        }
        List<BakedQuad> cachedQuads = modelCache.get(key);
        if (cachedQuads != null)
            return ImmutableList.copyOf(cachedQuads);
        else {
            if (conveyor == null)
                conveyor = ConveyorHandler.getConveyor(new ResourceLocation(key), tile);
            cachedQuads = Collections.synchronizedList(Lists.newArrayList());
            Matrix4f facingMatrix = TRSRTransformation.getMatrix(facing);
            if (conveyor != null)
                facingMatrix = conveyor.modifyBaseRotationMatrix(facingMatrix, tile, facing);
            Matrix4 matrix = new Matrix4(facingMatrix);
            ConveyorDirection conDir = conveyor != null ? conveyor.getConveyorDirection()
                    : ConveyorDirection.HORIZONTAL;
            boolean[] walls = conveyor != null && tile != null
                    ? new boolean[] { conveyor.renderWall(tile, facing, 0), conveyor.renderWall(tile, facing, 1) }
                    : new boolean[] { true, true };
            TextureAtlasSprite tex_conveyor = ClientUtils.mc().getTextureMapBlocks().getMissingSprite();
            TextureAtlasSprite tex_conveyor_colour = null;
            int colourStripes = -1;
            if (conveyor != null) {
                tex_conveyor = ClientUtils.getSprite(tile != null
                        ? (conveyor.isActive(tile) ? conveyor.getActiveTexture() : conveyor.getInactiveTexture())
                        : conveyor.getActiveTexture());
                if ((colourStripes = conveyor.getDyeColour()) >= 0)
                    tex_conveyor_colour = ClientUtils.getSprite(conveyor.getColouredStripesTexture());
            }
            cachedQuads.addAll(getBaseConveyor(facing, 1, matrix, conDir, tex_conveyor, walls,
                    new boolean[] { true, true }, tex_conveyor_colour, colourStripes));
            if (conveyor != null)
                cachedQuads = conveyor.modifyQuads(cachedQuads, tile, facing);
            modelCache.put(key, ImmutableList.copyOf(cachedQuads));
            return ImmutableList.copyOf(cachedQuads);
        }
    }

    public static List<BakedQuad> getBaseConveyor(EnumFacing facing, float length, Matrix4 matrix,
            ConveyorDirection conDir, TextureAtlasSprite tex_conveyor, boolean[] walls, boolean[] corners,
            TextureAtlasSprite tex_conveyor_colour, int stripeColour) {
        List<BakedQuad> quads = new ArrayList<BakedQuad>();

        Vector3f[] vertices = { new Vector3f(.0625f, 0, 1 - length), new Vector3f(.0625f, 0, 1),
                new Vector3f(.9375f, 0, 1), new Vector3f(.9375f, 0, 1 - length) };
        TextureAtlasSprite tex_casing0 = ClientUtils.getSprite(rl_casing[0]);
        TextureAtlasSprite tex_casing1 = ClientUtils.getSprite(rl_casing[1]);
        TextureAtlasSprite tex_casing2 = ClientUtils.getSprite(rl_casing[2]);
        float[] colour = { 1, 1, 1, 1 };
        float[] colourStripes = { (stripeColour >> 16 & 255) / 255f, (stripeColour >> 8 & 255) / 255f,
                (stripeColour & 255) / 255f, 1 };

        /**
         * Bottom & Top
         */
        //Shift if up/down
        for (int i = 0; i < 4; i++)
            if ((i == 0 || i == 3) ? conDir == ConveyorDirection.UP : conDir == ConveyorDirection.DOWN)
                vertices[i].translate(0, length, 0);
        //Draw bottom
        quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                ClientUtils.applyMatrixToVertices(matrix, vertices),
                Utils.rotateFacingTowardsDir(EnumFacing.DOWN, facing), tex_conveyor,
                new double[] { 1, 0, 15, length * 16 }, colour, true));
        //Expand verts to side
        for (Vector3f v : vertices)
            v.setX(v.getX() < .5f ? 0 : 1);
        //Draw bottom casing
        quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                ClientUtils.applyMatrixToVertices(matrix, vertices),
                Utils.rotateFacingTowardsDir(EnumFacing.DOWN, facing), tex_casing2,
                new double[] { 0, 0, 16, length * 16 }, colour, true));
        //Shift verts to top
        for (Vector3f v : vertices)
            v.translate(0, .125f, 0);
        //Draw top
        quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                ClientUtils.applyMatrixToVertices(matrix, vertices),
                Utils.rotateFacingTowardsDir(EnumFacing.UP, facing), tex_conveyor,
                new double[] { 0, length * 16, 16, 0 }, colour, false));
        if (corners[0]) {
            vertices = new Vector3f[] { new Vector3f(0, .1875f, .9375f), new Vector3f(0, .1875f, 1),
                    new Vector3f(1, .1875f, 1), new Vector3f(1, .1875f, .9375f) };
            //Shift if up/down
            for (int i = 0; i < 4; i++)
                vertices[i].translate(0,
                        i == 0 || i == 3
                                ? (conDir == ConveyorDirection.UP ? .0625f
                                        : conDir == ConveyorDirection.DOWN ? length - .0625f : 0)
                                : (conDir == ConveyorDirection.DOWN ? length : 0),
                        0);
            //Draw top casing back
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices),
                    Utils.rotateFacingTowardsDir(EnumFacing.UP, facing), tex_casing0, new double[] { 0, 1, 16, 0 },
                    colour, false));
        }
        if (corners[1]) {
            vertices = new Vector3f[] { new Vector3f(0, .1875f, 1 - length),
                    new Vector3f(0, .1875f, 1.0625f - length), new Vector3f(1, .1875f, 1.0625f - length),
                    new Vector3f(1, .1875f, 1 - length) };
            //Shift if up/down
            for (int i = 0; i < 4; i++)
                vertices[i].translate(0,
                        i == 1 || i == 2
                                ? (conDir == ConveyorDirection.UP ? length - .0625f
                                        : conDir == ConveyorDirection.DOWN ? .0625f : 0)
                                : (conDir == ConveyorDirection.UP ? length : 0),
                        0);
            //Draw top casing front
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices),
                    Utils.rotateFacingTowardsDir(EnumFacing.UP, facing), tex_casing0, new double[] { 0, 1, 16, 0 },
                    colour, false));
        }

        /**
         * Sides
         */
        vertices = new Vector3f[] { new Vector3f(0, 0, 1 - length), new Vector3f(0, 0, 1),
                new Vector3f(0, .125f, 1), new Vector3f(0, .125f, 1 - length) };
        for (int i = 0; i < 4; i++)
            if ((i == 0 || i == 3) ? conDir == ConveyorDirection.UP : conDir == ConveyorDirection.DOWN)
                vertices[i].translate(0, length, 0);
        //Draw left side
        quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                ClientUtils.applyMatrixToVertices(matrix, vertices),
                Utils.rotateFacingTowardsDir(EnumFacing.WEST, facing), tex_casing1,
                new double[] { 0, 0, 2, length * 16 }, colour, false));
        //Shift upwards
        for (int i = 0; i < 4; i++)
            vertices[i].setY(vertices[i].getY() + ((i == 0 || i == 1) ? .125f : .0625f));

        //Shift back down and to the other side
        for (int i = 0; i < 4; i++)
            vertices[i].set(1, vertices[i].getY() - ((i == 0 || i == 1) ? .125f : .0625f));
        //Draw right side
        quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                ClientUtils.applyMatrixToVertices(matrix, vertices),
                Utils.rotateFacingTowardsDir(EnumFacing.EAST, facing), tex_casing1,
                new double[] { 0, 0, 2, length * 16 }, colour, true));
        //Shift upwards
        for (int i = 0; i < 4; i++)
            vertices[i].setY(vertices[i].getY() + ((i == 0 || i == 1) ? .125f : .0625f));
        /**
         * Corners
         */
        if (corners[0]) {
            vertices = new Vector3f[] { new Vector3f(0, .125f, .9375f), new Vector3f(0, .125f, 1),
                    new Vector3f(0, .1875f, 1), new Vector3f(0, .1875f, .9375f) };
            if (conDir != ConveyorDirection.HORIZONTAL)
                for (int i = 0; i < 4; i++)
                    vertices[i].translate(0,
                            i == 0 || i == 3
                                    ? (conDir == ConveyorDirection.UP ? .0625f
                                            : conDir == ConveyorDirection.DOWN ? length - .0625f : 0)
                                    : (conDir == ConveyorDirection.DOWN ? length : 0),
                            0);
            //Back left
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices),
                    Utils.rotateFacingTowardsDir(EnumFacing.WEST, facing), tex_casing0, new double[] { 0, 0, 1, 1 },
                    colour, false));
            for (Vector3f v : vertices)
                v.translate(.0625f, 0, 0);
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices),
                    Utils.rotateFacingTowardsDir(EnumFacing.EAST, facing), tex_casing0, new double[] { 0, 0, 1, 1 },
                    colour, true));
            //Shift right
            for (Vector3f v : vertices)
                v.setX(1);
            //Back right
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices),
                    Utils.rotateFacingTowardsDir(EnumFacing.EAST, facing), tex_casing0, new double[] { 0, 0, 1, 1 },
                    colour, true));
            for (Vector3f v : vertices)
                v.translate(-.0625f, 0, 0);
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices),
                    Utils.rotateFacingTowardsDir(EnumFacing.WEST, facing), tex_casing0, new double[] { 0, 0, 1, 1 },
                    colour, false));
        }
        if (corners[1]) {
            vertices = new Vector3f[] { new Vector3f(0, .125f, 1 - length),
                    new Vector3f(0, .125f, 1.0625f - length), new Vector3f(0, .1875f, 1.0625f - length),
                    new Vector3f(0, .1875f, 1 - length) };
            if (conDir != ConveyorDirection.HORIZONTAL)
                for (int i = 0; i < 4; i++)
                    vertices[i].translate(0,
                            i == 1 || i == 2
                                    ? (conDir == ConveyorDirection.UP ? length - .0625f
                                            : conDir == ConveyorDirection.DOWN ? .0625f : 0)
                                    : (conDir == ConveyorDirection.UP ? length : 0),
                            0);
            //Front left
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices),
                    Utils.rotateFacingTowardsDir(EnumFacing.WEST, facing), tex_casing0,
                    new double[] { 0, 15, 1, 16 }, colour, false));
            for (Vector3f v : vertices)
                v.translate(.0625f, 0, 0);
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices),
                    Utils.rotateFacingTowardsDir(EnumFacing.EAST, facing), tex_casing0,
                    new double[] { 0, 15, 1, 16 }, colour, true));
            //Shift right
            for (Vector3f v : vertices)
                v.setX(1);
            //Front right
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices),
                    Utils.rotateFacingTowardsDir(EnumFacing.EAST, facing), tex_casing0,
                    new double[] { 0, 15, 1, 16 }, colour, true));
            for (Vector3f v : vertices)
                v.translate(-.0625f, 0, 0);
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices),
                    Utils.rotateFacingTowardsDir(EnumFacing.WEST, facing), tex_casing0,
                    new double[] { 0, 15, 1, 16 }, colour, false));
        }

        /**
         * Front & Back
         */
        vertices = new Vector3f[] { new Vector3f(.0625f, 0, 1 - length), new Vector3f(.0625f, .125f, 1 - length),
                new Vector3f(.9375f, .125f, 1 - length), new Vector3f(.9375f, 0, 1 - length) };
        //Shift if up/down
        if (conDir == ConveyorDirection.UP)
            for (Vector3f v : vertices)
                v.translate(0, length, 0);
        //Draw front
        double frontUMax = (1 - length) * 16;
        quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                ClientUtils.applyMatrixToVertices(matrix, vertices), facing, tex_conveyor,
                new double[] { 1, frontUMax + 2, 15, frontUMax }, colour, false));
        //Expand to side and up
        for (int i = 0; i < 4; i++)
            vertices[i].set(vertices[i].getX() < .5f ? 0 : 1, vertices[i].getY() + (i == 1 || i == 2 ? .0625f : 0));
        //Draw front casing
        quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                ClientUtils.applyMatrixToVertices(matrix, vertices), facing, tex_casing2,
                new double[] { 0, 3, 16, 0 }, colour, false));
        for (Vector3f v : vertices)
            v.translate(0,
                    (conDir == ConveyorDirection.UP ? -.0625f : conDir == ConveyorDirection.DOWN ? .0625f : 0),
                    .0625f);
        quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                ClientUtils.applyMatrixToVertices(matrix, vertices), facing, tex_casing2,
                new double[] { 0, 3, 16, 0 }, colour, true));
        //Undo expand, shift if up/down, shift to back
        for (int i = 0; i < 4; i++) {
            Vector3f v = vertices[i];
            v.setX(v.getX() < .5f ? .0625f : .9375f);
            v.setY(v.getY() - (i == 1 || i == 2 ? .0625f : 0));
            if (conDir == ConveyorDirection.UP)
                v.translate(0, -(length - .0625f), 0);
            if (conDir == ConveyorDirection.DOWN)
                v.translate(0, (length - .0625f), 0);
            v.translate(0, 0, length - .0625f);
        }
        //Draw back
        quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                ClientUtils.applyMatrixToVertices(matrix, vertices), facing.getOpposite(), tex_conveyor,
                new double[] { 1, 0, 15, 2 }, colour, true));
        //Expand to side and up
        for (int i = 0; i < 4; i++)
            vertices[i].set(vertices[i].getX() < .5f ? 0 : 1, vertices[i].getY() + (i == 1 || i == 2 ? .0625f : 0));
        //Draw back casing
        quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                ClientUtils.applyMatrixToVertices(matrix, vertices), facing.getOpposite(), tex_casing2,
                new double[] { 0, 0, 16, 3 }, colour, true));
        for (Vector3f v : vertices)
            v.translate(0, conDir == ConveyorDirection.UP ? .0625f : conDir == ConveyorDirection.DOWN ? -.0625f : 0,
                    -.0625f);
        quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                ClientUtils.applyMatrixToVertices(matrix, vertices), facing.getOpposite(), tex_casing2,
                new double[] { 0, 0, 16, 3 }, colour, false));

        /**
         * Walls
         */
        float wallLength = length - .125f;
        vertices = new Vector3f[] { new Vector3f(0, .1875f, .9375f - wallLength), new Vector3f(0, .1875f, .9375f),
                new Vector3f(.0625f, .1875f, .9375f), new Vector3f(.0625f, .1875f, .9375f - wallLength) };
        Vector3f[] vertices2 = new Vector3f[] { new Vector3f(0, .125f, .9375f - wallLength),
                new Vector3f(0, .125f, .9375f), new Vector3f(0, .1875f, .9375f),
                new Vector3f(0, .1875f, .9375f - wallLength) };
        Vector3f[] vertices3 = new Vector3f[] { new Vector3f(.0625f, .125f, .9375f - wallLength),
                new Vector3f(.0625f, .125f, .9375f), new Vector3f(.0625f, .1875f, .9375f),
                new Vector3f(.0625f, .1875f, .9375f - wallLength) };
        Vector3f[] verticesColour = new Vector3f[] {
                new Vector3f(0, .1876f, corners[1] ? (1 - length) : (.9375f - wallLength)),
                new Vector3f(0, .1876f, corners[0] ? 1 : .9375f),
                new Vector3f(.0625f, .1876f, corners[0] ? 1 : .9375f),
                new Vector3f(.0625f, .1876f, corners[1] ? (1 - length) : (.9375f - wallLength)) };
        for (int i = 0; i < 4; i++)
            if (conDir != ConveyorDirection.HORIZONTAL) {
                float f = (i == 0 || i == 3) ? (conDir == ConveyorDirection.UP ? length - .0625f : .0625f)
                        : (conDir == ConveyorDirection.UP ? .0625f : length - .0625f);
                vertices[i].translate(0, f, 0);
                vertices2[i].translate(0, f, 0);
                vertices3[i].translate(0, f, 0);
                verticesColour[i].translate(0, f, 0);
            }
        //Draw left walls
        if (walls[0]) {
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices),
                    Utils.rotateFacingTowardsDir(EnumFacing.UP, facing), tex_casing2, new double[] { 0, 15, 1, 1 },
                    colour, false));
            if (tex_conveyor_colour != null && stripeColour >= 0)
                quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                        ClientUtils.applyMatrixToVertices(matrix, verticesColour),
                        Utils.rotateFacingTowardsDir(EnumFacing.UP, facing), tex_conveyor_colour,
                        new double[] { 0, 15, 1, 1 }, colourStripes, false));
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices2),
                    Utils.rotateFacingTowardsDir(EnumFacing.WEST, facing), tex_casing1,
                    new double[] { 2, 15, 3, 1 }, colour, false));
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices3),
                    Utils.rotateFacingTowardsDir(EnumFacing.EAST, facing), tex_casing1,
                    new double[] { 2, 15, 3, 1 }, colour, true));
        }
        for (int i = 0; i < 4; i++) {
            vertices[i].translate(.9375f, 0, 0);
            vertices2[i].translate(.9375f, 0, 0);
            vertices3[i].translate(.9375f, 0, 0);
            verticesColour[i].translate(.9375f, 0, 0);
        }
        //Draw right walls
        if (walls[1]) {
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices),
                    Utils.rotateFacingTowardsDir(EnumFacing.UP, facing), tex_casing2,
                    new double[] { 15, 15, 16, 1 }, colour, false));
            if (tex_conveyor_colour != null && stripeColour >= 0)
                quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                        ClientUtils.applyMatrixToVertices(matrix, verticesColour),
                        Utils.rotateFacingTowardsDir(EnumFacing.UP, facing), tex_conveyor_colour,
                        new double[] { 15, 15, 16, 1 }, colourStripes, false));
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices2),
                    Utils.rotateFacingTowardsDir(EnumFacing.WEST, facing), tex_casing1,
                    new double[] { 2, 15, 3, 1 }, colour, false));
            quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM,
                    ClientUtils.applyMatrixToVertices(matrix, vertices3),
                    Utils.rotateFacingTowardsDir(EnumFacing.EAST, facing), tex_casing1,
                    new double[] { 2, 15, 3, 1 }, colour, true));
        }

        return quads;
    }

    @Override
    public boolean isAmbientOcclusion() {
        return true;
    }

    @Override
    public boolean isGui3d() {
        return true;
    }

    @Override
    public boolean isBuiltInRenderer() {
        return false;
    }

    TextureAtlasSprite tex_particle;

    @Override
    public TextureAtlasSprite getParticleTexture() {
        if (tex_particle == null)
            tex_particle = ClientUtils
                    .getSprite(new ResourceLocation(ImmersiveEngineering.MODID, "blocks/conveyor_off"));
        return tex_particle;
    }

    @Override
    public ItemCameraTransforms getItemCameraTransforms() {
        return ItemCameraTransforms.DEFAULT;
    }

    @Override
    public ItemOverrideList getOverrides() {
        return overrideList;
    }

    static HashMap<String, IBakedModel> itemModelCache = new HashMap<String, IBakedModel>();
    ItemOverrideList overrideList = new ItemOverrideList(new ArrayList()) {
        @Override
        public IBakedModel handleItemState(IBakedModel originalModel, ItemStack stack, World world,
                EntityLivingBase entity) {
            String key = ItemNBTHelper.getString(stack, "conveyorType");
            IBakedModel model = itemModelCache.get(key);
            if (model == null) {
                model = new ModelConveyor(ConveyorHandler.getConveyor(new ResourceLocation(key), null));
                itemModelCache.put(key, model);
            }
            return model;
        }
    };

    static HashMap<TransformType, Matrix4> transformationMap = new HashMap<TransformType, Matrix4>();

    static {
        transformationMap.put(TransformType.FIRST_PERSON_LEFT_HAND,
                new Matrix4().scale(.5, .5, .5).translate(0, .25, 0).rotate(Math.toRadians(-45), 0, 1, 0));
        transformationMap.put(TransformType.FIRST_PERSON_RIGHT_HAND,
                new Matrix4().scale(.5, .5, .5).translate(0, .25, 0).rotate(Math.toRadians(-45), 0, 1, 0));
        transformationMap.put(TransformType.THIRD_PERSON_LEFT_HAND,
                new Matrix4().translate(0, .0625, -.125).scale(.3125, .3125, .3125)
                        .rotate(Math.toRadians(30), 1, 0, 0).rotate(Math.toRadians(130), 0, 1, 0));
        transformationMap.put(TransformType.THIRD_PERSON_RIGHT_HAND,
                new Matrix4().translate(0, .0625, -.125).scale(.3125, .3125, .3125)
                        .rotate(Math.toRadians(30), 1, 0, 0).rotate(Math.toRadians(130), 0, 1, 0));
        transformationMap.put(TransformType.GUI,
                new Matrix4().scale(.625, .625, .625).rotate(Math.toRadians(-45), 0, 1, 0)
                        .rotate(Math.toRadians(-20), 0, 0, 1).rotate(Math.toRadians(20), 1, 0, 0));
        transformationMap.put(TransformType.FIXED,
                new Matrix4().scale(.625, .625, .625).rotate(Math.PI, 0, 1, 0).translate(0, 0, .3125));
        transformationMap.put(TransformType.GROUND, new Matrix4().scale(.25, .25, .25));
    }

    @Override
    public Pair<? extends IBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType) {
        Matrix4 matrix = transformationMap.containsKey(cameraTransformType)
                ? transformationMap.get(cameraTransformType)
                : new Matrix4();
        return Pair.of(this, matrix.toMatrix4f());
    }
}