mca.client.render.RenderHuman.java Source code

Java tutorial

Introduction

Here is the source code for mca.client.render.RenderHuman.java

Source

/*******************************************************************************
 * RenderHuman.java
 * Copyright (c) 2014 WildBamaBoy.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the MCA Minecraft Mod license.
 ******************************************************************************/

package mca.client.render;

import java.util.ArrayList;
import java.util.List;

import mca.ai.AIConverse;
import mca.ai.AISleep;
import mca.client.gui.GuiInteraction;
import mca.client.gui.GuiVillagerEditor;
import mca.client.model.ModelHuman;
import mca.client.model.UVPoint;
import mca.core.Constants;
import mca.core.MCA;
import mca.data.PlayerMemory;
import mca.entity.EntityHuman;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.entity.RenderBiped;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Vec3;

import org.lwjgl.opengl.GL11;

import radixcore.client.render.RenderHelper;
import radixcore.util.RadixMath;

/**
 * Determines how a Human is rendered.
 */
public class RenderHuman extends RenderBiped {
    private static final ResourceLocation gui = new ResourceLocation("mca:textures/gui.png");
    private static final UVPoint exMark = new UVPoint(55, 18, 3, 13);
    private static final UVPoint minus = new UVPoint(69, 23, 7, 3);
    private static final UVPoint plus = new UVPoint(85, 21, 7, 7);
    private static final float LABEL_SCALE = 0.027F;
    private final ModelBiped modelArmorPlate;
    private final ModelBiped modelArmor;

    public RenderHuman() {
        super(new ModelHuman(0.0F), 0.5F);

        modelBipedMain = (ModelBiped) mainModel;
        modelArmorPlate = new ModelBiped(1.0F);
        modelArmor = new ModelBiped(0.5F);
    }

    @Override
    protected void preRenderCallback(EntityLivingBase entityLivingBase, float partialTickTime) {
        final EntityHuman entity = (EntityHuman) entityLivingBase;
        final AISleep sleepAI = entity.getAI(AISleep.class);
        float scale = entity.getIsMale() ? Constants.SCALE_M_ADULT : Constants.SCALE_F_ADULT;

        if (entity.getIsChild()) {
            final boolean doGradualGrowth = MCA.getConfig().isAgingEnabled;
            final float growthFactor = (entity.getIsMale() ? 0.39F : 0.37F) / MCA.getConfig().childGrowUpTime
                    * entity.getAge();

            scale = 0.55F + growthFactor;

            if (entityLivingBase.ridingEntity != null) {
                GL11.glTranslated(0.0D, (1.0D + growthFactor) + growthFactor, 0.2D);
            }
        }

        GL11.glScalef(scale, scale + entity.getHeight(), scale);
        GL11.glScalef(scale + entity.getGirth(), scale, scale + entity.getGirth());

        if (sleepAI.getIsInBed()) {
            renderHumanSleeping(entity, partialTickTime);
        }

        else if (entityLivingBase.ridingEntity != null) {
            GL11.glTranslated(0.0D, 0.55D, 0.1D);
        }
    }

    @Override
    protected void passSpecialRender(EntityLivingBase entityLivingBase, double posX, double posY, double posZ) {
        super.passSpecialRender(entityLivingBase, posX, posY, posZ);

        final EntityHuman human = (EntityHuman) entityLivingBase;
        final AIConverse converseAI = human.getAI(AIConverse.class);
        final int currentHealth = (int) human.getHealth();
        final int maxHealth = (int) human.getMaxHealth();
        final double distanceFromPlayer = RadixMath.getDistanceToEntity(human, Minecraft.getMinecraft().thePlayer);

        if (Minecraft.getMinecraft().currentScreen instanceof GuiVillagerEditor) {
            return;
        }

        else if (currentHealth < maxHealth) {
            renderLabel(human, posX, posY, posZ,
                    MCA.getLanguageManager().getString("label.health") + currentHealth + "/" + maxHealth);
        }

        else if (canRenderNameTag(entityLivingBase) && MCA.getConfig().showNameTagOnHover) {
            renderLabel(human, posX, posY, posZ, human.getTitle(Minecraft.getMinecraft().thePlayer));
        }

        else if (human.displayNameForPlayer) {
            renderLabel(human, posX, posY + (distanceFromPlayer / 15.0D) + (human.getHeight() * 1.15D), posZ,
                    human.getTitle(Minecraft.getMinecraft().thePlayer));
            renderHearts(human, posX, posY + (distanceFromPlayer / 15.0D) + (human.getHeight() * 1.15D), posZ,
                    human.getPlayerMemory(Minecraft.getMinecraft().thePlayer).getHearts());
        }

        else if (human.getAIManager().isToggleAIActive()) {
            renderLabel(human, posX, posY + (distanceFromPlayer / 15.0D) + (human.getHeight() * 1.15D), posZ,
                    human.getAIManager().getNameOfActiveAI());
        }

        else if (converseAI.getConversationActive() && distanceFromPlayer <= 6.0D
                && MCA.getConfig().showVillagerConversations) {
            String conversationString = "conversation" + converseAI.getConversationID() + ".progress"
                    + converseAI.getConversationProgress();
            boolean elevateLabel = converseAI.getConversationProgress() % 2 == 0;
            posY = elevateLabel ? posY + 0.25D : posY;

            if (converseAI.getConversationProgress() != 0) {
                renderLabel(human, posX, posY, posZ, MCA.getLanguageManager().getString(conversationString));
            }
        }
    }

