package client.renderer.entity;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.List;

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;

import client.renderer.DefaultVertexFormats;
import client.renderer.GlState;
import client.renderer.ItemRenderer;
import client.renderer.RenderBuffer;
import client.renderer.Tessellator;
import client.renderer.layers.LayerRenderer;
import client.renderer.model.ModelBase;
import client.renderer.texture.DynamicTexture;
import common.collect.Lists;
import common.entity.Entity;
import common.entity.item.EntityCrystal;
import common.entity.types.EntityAnimal;
import common.entity.types.EntityLiving;
import common.log.Log;
import common.util.ExtMath;
import common.util.Color;

public abstract class RendererLivingEntity<T extends EntityLiving> extends Render<T>
{
    private static final DynamicTexture textureBrightness = new DynamicTexture(16, 16);
    private static final String crystalBeamTextures = "textures/world/beam.png";
    protected ModelBase mainModel;
    protected FloatBuffer brightnessBuffer = ByteBuffer.allocateDirect(4 << 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
    protected List<LayerRenderer<T>> layerRenderers = Lists.<LayerRenderer<T>>newArrayList();
    protected boolean renderOutlines = false;

    public RendererLivingEntity(RenderManager renderManagerIn, ModelBase modelBaseIn)
    {
        super(renderManagerIn);
        this.mainModel = modelBaseIn;
//        this.shadowSize = shadowSizeIn;
    }

    protected <V extends EntityLiving, U extends LayerRenderer<V>> boolean addLayer(U layer)
    {
        return this.layerRenderers.add((LayerRenderer<T>)layer);
    }

    protected <V extends EntityLiving, U extends LayerRenderer<V>> boolean removeLayer(U layer)
    {
        return this.layerRenderers.remove(layer);
    }

    public ModelBase getMainModel()
    {
        return this.mainModel;
    }

    /**
     * Returns a rotation angle that is inbetween two other rotation angles. par1 and par2 are the angles between which
     * to interpolate, par3 is probably a float between 0.0 and 1.0 that tells us where "between" the two angles we are.
     * Example: par1 = 30, par2 = 50, par3 = 0.5, then return = 40
     */
    protected float interpolateRotation(float par1, float par2, float par3)
    {
        float f;

        for (f = par2 - par1; f < -180.0F; f += 360.0F)
        {
            ;
        }

        while (f >= 180.0F)
        {
            f -= 360.0F;
        }

        return par1 + par3 * f;
    }

//    public void transformHeldFull3DItemLayer()
//    {
//    }

    /**
     * Renders the desired {@code T} type Entity.
     */
    public void doRender(T entity, double x, double y, double z, float partialTicks)
    {
        GL11.glPushMatrix();
        GlState.disableCull();
        this.mainModel.swingProgress = this.getSwingProgress(entity, partialTicks);
        this.mainModel.isRiding = entity.isRiding();
        this.mainModel.isChild = entity instanceof EntityAnimal && ((EntityAnimal)entity).isChild();

        try
        {
            float f = this.interpolateRotation(entity.prevYawOffset, entity.yawOffset, partialTicks);
            float f1 = this.interpolateRotation(entity.prevHeadYaw, entity.headYaw, partialTicks);
            float f2 = f1 - f;

            if (entity.isRiding() && entity.vehicle instanceof EntityLiving)
            {
                EntityLiving entitylivingbase = (EntityLiving)entity.vehicle;
                f = this.interpolateRotation(entitylivingbase.prevYawOffset, entitylivingbase.yawOffset, partialTicks);
                f2 = f1 - f;
                float f3 = ExtMath.wrapf(f2);

                if (f3 < -85.0F)
                {
                    f3 = -85.0F;
                }

                if (f3 >= 85.0F)
                {
                    f3 = 85.0F;
                }

                f = f1 - f3;

                if (f3 * f3 > 2500.0F)
                {
                    f += f3 * 0.2F;
                }
            }

            float f7 = entity.prevPitch + (entity.rotPitch - entity.prevPitch) * partialTicks;
            this.renderLivingAt(entity, x, y, z);
            float f8 = this.handleRotationFloat(entity, partialTicks);
            this.rotateCorpse(entity, f8, f, partialTicks);
            GlState.enableRescaleNormal();
            GL11.glScalef(-1.0F, -1.0F, 1.0F);
            this.preRenderCallback(entity, partialTicks);
            float f4 = 0.0625F;
            GL11.glTranslatef(0.0F, -1.5078125F, 0.0F);
            float f5 = entity.prevLswingAmount + (entity.lswingAmount - entity.prevLswingAmount) * partialTicks;
            float f6 = entity.limbSwing - entity.lswingAmount * (1.0F - partialTicks);

            if (this.mainModel.isChild)
            {
                f6 *= 3.0F;
            }

            if (f5 > 1.0F)
            {
                f5 = 1.0F;
            }

            GlState.enableAlpha();
            this.mainModel.setLivingAnimations(entity, f6, f5, partialTicks);
            this.mainModel.setRotationAngles(f6, f5, f8, f2, f7, 0.0625F, entity);

            if (this.renderOutlines)
            {
                boolean flag1 = this.setOutlineColor(entity);
                this.renderModel(entity, f6, f5, f8, f2, f7, 0.0625F);

                if (flag1)
                {
                    this.unsetOutlineColor();
                }
            }
            else
            {
//                boolean flag = this.setDoRenderBrightness(entity, partialTicks);
                this.renderModel(entity, f6, f5, f8, f2, f7, 0.0625F);

//                if (flag)
//                {
//                    this.unsetBrightness();
//                }

                GlState.depthMask(true);

//                if (!(entity.isPlayer()) || !((EntityNPC)entity).isSpectator())
//                {
                this.renderLayers(entity, f6, f5, partialTicks, f8, f2, f7, 0.0625F);
//                }
            }

            GlState.disableRescaleNormal();
        }
        catch (Exception exception)
        {
        	Log.RENDER.error((Throwable)exception, (String)"Konnte Objekt nicht rendern");
        }

        GlState.setActiveTexture(GL13.GL_TEXTURE1);
        GlState.enableTexture2D();
        GlState.setActiveTexture(GL13.GL_TEXTURE0);
        GlState.enableCull();
        GL11.glPopMatrix();

        if (!this.renderOutlines)
        {
            super.doRender(entity, x, y, z, partialTicks);
        }
    }

    protected boolean setOutlineColor(T entityLivingBaseIn)
    {
        int // i = 16777215;

//        if (entityLivingBaseIn.isPlayer())
//        {
//            ScorePlayerTeam scoreplayerteam = (ScorePlayerTeam)((EntityNPC)entityLivingBaseIn).getTeam();
//
//            if (scoreplayerteam != null)
//            {
//                String s = FontRenderer.getFormatFromString(scoreplayerteam.getColorPrefix());
//
//                if (s.length() >= 1)
//                {
//                    i = this.getFontRendererFromRenderManager().getColorCode(s.charAt(0));
//                }
//            }
//        }
//        else {
        c = entityLivingBaseIn.getColor();
//        }

        float r = (float)(c >> 16 & 255) / 255.0F;
        float g = (float)(c >> 8 & 255) / 255.0F;
        float b = (float)(c & 255) / 255.0F;
        GlState.disableLighting();
        GlState.setActiveTexture(GL13.GL_TEXTURE0);
        GlState.color(r, g, b, 1.0F);
        GlState.disableTexture2D();
        GlState.setActiveTexture(GL13.GL_TEXTURE1);
        GlState.disableTexture2D();
        GlState.setActiveTexture(GL13.GL_TEXTURE0);
        return true;
    }

    protected void unsetOutlineColor()
    {
        GlState.enableLighting();
        GlState.setActiveTexture(GL13.GL_TEXTURE0);
        GlState.enableTexture2D();
        GlState.setActiveTexture(GL13.GL_TEXTURE1);
        GlState.enableTexture2D();
        GlState.setActiveTexture(GL13.GL_TEXTURE0);
    }
    
    protected void renderModel(T entity, float x, float y, float z, float yaw, float pitch, float scale)
    {
//        boolean vis = !entity.isInvisible();
        boolean ghost = entity.isGhost(); // ) || (!vis && !entity.isInvisible());

//        if (!entity.isInvisible())
//        {
        if (!this.bindEntityTexture(entity))
        {
            return;
        }

        if (ghost)
        {
            GL11.glPushMatrix();
            GlState.color(1.0F, 1.0F, 1.0F, 0.3F);
//                GlState.color(entity.getRenderColor() | (vis ? 0x50000000 : 0x26000000));
            GlState.depthMask(false);
            GlState.enableBlend();
            GlState.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
            GlState.alphaFunc(GL11.GL_GREATER, 0.003921569F);
        }

        if(entity.isGlowing())
            GlState.color(0.1F, 1.0F, 0.1F, 1.0F);
        if(entity.hurtTime > 0 || entity.deathTime > 0)
            GlState.color(1.0F, 0.5F, 0.5F, 1.0F);

        this.mainModel.render(entity, x, y, z, yaw, pitch, scale);

        if (ghost)
        {
            GlState.disableBlend();
            GlState.alphaFunc(GL11.GL_GREATER, 0.1F);
            GL11.glPopMatrix();
            GlState.depthMask(true);
        }
//        }
    }

//    protected boolean setDoRenderBrightness(T entityLivingBaseIn, float partialTicks)
//    {
//        return this.setBrightness(entityLivingBaseIn, partialTicks, true);
//    }

//    protected boolean setBrightness(T entitylivingbaseIn, float partialTicks, boolean combineTextures)
//    {
//    	return false;
//        float f = entitylivingbaseIn.getBrightness(partialTicks);
//        int i = this.getColorMultiplier(entitylivingbaseIn, f, partialTicks);
//        boolean flag = (i >> 24 & 255) > 0;
        // boolean flag1 = entitylivingbaseIn.hurtTime > 0 || entitylivingbaseIn.deathTime > 0;

//        if (!flag) //  && !flag1)
//        {
//            return false;
//        }
//        else if (!flag && !combineTextures)
//        {
//            return false;
//        }
//        else
//        {
//            GlState.setActiveTexture(SKC.GL_TEXTURE0);
//            GlState.enableTexture2D();
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_TEXTURE_ENV_MODE, SKC.GL_COMBINE);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_COMBINE_RGB, SKC.GL_MODULATE);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE0_RGB, SKC.GL_TEXTURE0);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE1_RGB, SKC.GL_PRIMARY_COLOR);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND0_RGB, SKC.GL_SRC_COLOR);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND1_RGB, SKC.GL_SRC_COLOR);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_COMBINE_ALPHA, SKC.GL_REPLACE);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE0_ALPHA, SKC.GL_TEXTURE0);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND0_ALPHA, SKC.GL_SRC_ALPHA);
//            GlState.setActiveTexture(SKC.GL_TEXTURE1);
//            GlState.enableTexture2D();
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_TEXTURE_ENV_MODE, SKC.GL_COMBINE);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_COMBINE_RGB, SKC.GL_INTERPOLATE);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE0_RGB, SKC.GL_CONSTANT);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE1_RGB, SKC.GL_PREVIOUS);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE2_RGB, SKC.GL_CONSTANT);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND0_RGB, SKC.GL_SRC_COLOR);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND1_RGB, SKC.GL_SRC_COLOR);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND2_RGB, SKC.GL_SRC_ALPHA);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_COMBINE_ALPHA, SKC.GL_REPLACE);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE0_ALPHA, SKC.GL_PREVIOUS);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND0_ALPHA, SKC.GL_SRC_ALPHA);
//            this.brightnessBuffer.position(0);
//
////            if (flag1)
////            {
////                this.brightnessBuffer.put(1.0F);
////                this.brightnessBuffer.put(0.0F);
////                this.brightnessBuffer.put(0.0F);
////                this.brightnessBuffer.put(0.3F);
////            }
////            else
////            {
//                float f1 = (float)(i >> 24 & 255) / 255.0F;
//                float f2 = (float)(i >> 16 & 255) / 255.0F;
//                float f3 = (float)(i >> 8 & 255) / 255.0F;
//                float f4 = (float)(i & 255) / 255.0F;
//                this.brightnessBuffer.put(f2);
//                this.brightnessBuffer.put(f3);
//                this.brightnessBuffer.put(f4);
//                this.brightnessBuffer.put(1.0F - f1);
////            }
//
//            this.brightnessBuffer.flip();
//            SKC.glTexEnv(SKC.GL_TEXTURE_ENV, SKC.GL_TEXTURE_ENV_COLOR, (FloatBuffer)this.brightnessBuffer);
//            GlState.setActiveTexture(SKC.GL_TEXTURE2);
//            GlState.enableTexture2D();
//            GlState.bindTexture(textureBrightness.getGlTextureId());
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_TEXTURE_ENV_MODE, SKC.GL_COMBINE);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_COMBINE_RGB, SKC.GL_MODULATE);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE0_RGB, SKC.GL_PREVIOUS);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE1_RGB, SKC.GL_TEXTURE1);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND0_RGB, SKC.GL_SRC_COLOR);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND1_RGB, SKC.GL_SRC_COLOR);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_COMBINE_ALPHA, SKC.GL_REPLACE);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE0_ALPHA, SKC.GL_PREVIOUS);
//            SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND0_ALPHA, SKC.GL_SRC_ALPHA);
//            GlState.setActiveTexture(SKC.GL_TEXTURE0);
//            return true;
//        }
//    }

