com.teambrmodding.neotech.client.models.ModelItemFluidStorage.java Source code

Java tutorial

Introduction

Here is the source code for com.teambrmodding.neotech.client.models.ModelItemFluidStorage.java

Source

package com.teambrmodding.neotech.client.models;

import com.google.common.collect.ImmutableMap;
import com.teambrmodding.neotech.common.blocks.storage.ItemBlockFluidStorage;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.*;
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.util.EnumFacing;
import net.minecraft.world.World;
import net.minecraftforge.client.model.IPerspectiveAwareModel;
import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
import net.minecraftforge.common.model.TRSRTransformation;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidUtil;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.util.vector.Vector3f;

import javax.annotation.Nullable;
import javax.vecmath.Matrix4f;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;

/**
 * This file was created for NeoTech
 * <p>
 * NeoTech is licensed under the
 * Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License:
 * http://creativecommons.org/licenses/by-nc-sa/4.0/
 *
 * @author Paul Davis - pauljoda
 * @since 2/27/2017
 */
public class ModelItemFluidStorage implements IBakedModel, IPerspectiveAwareModel {
    // The face bakery
    protected static final FaceBakery faceBakery = new FaceBakery();

    private static TRSRTransformation get(float tx, float ty, float tz, float ax, float ay, float az, float s) {
        return new TRSRTransformation(new javax.vecmath.Vector3f(tx / 16, ty / 16, tz / 16),
                TRSRTransformation.quatFromXYZDegrees(new javax.vecmath.Vector3f(ax, ay, az)),
                new javax.vecmath.Vector3f(s, s, s), null);
    }

    private static ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transforms = ImmutableMap.<ItemCameraTransforms.TransformType, TRSRTransformation>builder()
            .put(ItemCameraTransforms.TransformType.GUI, get(0, 0, 0, 30, 45, 0, 0.625f))
            .put(ItemCameraTransforms.TransformType.THIRD_PERSON_RIGHT_HAND, get(0, 2.5f, 0, 75, 45, 0, 0.375f))
            .put(ItemCameraTransforms.TransformType.THIRD_PERSON_LEFT_HAND, get(0, 2.5f, 0, 75, 45, 0, 0.375f))
            .put(ItemCameraTransforms.TransformType.FIRST_PERSON_RIGHT_HAND, get(0, 0, 0, 0, 45, 0, 0.4f))
            .put(ItemCameraTransforms.TransformType.FIRST_PERSON_LEFT_HAND, get(0, 0, 0, 0, 225, 0, 0.4f))
            .put(ItemCameraTransforms.TransformType.GROUND, get(0, 2, 0, 0, 0, 0, 0.25f))
            .put(ItemCameraTransforms.TransformType.HEAD, get(0, 0, 0, 0, 0, 0, 1))
            .put(ItemCameraTransforms.TransformType.FIXED, get(0, 0, 0, 0, 0, 0, 1)).build();

    // Variables
    private IBakedModel parentModel;
    private float fluidHeight;
    private Fluid renderFluid;

    // Stub constructor
    public ModelItemFluidStorage() {
    }

    /**
     * Wraps the default model
     * @param parentModel The defined model
     */
    public ModelItemFluidStorage(IBakedModel parentModel) {
        this.parentModel = parentModel;
    }

    /*******************************************************************************************************************
     * IPerspectiveAwareModel                                                                                          *
     *******************************************************************************************************************/

    @Override
    public Pair<? extends IBakedModel, Matrix4f> handlePerspective(
            ItemCameraTransforms.TransformType cameraTransformType) {
        return Pair.of(this,
                transforms.get(cameraTransformType) != null ? transforms.get(cameraTransformType).getMatrix()
                        : get(0, 0, 0, 0, 0, 0, 1.0f).getMatrix());
    }

    /*******************************************************************************************************************
     * IBakedModel                                                                                                     *
     *******************************************************************************************************************/

    // Held Variables for creating quads
    private static final BlockFaceUV uv = new BlockFaceUV(new float[] { 0.0F, 0.0F, 16.0F, 16.0F }, 0);
    private static final BlockPartFace face = new BlockPartFace(null, 0, "", uv);
    private static final ModelRotation modelRot = ModelRotation.X0_Y0;
    private static final boolean scale = true;