    @Override
    protected ResourceLocation getEntityTexture(Entity entity) {
        final String skinName = ((EntityHuman) entity).getSkin();

        if (skinName.isEmpty()) {
            return new ResourceLocation("minecraft:textures/entity/steve.png");
        }

        else {
            return new ResourceLocation(((EntityHuman) entity).getSkin());
        }
    }

    private void renderHuman(EntityHuman entity, double posX, double posY, double posZ, float rotationYaw,
            float rotationPitch) {
        final EntityPlayer player = Minecraft.getMinecraft().thePlayer;
        final PlayerMemory memory = entity.getPlayerMemoryWithoutCreating(player);

        if (!entity.getDoDisplay()) {
            return;
        }

        //Pass special renders according to player memory here.
        if (RadixMath.getDistanceToEntity(entity, player) <= 5.0F && !entity.getAI(AISleep.class).getIsSleeping()
                && !entity.displayNameForPlayer && memory != null) {
            UVPoint uvp = memory.doDisplayFeedback() ? (memory.getLastInteractionSuccess() ? plus : minus)
                    : memory.getHasQuest() ? exMark : null;

            if (uvp != null) {
                GL11.glPushMatrix();
                {
                    GL11.glTranslatef((float) posX, (float) posY + entity.height + 0.25F + 0.5F, (float) posZ);
                    GL11.glRotatef(-renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
                    GL11.glRotatef(renderManager.playerViewX, 1.0F, 0.0F, 0.0F);
                    GL11.glScalef(-LABEL_SCALE, -LABEL_SCALE, LABEL_SCALE);
                    GL11.glDisable(GL11.GL_LIGHTING);
                    GL11.glTranslatef(0.0F, 0.25F / LABEL_SCALE, 0.0F);
                    RenderHelper.drawTexturedRectangle(gui, (int) posX, (int) posY + 12, uvp.getU(), uvp.getV(),
                            uvp.getWidth(), uvp.getHeight());
                }
                GL11.glPopMatrix();

                GL11.glDepthMask(true);
                GL11.glEnable(GL11.GL_LIGHTING);
            }
        }

        double posYCorrection = posY - entity.yOffset;
        shadowOpaque = 1.0F;

        final ItemStack heldItem = entity.getHeldItem();
        modelArmorPlate.heldItemRight = modelArmor.heldItemRight = modelBipedMain.heldItemRight = heldItem == null
                ? 0
                : 1;
        modelArmorPlate.isSneak = modelArmor.isSneak = modelBipedMain.isSneak = entity.isSneaking();

        if (heldItem != null) {
            final EnumAction useAction = heldItem.getItemUseAction();

            if (useAction == EnumAction.bow) {
                modelArmorPlate.aimedBow = modelArmor.aimedBow = modelBipedMain.aimedBow = true;
            }
        }

        if (entity.isSneaking()) {
            posYCorrection -= 0.125D;
        }

        super.doRender(entity, posX, posYCorrection, posZ, rotationYaw, rotationPitch);
        modelArmorPlate.aimedBow = modelArmor.aimedBow = modelBipedMain.aimedBow = false;
        modelArmorPlate.isSneak = modelArmor.isSneak = modelBipedMain.isSneak = false;
        modelArmorPlate.heldItemRight = modelArmor.heldItemRight = modelBipedMain.heldItemRight = 0;
    }

    protected void renderHumanSleeping(EntityHuman entity, double partialTickTime) {
        final AISleep sleepAI = entity.getAI(AISleep.class);
        final int meta = sleepAI.getBedMeta();

        if (meta == 8) {
            entity.rotationYawHead = 180.0F;
            GL11.glTranslated(-0.5D, 0.0D, -1.0D);
            GL11.glRotated(90, -1, 0, 0);
            GL11.glTranslated(0.0D, 0.0D, -0.75D);
        }

        else if (meta == 11) {
            entity.rotationYawHead = 90.0F;
            GL11.glTranslated(0.5D, 0.0D, -1.0D);
            GL11.glRotated(90, -1, 0, 0);
            GL11.glTranslated(0.0D, 0.0D, -0.75D);
        }

        else if (meta == 10) {
            entity.rotationYawHead = 0.0F;
            GL11.glTranslated(0.5D, 0.0D, -2.0D);
            GL11.glRotated(90, -1, 0, 0);
            GL11.glTranslated(0.0D, 0.0D, -0.75D);
        }

        else if (meta == 9) {
            entity.rotationYawHead = -90.0F;
            GL11.glTranslated(-0.5D, 0.0D, -2.0D);
            GL11.glRotated(90, -1, 0, 0);
            GL11.glTranslated(0.0D, 0.0D, -0.75D);
        }
    }

    @Override
    public void doRender(Entity entity, double posX, double posY, double posZ, float rotationYaw,
            float rotationPitch) {
        renderHuman((EntityHuman) entity, posX, posY, posZ, rotationYaw, rotationPitch);
    }

    @Override
    public void doRender(EntityLiving entityLiving, double posX, double posY, double posZ, float rotationYaw,
            float rotationPitch) {
        renderHuman((EntityHuman) entityLiving, posX, posY, posZ, rotationYaw, rotationPitch);
    }

    private void renderHearts(EntityHuman human, double posX, double posY, double posZ, int heartsLevel) {
        try {
            //Clamp to 10 first to calculate gold hearts.
            int clampedHearts = RadixMath.clamp(((Math.abs(heartsLevel) + 5) / 10), 0, 10);
            final boolean isNegative = heartsLevel < 0;
            int goldHearts = isNegative ? 0 : clampedHearts - 5;

            final int heartU = 5;
            final int goldHeartU = 37;
            final int negHeartU = 21;

            //Clamp down to 5 hearts since processing has completed, needed to generate the list properly.
            clampedHearts = RadixMath.clamp(clampedHearts, 0, 5);
            final List<Integer> heartsToDraw = new ArrayList<Integer>();

            //Add the needed gold hearts.
            while (goldHearts > 0) {
                heartsToDraw.add(goldHeartU);
                goldHearts--;
            }

            //Add the remaining hearts.
            while (heartsToDraw.size() < clampedHearts) {
                if (isNegative) {
                    heartsToDraw.add(negHeartU);
                }

                else {
                    heartsToDraw.add(heartU);
                }
            }

            //Draw hearts.
            if (!heartsToDraw.isEmpty()) {
                GL11.glPushMatrix();
                {
                    GL11.glTranslatef((float) posX + 0.0F, (float) posY + human.height + 0.25F, (float) posZ);
                    GL11.glRotatef(-renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
                    GL11.glRotatef(renderManager.playerViewX, 1.0F, 0.0F, 0.0F);
                    GL11.glScalef(-LABEL_SCALE, -LABEL_SCALE, LABEL_SCALE);
                    GL11.glDisable(GL11.GL_LIGHTING);
                    GL11.glTranslatef(0.0F, 0.25F / LABEL_SCALE, 0.0F);

                    switch (heartsToDraw.size()) {
                    case 1:
                        RenderHelper.drawTexturedRectangle(gui, ((int) posX + (10 * 2) - 22), (int) posY - 4,
                                heartsToDraw.get(0), 20, 9, 9);
                        break;
                    case 2:
                        for (int i = 0; i < 2; i++) {
                            RenderHelper.drawTexturedRectangle(gui, ((int) posX + (10 * i) - 9), (int) posY - 4,
                                    heartsToDraw.get(i), 20, 9, 9);
                        }
                        break;
                    case 3:
                        for (int i = 0; i < 3; i++) {
                            RenderHelper.drawTexturedRectangle(gui, ((int) posX + (10 * i) - 14), (int) posY - 4,
                                    heartsToDraw.get(i), 20, 9, 9);
                        }
                        break;
                    case 4:
                        for (int i = 0; i < 4; i++) {
                            RenderHelper.drawTexturedRectangle(gui, ((int) posX + (10 * i) - 19), (int) posY - 4,
                                    heartsToDraw.get(i), 20, 9, 9);
                        }
                        break;
                    case 5:
                        for (int i = 0; i < 5; i++) {
                            RenderHelper.drawTexturedRectangle(gui, ((int) posX + (10 * i) - 23), (int) posY - 4,
                                    heartsToDraw.get(i), 20, 9, 9);
                        }
                        break;
                    }
                }
                GL11.glPopMatrix();

                GL11.glDepthMask(true);
                GL11.glEnable(GL11.GL_LIGHTING);
            }
        }

        catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * Renders a label above an entity's head.
     * 
     * @param human The entity that the label should be rendered on.
     * @param labelText The text that should appear on the label.
     */
    private void renderLabel(EntityHuman human, double posX, double posY, double posZ, String labelText) {
        if (human.isSneaking()) {
            final Tessellator tessellator = Tessellator.instance;
            final FontRenderer fontRendererObj = getFontRendererFromRenderManager();
            final int stringWidth = fontRendererObj.getStringWidth(labelText) / 2;

            GL11.glPushMatrix();
            {
                GL11.glTranslatef((float) posX + 0.0F, (float) posY + 2.3F, (float) posZ);
                GL11.glNormal3f(0.0F, 1.0F, 0.0F);
                GL11.glRotatef(-renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
                GL11.glRotatef(renderManager.playerViewX, 1.0F, 0.0F, 0.0F);
                GL11.glScalef(-LABEL_SCALE, -LABEL_SCALE, LABEL_SCALE);
                GL11.glDisable(GL11.GL_LIGHTING);
                GL11.glTranslatef(0.0F, 0.25F / LABEL_SCALE, 0.0F);
                GL11.glDepthMask(false);
                GL11.glEnable(GL11.GL_BLEND);
                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

                GL11.glDisable(GL11.GL_TEXTURE_2D);

                tessellator.startDrawingQuads();
                tessellator.setColorRGBA_F(0.0F, 0.0F, 0.0F, 0.25F);
                tessellator.addVertex(-stringWidth - 1, -1D, 0.0D);
                tessellator.addVertex(-stringWidth - 1, 8D, 0.0D);
                tessellator.addVertex(stringWidth + 1, 8D, 0.0D);
                tessellator.addVertex(stringWidth + 1, -1D, 0.0D);
                tessellator.draw();

                GL11.glEnable(GL11.GL_TEXTURE_2D);

                GL11.glDepthMask(true);
                fontRendererObj.drawString(labelText, -fontRendererObj.getStringWidth(labelText) / 2, 0,
                        0x20ffffff);
                GL11.glEnable(GL11.GL_LIGHTING);
                GL11.glDisable(GL11.GL_BLEND);
                GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
            }
            GL11.glPopMatrix();
        }

        else {
            //RenderLivingLabel
            func_147906_a(human, labelText, posX, posY, posZ, 64);
        }
    }

    protected boolean canRenderNameTag(EntityLivingBase entityRendering) {
        final EntityPlayer entityPlayer = Minecraft.getMinecraft().thePlayer;
        final Vec3 entityLookVector = Vec3.createVectorHelper(
                entityRendering.posX - entityPlayer.posX, entityRendering.boundingBox.minY
                        + (double) entityRendering.height / 2.0F - entityPlayer.posY + entityPlayer.getEyeHeight(),
                entityRendering.posZ - entityPlayer.posZ).normalize();
        final double dotProduct = entityPlayer.getLook(1.0F).normalize().dotProduct(entityLookVector);
        final boolean isPlayerLookingAt = dotProduct > 1.0D - 0.025D / entityLookVector.lengthVector()
                ? entityPlayer.canEntityBeSeen(entityRendering)
                : false;
        final double distance = entityRendering.getDistanceToEntity(renderManager.livingPlayer);

        return !(Minecraft.getMinecraft().currentScreen instanceof GuiInteraction) && distance < 5.0D
                && isPlayerLookingAt && Minecraft.isGuiEnabled() && entityRendering != renderManager.livingPlayer
                && !entityRendering.isInvisibleToPlayer(Minecraft.getMinecraft().thePlayer)
                && entityRendering.riddenByEntity == null;
    }
}