//    protected void unsetBrightness()
//    {
//        GlState.setActiveTexture(SKC.GL_TEXTURE0);
//        GlState.enableTexture2D();
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_TEXTURE_ENV_MODE, SKC.GL_COMBINE);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_COMBINE_RGB, SKC.GL_MODULATE);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE0_RGB, SKC.GL_TEXTURE0);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE1_RGB, SKC.GL_PRIMARY_COLOR);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND0_RGB, SKC.GL_SRC_COLOR);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND1_RGB, SKC.GL_SRC_COLOR);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_COMBINE_ALPHA, SKC.GL_MODULATE);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE0_ALPHA, SKC.GL_TEXTURE0);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE1_ALPHA, SKC.GL_PRIMARY_COLOR);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND0_ALPHA, SKC.GL_SRC_ALPHA);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND1_ALPHA, SKC.GL_SRC_ALPHA);
//        GlState.setActiveTexture(SKC.GL_TEXTURE1);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_TEXTURE_ENV_MODE, SKC.GL_COMBINE);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_COMBINE_RGB, SKC.GL_MODULATE);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND0_RGB, SKC.GL_SRC_COLOR);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND1_RGB, SKC.GL_SRC_COLOR);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE0_RGB, SKC.GL_TEXTURE);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE1_RGB, SKC.GL_PREVIOUS);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_COMBINE_ALPHA, SKC.GL_MODULATE);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND0_ALPHA, SKC.GL_SRC_ALPHA);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE0_ALPHA, SKC.GL_TEXTURE);
//        GlState.color(1.0F, 1.0F, 1.0F, 1.0F);
//        GlState.setActiveTexture(SKC.GL_TEXTURE2);
//        GlState.disableTexture2D();
//        GlState.bindTexture(0);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_TEXTURE_ENV_MODE, SKC.GL_COMBINE);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_COMBINE_RGB, SKC.GL_MODULATE);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND0_RGB, SKC.GL_SRC_COLOR);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND1_RGB, SKC.GL_SRC_COLOR);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE0_RGB, SKC.GL_TEXTURE);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE1_RGB, SKC.GL_PREVIOUS);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_COMBINE_ALPHA, SKC.GL_MODULATE);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_OPERAND0_ALPHA, SKC.GL_SRC_ALPHA);
//        SKC.glTexEnvi(SKC.GL_TEXTURE_ENV, SKC.GL_SOURCE0_ALPHA, SKC.GL_TEXTURE);
//        GlState.setActiveTexture(SKC.GL_TEXTURE0);
//    }

    /**
     * Sets a simple glTranslate on a LivingEntity.
     */
    protected void renderLivingAt(T entityLivingBaseIn, double x, double y, double z)
    {
        GL11.glTranslatef((float)x, (float)y, (float)z);
    }

    protected void rotateCorpse(T bat, float p_77043_2_, float p_77043_3_, float partialTicks)
    {
        GL11.glRotatef(180.0F - p_77043_3_, 0.0F, 1.0F, 0.0F);

        if (bat.deathTime > 0)
        {
            float f = ((float)bat.deathTime + partialTicks - 1.0F) / 20.0F * 1.6F;
            f = ExtMath.sqrtf(f);

            if (f > 1.0F)
            {
                f = 1.0F;
            }

            GL11.glRotatef(f * this.getDeathMaxRotation(bat), 0.0F, 0.0F, 1.0F);
        }
        else
        {
            String s = Color.stripCodes(bat.getCustomNameTag());

            if (s != null && (s.startsWith("Australia") || s.startsWith("Australien"))) // && (!(bat.isPlayer()) || ((EntityNPC)bat).isWearing(ModelPart.CAPE)))
            {
                GL11.glTranslatef(0.0F, bat.height + 0.1F, 0.0F);
                GL11.glRotatef(180.0F, 0.0F, 0.0F, 1.0F);
            }
        }
    }

    /**
     * Returns where in the swing animation the living entity is (from 0 to 1).  Args : entity, partialTickTime
     */
    protected float getSwingProgress(T livingBase, float partialTickTime)
    {
        return livingBase.getSwingProgress(partialTickTime);
    }

    /**
     * Defines what float the third param in setRotationAngles of ModelBase is
     */
    protected float handleRotationFloat(T livingBase, float partialTicks)
    {
        return (float)livingBase.ticksExisted + partialTicks;
    }

    protected void renderLayers(T entity, float swing, float amount, float partial, float time, float dYaw, float dPitch, float scale) {
        for(LayerRenderer<T> layer : this.layerRenderers) {
//            boolean bright = this.setBrightness(entity, partial, layer.shouldCombineTextures());
            layer.doRenderLayer(entity, swing, amount, partial, time, dYaw, dPitch, scale);
//            if(bright)
//            	this.unsetBrightness();
        }
    }

    protected float getDeathMaxRotation(T entityLivingBaseIn)
    {
        return 90.0F;
    }

    /**
     * Returns an ARGB int color back. Args: entityLiving, lightBrightness, partialTickTime
     */