    @Override
    public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand) {
        List<BakedQuad> quadList = new ArrayList<>();

        // Add parent quads
        quadList.addAll(parentModel.getQuads(state, side, rand));

        // Render Fluid
        if (renderFluid != null) {
            UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(DefaultVertexFormats.ITEM);

            TextureAtlasSprite texture = Minecraft.getMinecraft().getTextureMapBlocks()
                    .getAtlasSprite(renderFluid.getStill().toString());
            int color = renderFluid.getColor();

            if (!renderFluid.isGaseous()) {
                // Top and Bottom
                quadList.add(applyColor(faceBakery.makeBakedQuad(new Vector3f(2.01F, fluidHeight, 2.01F),
                        new Vector3f(13.99F, fluidHeight, 13.99F), face, texture, EnumFacing.UP, modelRot, null,
                        scale, true), color));
                quadList.add(applyColor(faceBakery.makeBakedQuad(new Vector3f(2.01F, 0.001F, 2.01F),
                        new Vector3f(13.999F, 0.001F, 13.999F), face, texture, EnumFacing.DOWN, modelRot, null,
                        scale, true), color));

                // Sides
                quadList.add(applyColor(faceBakery.makeBakedQuad(new Vector3f(2.01F, 1.01F, 2.01F),
                        new Vector3f(13.99F, fluidHeight, 2.01F), face, texture, EnumFacing.NORTH, modelRot, null,
                        scale, true), color));
                quadList.add(applyColor(faceBakery.makeBakedQuad(new Vector3f(2.01F, 1.01F, 13.99F),
                        new Vector3f(13.99F, fluidHeight, 13.99F), face, texture, EnumFacing.SOUTH, modelRot, null,
                        scale, true), color));
                quadList.add(applyColor(faceBakery.makeBakedQuad(new Vector3f(2.01F, 1.01F, 2.01F),
                        new Vector3f(2.01F, fluidHeight, 13.99F), face, texture, EnumFacing.WEST, modelRot, null,
                        scale, true), color));
                quadList.add(applyColor(faceBakery.makeBakedQuad(new Vector3f(13.99F, 1.01F, 2.01F),
                        new Vector3f(13.99F, fluidHeight, 13.99F), face, texture, EnumFacing.EAST, modelRot, null,
                        scale, true), color));
            } else {
                // Top and Bottom
                quadList.add(applyColor(faceBakery.makeBakedQuad(new Vector3f(2.01F, 14.99F, 2.01F),
                        new Vector3f(13.99F, 14.99F, 13.99F), face, texture, EnumFacing.UP, modelRot, null, scale,
                        true), color));
                quadList.add(applyColor(faceBakery.makeBakedQuad(new Vector3f(2.01F, 14.99F - fluidHeight, 2.01F),
                        new Vector3f(13.999F, 14.99F - fluidHeight, 13.999F), face, texture, EnumFacing.DOWN,
                        modelRot, null, scale, true), color));

                // Sides
                quadList.add(applyColor(faceBakery.makeBakedQuad(new Vector3f(2.01F, 14.99F, 2.01F),
                        new Vector3f(13.99F, 14.99F - fluidHeight, 2.01F), face, texture, EnumFacing.SOUTH,
                        modelRot, null, scale, true), color));
                quadList.add(applyColor(faceBakery.makeBakedQuad(new Vector3f(2.01F, 14.99F, 13.99F),
                        new Vector3f(13.99F, 14.99F - fluidHeight, 13.99F), face, texture, EnumFacing.NORTH,
                        modelRot, null, scale, true), color));
                quadList.add(applyColor(faceBakery.makeBakedQuad(new Vector3f(2.01F, 14.99F, 2.01F),
                        new Vector3f(2.01F, 14.99F - fluidHeight, 13.99F), face, texture, EnumFacing.EAST, modelRot,
                        null, scale, true), color));
                quadList.add(applyColor(faceBakery.makeBakedQuad(new Vector3f(13.99F, 14.99F, 2.01F),
                        new Vector3f(13.99F, 14.99F - fluidHeight, 13.99F), face, texture, EnumFacing.WEST,
                        modelRot, null, scale, true), color));
            }
        }

        return quadList;
    }

    @Override
    public boolean isAmbientOcclusion() {
        return parentModel.isAmbientOcclusion();
    }

    @Override
    public boolean isGui3d() {
        return parentModel.isGui3d();
    }

    @Override
    public boolean isBuiltInRenderer() {
        return parentModel.isBuiltInRenderer();
    }

    @Override
    public TextureAtlasSprite getParticleTexture() {
        return parentModel.getParticleTexture();
    }

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

    @Override
    public ItemOverrideList getOverrides() {
        return new ItemFluidStorageOverrideList();
    }

    /*******************************************************************************************************************
     * ItemOverrideList                                                                                                *
     ******************************************************************************************************************/

    private class ItemFluidStorageOverrideList extends ItemOverrideList {

        /**
         * Default Constructor
         */
        public ItemFluidStorageOverrideList() {
            super(new ArrayList<>());
        }

        /**
         * Handles adding the data to the model we need from the itemstack
         * @param originalModel The base model loaded from json
         * @param stack         The stack containing info
         * @param world         The world
         * @param entity
         * @return
         */
        @Override
        public IBakedModel handleItemState(IBakedModel originalModel, ItemStack stack, World world,
                EntityLivingBase entity) {
            if (stack.hasTagCompound()
                    && stack.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null)
                    && originalModel instanceof ModelItemFluidStorage
                    && stack.getItem() instanceof ItemBlockFluidStorage) {
                // Grab the info needed
                ModelItemFluidStorage model = (ModelItemFluidStorage) originalModel;
                IFluidHandler tank = stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY,
                        null);

                // Attempt to extract fluid
                FluidStack currentStored = FluidUtil.getFluidContained(stack);
                if (currentStored == null) {
                    model.fluidHeight = 0.0F;
                    model.renderFluid = null;
                    return model; // There is nothing stored, don't need extra rendering
                }

                model.fluidHeight = // Scale fluid to model height
                        (Math.min(14.99F, ((currentStored.amount * 14F) / tank.getTankProperties()[0].getCapacity())
                                + 1.31F));
                model.renderFluid = currentStored.getFluid(); // Set fluid to render
                return model; // Returned model that will handle fluid rendering
            } else if (originalModel instanceof ModelItemFluidStorage) {
                ModelItemFluidStorage model = (ModelItemFluidStorage) originalModel;
                model.fluidHeight = 0.0F;
                model.renderFluid = null;
                return model;
            }

            return originalModel;
        }
    }

    /*******************************************************************************************************************
     * Class Methods                                                                                                   *
     *******************************************************************************************************************/

    /**
     * Applies a color to the baked quad, returning the new one
     * @param quad  The quad to color
     * @param color The color to color
     * @return A new baked quad with the given color
     */
    public static BakedQuad applyColor(BakedQuad quad, int color) {
        int[] vertexData = new int[quad.getVertexData().length];
        color = fixColorForMC(color);
        for (int i = 0; i < vertexData.length; i++) {
            if (i == 3 || i == 10 || i == 17 || i == 24)
                vertexData[i] = color;
            else if (i == 3 || i == 13 || i == 20)
                vertexData[i] = 0;
            else
                vertexData[i] = quad.getVertexData()[i];
        }
        return new BakedQuad(vertexData, quad.getTintIndex(), quad.getFace(), quad.getSprite(), true,
                DefaultVertexFormats.ITEM);
    }

    /**
     * Change standard color into color MC wants for vertex data
     * @param input The input
     * @return The correct color to add to the vertex data
     */
    public static int fixColorForMC(int input) {
        // ABGR, MC is reverse for some reason
        Color outputColor = new Color(input);
        int a = outputColor.getAlpha();
        int r = outputColor.getRed();
        int g = outputColor.getGreen();
        int b = outputColor.getBlue();

        return new Color(b, g, r, a).getRGB();
    }
}