//    protected int getColorMultiplier(T entitylivingbaseIn, float lightBrightness, float partialTickTime)
//    {
//        return 0;
//    }

    /**
     * Allows the render to do any OpenGL state modifications necessary before the model is rendered. Args:
     * entityLiving, partialTickTime
     */
    protected void preRenderCallback(T entitylivingbaseIn, float partialTickTime)
    {
    }
    
    
    
//    protected boolean canRenderStats(T entity) {
//    	return entity.isEntityAlive() && !entity.isInvisible();
//    }

    public void renderName(T entity, double x, double y, double z)
    {
    	String name = entity.getLabel();
    	if(name != null && !name.isEmpty())
			this.manager.renderLabel(entity, name, x, entity.isSneakingVisually() ? y - 0.25 : y, z, 64);
        if(entity.isEntityAlive())
			this.manager.renderLabel(entity, entity.formatStats(), x, (entity.isSneakingVisually() ? y - 0.25 : y) + 0.3, z, 32);
    }

//    protected boolean canRenderName(T entity)
//    {
//        return entity != this.renderManager.livingPlayer && !entity.isInvisible() && entity.passenger == null;
//    }

    public void setRenderOutlines(boolean renderOutlinesIn)
    {
        this.renderOutlines = renderOutlinesIn;
    }
    
    protected void drawRechargeRay(Entity entity, EntityCrystal crystal, double p_180574_2_, double p_180574_4_, double p_180574_6_, float p_180574_8_)
    {
        float f = (float)crystal.innerRotation + p_180574_8_;
        float f1 = ExtMath.sin(f * 0.2F) / 2.0F + 0.5F;
        f1 = (f1 * f1 + f1) * 0.2F;
        float f2 = (float)(crystal.posX - entity.posX - (entity.prevX - entity.posX) * (double)(1.0F - p_180574_8_));
        float f3 = (float)((double)f1 + crystal.posY - 1.0D - entity.posY - (entity.prevY - entity.posY) * (double)(1.0F - p_180574_8_));
        float f4 = (float)(crystal.posZ - entity.posZ - (entity.prevZ - entity.posZ) * (double)(1.0F - p_180574_8_));
        float f5 = ExtMath.sqrtf(f2 * f2 + f4 * f4);
        float f6 = ExtMath.sqrtf(f2 * f2 + f3 * f3 + f4 * f4);
        GL11.glPushMatrix();
        GL11.glTranslatef((float)p_180574_2_, (float)p_180574_4_ + 2.0F, (float)p_180574_6_);
        GL11.glRotatef((float)(-Math.atan2((double)f4, (double)f2)) * 180.0F / (float)Math.PI - 90.0F, 0.0F, 1.0F, 0.0F);
        GL11.glRotatef((float)(-Math.atan2((double)f5, (double)f3)) * 180.0F / (float)Math.PI - 90.0F, 1.0F, 0.0F, 0.0F);
//        Tessellator tessellator = Tessellator.getInstance();
        RenderBuffer worldrenderer = Tessellator.getBuffer();
        ItemRenderer.disableStandardItemLighting();
        GlState.disableCull();
        this.bindTexture(crystalBeamTextures);
        GlState.shadeModel(GL11.GL_SMOOTH);
        float f7 = 0.0F - ((float)entity.ticksExisted + p_180574_8_) * 0.01F;
        float f8 = ExtMath.sqrtf(f2 * f2 + f3 * f3 + f4 * f4) / 32.0F - ((float)entity.ticksExisted + p_180574_8_) * 0.01F;
        worldrenderer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_COLOR);
        int i = 8;

        for (int j = 0; j <= 8; ++j)
        {
            float f9 = ExtMath.sin((float)(j % 8) * (float)Math.PI * 2.0F / 8.0F) * 0.75F;
            float f10 = ExtMath.cos((float)(j % 8) * (float)Math.PI * 2.0F / 8.0F) * 0.75F;
            float f11 = (float)(j % 8) * 1.0F / 8.0F;
            worldrenderer.pos((double)(f9 * 0.2F), (double)(f10 * 0.2F), 0.0D).tex((double)f11, (double)f8).color(0, 0, 0, 255).endVertex();
            worldrenderer.pos((double)f9, (double)f10, (double)f6).tex((double)f11, (double)f7).color(255, 255, 255, 255).endVertex();
        }

        Tessellator.draw();
        GlState.enableCull();
        GlState.shadeModel(GL11.GL_FLAT);
        ItemRenderer.enableStandardItemLighting();
        GL11.glPopMatrix();
    }

    static
    {
        int[] aint = textureBrightness.getData();

        for (int i = 0; i < 256; ++i)
        {
            aint[i] = -1;
        }

        textureBrightness.updateTexture();
    }
}
