code:
package astrotibs.notenoughpets.client.model;

import net.minecraft.client.model.ModelOcelot;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.Entity;
import net.minecraft.entity.passive.EntityOcelot;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

//Added annotation in v1.2.1
@SideOnly(Side.CLIENT)
public class ModelOcelotNEP extends ModelOcelot
{
    ModelRenderer ocelotBackLeftLeg = ReflectionHelper.getPrivateValue( ModelOcelot.class, this, new String[]{"ocelotBackLeftLeg", "field_78161_a"} );
    ModelRenderer ocelotBackRightLeg = ReflectionHelper.getPrivateValue( ModelOcelot.class, this, new String[]{"ocelotBackRightLeg", "field_78159_b"} );
    ModelRenderer ocelotFrontLeftLeg = ReflectionHelper.getPrivateValue( ModelOcelot.class, this, new String[]{"ocelotFrontLeftLeg", "field_78160_c"} );
    ModelRenderer ocelotFrontRightLeg = ReflectionHelper.getPrivateValue( ModelOcelot.class, this, new String[]{"ocelotFrontRightLeg", "field_78157_d"} );
    ModelRenderer ocelotTail = ReflectionHelper.getPrivateValue( ModelOcelot.class, this, new String[]{"ocelotTail", "field_78158_e"} );
    ModelRenderer ocelotTail2 = ReflectionHelper.getPrivateValue( ModelOcelot.class, this, new String[]{"ocelotTail2", "field_78155_f"} );
    ModelRenderer ocelotHead = ReflectionHelper.getPrivateValue( ModelOcelot.class, this, new String[]{"ocelotHead", "field_78156_g"} );
    ModelRenderer ocelotBody = ReflectionHelper.getPrivateValue( ModelOcelot.class, this, new String[]{"ocelotBody", "field_78162_h"} );

    /**
     * Sets the models various rotation angles then renders the model.
     */
    @Override
    public void render(Entity entityIn, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scale)
    {
    	//super.render(entityIn, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale);*/

    	// Re-enabled in v1.2.1
    	float agescale = this.isChild ? 1F-(((float)((EntityOcelot)entityIn).getGrowingAge())/-24000) : 1F;

    	// Modify limb swing depending on age
    	if (this.isChild)
    	{
    		limbSwing /= 3F; // Remove the 3x speed assigned to children
    		limbSwing *= (2F - agescale);
    	}

        this.setRotationAngles(limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale, entityIn);

		// summon notenoughcats.Ocelot_NEC ~ ~ ~ {Owner:AstroTibs, CatType:0}
		// summon notenoughcats.Ocelot_NEC ~ ~ ~ {Owner:AstroTibs, CatType:15, Age:-24000}
		// summon notenoughcats.Ocelot_NEC ~ ~ ~ {CatType:2}

        //int field_175502_b_f = ReflectionHelper.getPrivateValue( EntityAgeable.class, (EntityAgeable)entityIn, new String[]{"field_175502_b"} );

        if (this.isChild)
        {
            // Render the head
            // Kitten head is 3/4 of adult size

            GlStateManager.pushMatrix();
            float headscale = MathHelper.clamp_float(0.75F + agescale*0.25F, 0.75F, 1F);
            GlStateManager.scale(headscale, headscale, headscale);
            float headYpos = MathHelper.clamp_float( (11F*(1F-agescale)) * scale, 0F, 11F * scale);
            float headZpos = MathHelper.clamp_float( (3F*(1F-agescale)) * scale, 0F, 3F * scale);
            GlStateManager.translate(0.0F, headYpos, headZpos);
            this.ocelotHead.render(scale);
            GlStateManager.popMatrix();

            // Render the body
            // Kitten body is half of adult size

            GlStateManager.pushMatrix();
            float bodyscale = MathHelper.clamp_float(0.5F + agescale*0.5F, 0.5F, 1F);
            GlStateManager.scale(bodyscale, bodyscale, bodyscale);

            float bodypospow = 0.65F; //

            float bodyYpos = MathHelper.clamp_float(
            		(float)(24F*(
            				1-agescale + (0.6*((agescale-0.5)*(agescale-0.5))-0.15)
            				))
            		* scale, 0F, 24.0F * scale);
            GlStateManager.translate(0.0F, bodyYpos, 0.0F);

            this.ocelotBody.render(scale);
            this.ocelotBackLeftLeg.render(scale);
            this.ocelotBackRightLeg.render(scale);
            this.ocelotFrontLeftLeg.render(scale);
            this.ocelotFrontRightLeg.render(scale);
            this.ocelotTail.render(scale);
            this.ocelotTail2.render(scale);
            GlStateManager.popMatrix();
        }
        else
        {
            super.render(entityIn, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale);
        }

    }

}


code:
package astrotibs.notenoughpets.client.model;

import astrotibs.notenoughpets.entity.EntityParrotNEP;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

/**
 * Pretty much pasted wholesale from 1.12
 */
@SideOnly(Side.CLIENT)
public class ModelParrotNEP extends ModelBase
{
    ModelRenderer body;
    ModelRenderer tail;
    ModelRenderer wingLeft;
    ModelRenderer wingRight;
    ModelRenderer head;
    ModelRenderer head2;
    ModelRenderer beak1;
    ModelRenderer beak2;
    ModelRenderer feather;
    ModelRenderer legLeft;
    ModelRenderer legRight;
    int shoulderAge;
    private ModelParrotNEP.State state = ModelParrotNEP.State.STANDING;

    public ModelParrotNEP(int shoulderAge)
    {
    	this.shoulderAge = shoulderAge;
        this.textureWidth = 32;
        this.textureHeight = 32;
        this.body = new ModelRenderer(this, 2, 8);
        this.body.addBox(-1.5F, 0.0F, -1.5F, 3, 6, 3);
        this.body.setRotationPoint(0.0F, 16.5F, -3.0F);
        this.tail = new ModelRenderer(this, 22, 1);
        this.tail.addBox(-1.5F, -1.0F, -1.0F, 3, 4, 1);
        this.tail.setRotationPoint(0.0F, 21.07F, 1.16F);
        this.wingLeft = new ModelRenderer(this, 19, 8);
        this.wingLeft.addBox(-0.5F, 0.0F, -1.5F, 1, 5, 3);
        this.wingLeft.setRotationPoint(1.5F, 16.94F, -2.76F);
        this.wingRight = new ModelRenderer(this, 19, 8);
        this.wingRight.addBox(-0.5F, 0.0F, -1.5F, 1, 5, 3);
        this.wingRight.setRotationPoint(-1.5F, 16.94F, -2.76F);
        this.head = new ModelRenderer(this, 2, 2);
        this.head.addBox(-1.0F, -1.5F, -1.0F, 2, 3, 2);
        this.head.setRotationPoint(0.0F, 15.69F, -2.76F);
        this.head2 = new ModelRenderer(this, 10, 0);
        this.head2.addBox(-1.0F, -0.5F, -2.0F, 2, 1, 4);
        this.head2.setRotationPoint(0.0F, -2.0F, -1.0F);
        this.head.addChild(this.head2);
        this.beak1 = new ModelRenderer(this, 11, 7);
        this.beak1.addBox(-0.5F, -1.0F, -0.5F, 1, 2, 1);
        this.beak1.setRotationPoint(0.0F, -0.5F, -1.5F);
        this.head.addChild(this.beak1);
        this.beak2 = new ModelRenderer(this, 16, 7);
        this.beak2.addBox(-0.5F, 0.0F, -0.5F, 1, 2, 1);
        this.beak2.setRotationPoint(0.0F, -1.75F, -2.45F);
        this.head.addChild(this.beak2);
        this.feather = new ModelRenderer(this, 2, 18);
        this.feather.addBox(0.0F, -4.0F, -2.0F, 0, 5, 4);
        this.feather.setRotationPoint(0.0F, -2.15F, 0.15F);
        this.head.addChild(this.feather);
        this.legLeft = new ModelRenderer(this, 14, 18);
        this.legLeft.addBox(-0.5F, 0.0F, -0.5F, 1, 2, 1);
        this.legLeft.setRotationPoint(1.0F, 22.0F, -1.05F);
        this.legRight = new ModelRenderer(this, 14, 18);
        this.legRight.addBox(-0.5F, 0.0F, -0.5F, 1, 2, 1);
        this.legRight.setRotationPoint(-1.0F, 22.0F, -1.05F);
    }

    /**
     * Sets the models various rotation angles then renders the model.
     */
    @Override
    public void render(Entity entityIn, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scale)
    {
    	float agescale = 1F;

    	if (entityIn instanceof EntityParrotNEP)
    	{
    		agescale = MathHelper.clamp_float(1F-(((float)((EntityParrotNEP)entityIn).getGrowingAge())/-24000), 0F, 1F);
    	}
    	else if (entityIn instanceof EntityPlayer)
    	{
    		agescale = MathHelper.clamp_float(1F-(((float)this.shoulderAge)/-24000), 0F, 1F);
    	}
    	// Modify limb swing depending on age
		limbSwing *= (2F - agescale);
    	this.setRotationAngles(limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale, entityIn);

    	// Scaling the head
    	GlStateManager.pushMatrix();
        float headscale = MathHelper.clamp_float(0.65F + agescale*0.35F, 0.65F, 1F);
        GlStateManager.scale(headscale, headscale, headscale);
        //GlStateManager.translate(0, 0, (1F-headscale)*-0.4F);
        float headYpos = (float) MathHelper.clamp_double( (14F * Math.pow(1F-agescale, 1.4F)) * scale, 0F, 14F * scale);
        float headZpos = MathHelper.clamp_float( (0.7F*(1F-agescale)) * scale, 0F, 0.7F * scale);
        GlStateManager.translate(0.0F, headYpos, headZpos);
        this.head.render(scale);
        GlStateManager.popMatrix();

        // Scaling the body
        GlStateManager.pushMatrix();
        float bodyscale = (float) MathHelper.clamp_double(0.5F + Math.pow(agescale, 1.1)*0.5F, 0.5F, 1F);
        GlStateManager.scale(bodyscale, bodyscale, bodyscale);
        GlStateManager.translate(0.0F, (agescale-1F)*0.01F, 0.0F);

        float bodyYpos = MathHelper.clamp_float(
        		(float)(24F*(
        				1-agescale + (0.5*(agescale-0.5)*(agescale-0.5)-0.15)
        				))
        		* scale, 0F, 24.0F * scale);
        GlStateManager.translate(0.0F, bodyYpos, 0.0F);

        this.body.render(scale);
        this.wingLeft.render(scale);
        this.wingRight.render(scale);
        this.tail.render(scale);
        this.legLeft.render(scale);
        this.legRight.render(scale);
        GlStateManager.popMatrix();
    }

    /**
     * Sets the model's various rotation angles. For bipeds, par1 and par2 are used for animating the movement of arms
     * and legs, where par1 represents the time(so that arms and legs swing back and forth) and par2 represents how
     * "far" arms and legs can swing at most.
     */
    @Override
    public void setRotationAngles(float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scaleFactor, Entity entityIn)
    {
        float f = ageInTicks * 0.3F;
        this.head.rotateAngleX = headPitch * 0.017453292F;
        this.head.rotateAngleY = netHeadYaw * 0.017453292F;
        this.head.rotateAngleZ = 0.0F;
        this.head.rotationPointX = 0.0F;
        this.body.rotationPointX = 0.0F;
        this.tail.rotationPointX = 0.0F;
        this.wingRight.rotationPointX = -1.5F;
        this.wingLeft.rotationPointX = 1.5F;

        if (this.state != ModelParrotNEP.State.FLYING)
        {
            if (this.state == ModelParrotNEP.State.SITTING)
            {
                return;
            }

            if (this.state == ModelParrotNEP.State.PARTY)
            {
                float f1 = MathHelper.cos((float)entityIn.ticksExisted);
                float f2 = MathHelper.sin((float)entityIn.ticksExisted);
                this.head.rotationPointX = f1;
                this.head.rotationPointY = 15.69F + f2;
                this.head.rotateAngleX = 0.0F;
                this.head.rotateAngleY = 0.0F;
                this.head.rotateAngleZ = MathHelper.sin((float)entityIn.ticksExisted) * 0.4F;
                this.body.rotationPointX = f1;
                this.body.rotationPointY = 16.5F + f2;
                this.wingLeft.rotateAngleZ = -0.0873F - ageInTicks;
                this.wingLeft.rotationPointX = 1.5F + f1;
                this.wingLeft.rotationPointY = 16.94F + f2;
                this.wingRight.rotateAngleZ = 0.0873F + ageInTicks;
                this.wingRight.rotationPointX = -1.5F + f1;
                this.wingRight.rotationPointY = 16.94F + f2;
                this.tail.rotationPointX = f1;
                this.tail.rotationPointY = 21.07F + f2;
                return;
            }

            this.legLeft.rotateAngleX += MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbSwingAmount;
            this.legRight.rotateAngleX += MathHelper.cos(limbSwing * 0.6662F + (float)Math.PI) * 1.4F * limbSwingAmount;
        }

        this.head.rotationPointY = 15.69F + f;
        this.tail.rotateAngleX = 1.015F + MathHelper.cos(limbSwing * 0.6662F) * 0.3F * limbSwingAmount;
        this.tail.rotationPointY = 21.07F + f;
        this.body.rotationPointY = 16.5F + f;
        this.wingLeft.rotateAngleZ = -0.0873F - ageInTicks;
        this.wingLeft.rotationPointY = 16.94F + f;
        this.wingRight.rotateAngleZ = 0.0873F + ageInTicks;
        this.wingRight.rotationPointY = 16.94F + f;
        this.legLeft.rotationPointY = 22.0F + f;
        this.legRight.rotationPointY = 22.0F + f;
    }

    /**
     * Used for easily adding entity-dependent animations. The second and third float params here are the same second
     * and third as in the setRotationAngles method.
     */
    @Override
    public void setLivingAnimations(EntityLivingBase entitylivingbaseIn, float limbSwing, float limbSwingAmount, float partialTickTime)
    {
        this.feather.rotateAngleX = -0.2214F;
        this.body.rotateAngleX = 0.4937F;
        this.wingLeft.rotateAngleX = -((float)Math.PI * 2F / 9F);
        this.wingLeft.rotateAngleY = -(float)Math.PI;
        this.wingRight.rotateAngleX = -((float)Math.PI * 2F / 9F);
        this.wingRight.rotateAngleY = -(float)Math.PI;
        this.legLeft.rotateAngleX = -0.0299F;
        this.legRight.rotateAngleX = -0.0299F;
        this.legLeft.rotationPointY = 22.0F;
        this.legRight.rotationPointY = 22.0F;

        if (entitylivingbaseIn instanceof EntityParrotNEP)
        {
        	EntityParrotNEP entityparrot = (EntityParrotNEP)entitylivingbaseIn;

            if (entityparrot.isPartying())
            {
                this.legLeft.rotateAngleZ = -0.34906584F;
                this.legRight.rotateAngleZ = 0.34906584F;
                this.state = ModelParrotNEP.State.PARTY;
                return;
            }

            if (entityparrot.isSitting())
            {
                float f = 1.9F;
                this.head.rotationPointY = 17.59F;
                this.tail.rotateAngleX = 1.5388988F;
                this.tail.rotationPointY = 22.97F;
                this.body.rotationPointY = 18.4F;
                this.wingLeft.rotateAngleZ = -0.0873F;
                this.wingLeft.rotationPointY = 18.84F;
                this.wingRight.rotateAngleZ = 0.0873F;
                this.wingRight.rotationPointY = 18.84F;
                ++this.legLeft.rotationPointY;
                ++this.legRight.rotationPointY;
                ++this.legLeft.rotateAngleX;
                ++this.legRight.rotateAngleX;
                this.state = ModelParrotNEP.State.SITTING;
            }
            else if (entityparrot.isFlying())
            {
                this.legLeft.rotateAngleX += ((float)Math.PI * 2F / 9F);
                this.legRight.rotateAngleX += ((float)Math.PI * 2F / 9F);
                this.state = ModelParrotNEP.State.FLYING;
            }
            else
            {
                this.state = ModelParrotNEP.State.STANDING;
            }

            this.legLeft.rotateAngleZ = 0.0F;
            this.legRight.rotateAngleZ = 0.0F;
        }
    }

    @SideOnly(Side.CLIENT)
    static enum State
    {
        FLYING,
        STANDING,
        SITTING,
        PARTY;
    }
}

license: unknown


code:
package astrotibs.notenoughpets.client.model;

import net.minecraft.client.model.ModelRenderer;
import net.minecraft.client.model.ModelWolf;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.passive.EntityWolf;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

//Added in v1.2
@SideOnly(Side.CLIENT)
public class ModelWolfNEP extends ModelWolf
{

  ModelRenderer wolfTail = ReflectionHelper.getPrivateValue( ModelWolf.class, this, new String[]{"wolfTail", "field_78180_g"} );
  ModelRenderer wolfMane = ReflectionHelper.getPrivateValue( ModelWolf.class, this, new String[]{"wolfMane", "field_78186_h"} );

  /**
   * Sets the models various rotation angles then renders the model.
   */
  @Override
  public void render(Entity entityIn, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scale)
  {

	  //super.render(entityIn, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale);

	  // Re-enabled in v1.2.1
	  float agescale = this.isChild ? 1F-(((float)((EntityWolf)entityIn).getGrowingAge())/-24000) : 1F;

	  // Modify limb swing depending on age
	  if (this.isChild)
	  {
		  limbSwing /= 3F; // Remove the 3x speed assigned to children
		  limbSwing *= (2F - agescale);
	  }

	  this.setRotationAngles(limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale, entityIn);

	  // summon notenoughcats.Wolf_NEC ~ ~ ~ {Owner:AstroTibs}
	  // summon notenoughcats.Wolf_NEC ~ ~ ~ {Owner:AstroTibs, Age:-24000}
	  // summon notenoughcats.Wolf_NEC ~ ~ ~

	  //LogHelper.info("age: " + ((float)((EntityWolf)entityIn).getGrowingAge()) );

	  if (this.isChild)
      {
          // Render the head
          // Puppy head is same as adult size
          //LogHelper.info("age: " + ((EntityWolf)entityIn).getGrowingAge());
		  GlStateManager.pushMatrix();
          float headscale = MathHelper.clamp_float(0.75F + agescale*0.25F, 0.75F, 1F);
          GlStateManager.scale(headscale, headscale, headscale);
          float headYpos = MathHelper.clamp_float( (11F*(1F-agescale)) * scale, 0F, 11F * scale);
          float headZpos = MathHelper.clamp_float( (2F*(1F-agescale)) * scale, 0F, 3F * scale);
          GlStateManager.translate(0.0F, headYpos, headZpos);
          this.wolfHeadMain.renderWithRotation(scale);
          GlStateManager.popMatrix();

          // Render the body
          // Puppy body is half of adult size

          GlStateManager.pushMatrix();
          float bodyscale = MathHelper.clamp_float(0.5F + agescale*0.5F, 0.5F, 1F);
          GlStateManager.scale(bodyscale, bodyscale, bodyscale);

          float bodypospow = 0.65F; //

          float bodyYpos = MathHelper.clamp_float(
          		(float)
          		(24F*(
          				1-agescale + (0.6*((agescale-0.5)*(agescale-0.5))-0.15)
          				))
          		* scale, 0F, 24.0F * scale);
          GlStateManager.translate(0.0F, bodyYpos, 0.0F);
          this.wolfBody.render(scale);
          this.wolfLeg1.render(scale);
          this.wolfLeg2.render(scale);
          this.wolfLeg3.render(scale);
          this.wolfLeg4.render(scale);
          this.wolfTail.renderWithRotation(scale);
          this.wolfMane.render(scale);
          GlStateManager.popMatrix();
      }
      else
      {
      	super.render(entityIn, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale);
      }

  }

  /**
   * I'm adding this in so that I can toy with leg animation speed.
   */
  @Override
  public void setLivingAnimations(EntityLivingBase wolf, float limbSwing, float limbSwingAmount, float headCock)
  {
  	float agescale = this.isChild ? 1F-(((float)((EntityWolf)wolf).getGrowingAge())/-24000) : 1F;

  	// Modify limb swing depending on age
  	if (this.isChild)
  	{
  		limbSwing /= 3F; // Remove the 3x speed assigned to children
  		limbSwing *= (2F - agescale);
  	}

  	super.setLivingAnimations(wolf, limbSwing, limbSwingAmount, headCock);
  }
}


code:
package astrotibs.notenoughpets.client.render;

import astrotibs.notenoughpets.entity.EntityMooshroomNEP;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.ModelQuadruped;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.layers.LayerRenderer;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.passive.EntityMooshroom;
import net.minecraft.init.Blocks;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

@SideOnly(Side.CLIENT)
public class LayerMooshroomMushroomNEP implements LayerRenderer<EntityMooshroom>
{
    private final RenderMooshroomNEP mooshroomRenderer;

    public LayerMooshroomMushroomNEP(RenderMooshroomNEP mooshroomRendererIn)
    {
        this.mooshroomRenderer = mooshroomRendererIn;
    }

    public void doRenderLayer(EntityMooshroom entitylivingbaseIn, float p_177141_2_, float p_177141_3_, float partialTicks, float p_177141_5_, float p_177141_6_, float p_177141_7_, float scale)
    {
        if (!entitylivingbaseIn.isChild() && !entitylivingbaseIn.isInvisible())
        {
            BlockRendererDispatcher blockrendererdispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
            this.mooshroomRenderer.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
            GlStateManager.enableCull();
            GlStateManager.cullFace(GlStateManager.CullFace.FRONT);
            GlStateManager.pushMatrix();
            GlStateManager.scale(1.0F, -1.0F, 1.0F);
            GlStateManager.translate(0.2F, 0.35F, 0.5F);
            GlStateManager.rotate(42.0F, 0.0F, 1.0F, 0.0F);
            GlStateManager.pushMatrix();
            GlStateManager.translate(-0.5F, -0.5F, 0.5F);
            blockrendererdispatcher.renderBlockBrightness(
            		(entitylivingbaseIn instanceof EntityMooshroomNEP && ((EntityMooshroomNEP)entitylivingbaseIn).getVarietySkin()!=0 ?
            				Blocks.BROWN_MUSHROOM : Blocks.RED_MUSHROOM).getDefaultState(), 1.0F
            		);
            GlStateManager.popMatrix();
            GlStateManager.pushMatrix();
            GlStateManager.translate(0.1F, 0.0F, -0.6F);
            GlStateManager.rotate(42.0F, 0.0F, 1.0F, 0.0F);
            GlStateManager.translate(-0.5F, -0.5F, 0.5F);
            blockrendererdispatcher.renderBlockBrightness(
            		(entitylivingbaseIn instanceof EntityMooshroomNEP && ((EntityMooshroomNEP)entitylivingbaseIn).getVarietySkin()!=0 ?
            				Blocks.BROWN_MUSHROOM : Blocks.RED_MUSHROOM).getDefaultState(), 1.0F
            		);
            GlStateManager.popMatrix();
            GlStateManager.popMatrix();
            GlStateManager.pushMatrix();
            ((ModelQuadruped)this.mooshroomRenderer.getMainModel()).head.postRender(0.0625F);
            GlStateManager.scale(1.0F, -1.0F, 1.0F);
            GlStateManager.translate(0.0F, 0.7F, -0.2F);
            GlStateManager.rotate(12.0F, 0.0F, 1.0F, 0.0F);
            GlStateManager.translate(-0.5F, -0.5F, 0.5F);
            blockrendererdispatcher.renderBlockBrightness(
            		(entitylivingbaseIn instanceof EntityMooshroomNEP && ((EntityMooshroomNEP)entitylivingbaseIn).getVarietySkin()!=0 ?
            				Blocks.BROWN_MUSHROOM : Blocks.RED_MUSHROOM).getDefaultState(), 1.0F
            		);
            GlStateManager.popMatrix();
            GlStateManager.cullFace(GlStateManager.CullFace.BACK);
            GlStateManager.disableCull();
        }
    }

    public boolean shouldCombineTextures()
    {
        return true;
    }
}


code:
package astrotibs.notenoughpets.client.render;

import astrotibs.notenoughpets.entity.EntityOcelotNEP;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.layers.LayerRenderer;
import net.minecraft.entity.passive.EntitySheep;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

@SideOnly(Side.CLIENT)
public class LayerOcelotCollar implements LayerRenderer<EntityOcelotNEP>
{
    private static final ResourceLocation OCELOT_COLLAR = new ResourceLocation("textures/entity/cat/cat_collar.png");
    private final RenderOcelotNEP ocelotNECRender;

    public LayerOcelotCollar(RenderOcelotNEP ocelotRenderIn)
    {
        this.ocelotNECRender = ocelotRenderIn;
    }

    public void doRenderLayer(EntityOcelotNEP entitylivingbaseIn, float p_177141_2_, float p_177141_3_, float partialTicks, float p_177141_5_, float p_177141_6_, float p_177141_7_, float scale)
    {
        if (entitylivingbaseIn.isTamed() && !entitylivingbaseIn.isInvisible())
        {
            this.ocelotNECRender.bindTexture(OCELOT_COLLAR);
            EnumDyeColor enumdyecolor = EnumDyeColor.byMetadata(entitylivingbaseIn.getCollarColor().getMetadata());
            float[] afloat = EntitySheep.getDyeRgb(enumdyecolor);
            GlStateManager.color(afloat[0], afloat[1], afloat[2]);
            this.ocelotNECRender.getMainModel().render(entitylivingbaseIn, p_177141_2_, p_177141_3_, p_177141_5_, p_177141_6_, p_177141_7_, scale);
        }
    }

    public boolean shouldCombineTextures()
    {
        return true;
    }
}


code:
package astrotibs.notenoughpets.client.render;

import astrotibs.notenoughpets.entity.EntityWolfNEP;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.layers.LayerRenderer;
import net.minecraft.entity.passive.EntitySheep;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

@SideOnly(Side.CLIENT)
public class LayerWolfCollarNEP implements LayerRenderer<EntityWolfNEP>
{
    private static final ResourceLocation WOLF_COLLAR = new ResourceLocation("textures/entity/wolf/wolf_collar.png");
    private final RenderWolfNEP wolfRenderer;

    public LayerWolfCollarNEP(RenderWolfNEP wolfRendererIn)
    {
        this.wolfRenderer = wolfRendererIn;
    }

    public void doRenderLayer(EntityWolfNEP entitylivingbaseIn, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, float scale)
    {
        if (entitylivingbaseIn.isTamed() && !entitylivingbaseIn.isInvisible())
        {
            this.wolfRenderer.bindTexture(WOLF_COLLAR);
            float[] afloat = EntitySheep.getDyeRgb(entitylivingbaseIn.getCollarColor());
            GlStateManager.color(afloat[0], afloat[1], afloat[2]);
            this.wolfRenderer.getMainModel().render(entitylivingbaseIn, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale);
        }
    }

    public boolean shouldCombineTextures()
    {
        return true;
    }

}


code:
package astrotibs.notenoughpets.client.render;

import astrotibs.notenoughpets.entity.EntityMooshroomNEP;
import astrotibs.notenoughpets.util.SkinVariations;
import net.minecraft.client.model.ModelCow;
import net.minecraft.client.renderer.entity.RenderLiving;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.passive.EntityMooshroom;
import net.minecraft.util.ResourceLocation;

public class RenderMooshroomNEP extends RenderLiving<EntityMooshroom>
{
    public RenderMooshroomNEP(RenderManager renderManagerIn)
    {
    	super(renderManagerIn, new ModelCow(), 0.7F);
        this.addLayer(new LayerMooshroomMushroomNEP(this));
    }

    /**
     * Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture.
     */
	@Override
    protected ResourceLocation getEntityTexture(EntityMooshroom mooshroom)
    {
		return SkinVariations.mooshroomSkinArray[(mooshroom instanceof EntityMooshroomNEP ? ((EntityMooshroomNEP)mooshroom).getVarietySkin() : 0)];
    }
}


code:
package astrotibs.notenoughpets.client.render;

import java.lang.reflect.Method;

import astrotibs.notenoughpets.client.model.ModelOcelotNEP;
import astrotibs.notenoughpets.entity.EntityOcelotNEP;
import astrotibs.notenoughpets.util.SkinVariations;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.entity.RenderLiving;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.entity.passive.EntityOcelot;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.ReflectionHelper;

public class RenderOcelotNEP extends RenderLiving<EntityOcelotNEP>
{
	public RenderOcelotNEP(RenderManager renderManagerIn)
    {
        //super(renderManagerIn, modelBaseIn, shadowSizeIn);
		super(renderManagerIn, new ModelOcelotNEP(), 0.4F);
        this.addLayer(new LayerOcelotCollar(this));
    }

    /**
     * Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture.
     */
	@Override
    protected ResourceLocation getEntityTexture(EntityOcelotNEP ocelot)
    {
    	int tamedIndex = ocelot.isTamed() ? 1 : 0;

    	// First, check for manual overrides!
		if (
				ocelot.getCustomNameTag().equals("Babou") // Archer reference? No! This was SALVADOR DALI'S PET!
				|| ocelot.getCustomNameTag().equals("Murphy Jr.") // I was trying to get the cat in the tub, but... he's crazy. He hates it.
				|| ocelot.getCustomNameTag().equals("Little Murphy") // Don't you need a license to keep endangered species?
				)
		{
			return SkinVariations.catSkinArray[0][tamedIndex];
		}
		else if (ocelot.getCustomNameTag().equals("Newton")) // Late cat belonging to Jeb
		{
			return SkinVariations.catSkinArray[1][tamedIndex];
		}
		else if (ocelot.getCustomNameTag().equals("Jellie")) // Cat belonging to YouTube user GoodTimesWithScar
		{
			return SkinVariations.catSkinArray[9][tamedIndex];
		}
		else if (ocelot.getCustomNameTag().equals("Juno"))
		{
			return SkinVariations.catSkinArray[13][tamedIndex];
		}
		else if (ocelot.getCustomNameTag().equals("Willie"))
		{
			return SkinVariations.catSkinArray[14][tamedIndex];
		}
		else if (ocelot.getCustomNameTag().equals("Lily"))
		{
			return SkinVariations.catSkinArray[15][tamedIndex];
		}
		else if (ocelot.getCustomNameTag().equals("Boo")) // Cat belonging to Asher Applegate
		{
			return SkinVariations.catSkinArray[16][tamedIndex];
		}
		else if (ocelot.getCustomNameTag().equals("Winslow")) // Cassie Rose's cat from Minecraft: Story Mode
		{
			return SkinVariations.catSkinArray[17][tamedIndex];
		}
		else if (ocelot.getCustomNameTag().equals("Blitzkrieg")) // Cat belonging to Shahayhay
		{
			return SkinVariations.catSkinArray[18][tamedIndex];
		}
		else if (ocelot.getCustomNameTag().equals("Princess")) // Cat belonging to Chara Violet
		{
			return SkinVariations.catSkinArray[19][tamedIndex];
		}

		// If there are no manual overrides, refer to the cat's skin int
		return SkinVariations.catSkinArray[Math.max(ocelot.getTameSkin() >= SkinVariations.catSkinArray.length ? 0 : ocelot.getTameSkin(), 0)][tamedIndex];
    }

    /**
     * Allows the render to do state modifications necessary before the model is rendered.
     */
	@Override
    protected void preRenderCallback(EntityOcelotNEP entitylivingbaseIn, float partialTickTime)
    {
        super.preRenderCallback(entitylivingbaseIn, partialTickTime);

        // Ocelots should be slightly larger than regular cats
        if (entitylivingbaseIn.getTameSkin()!=0) {GlStateManager.scale(0.8F, 0.8F, 0.8F);}
    }

	// Scale shadow based on entity size
	@Override
	public void doRenderShadowAndFire(Entity entityIn, double x, double y, double z, float yaw, float partialTicks)
	{
		if (this.renderManager.options != null)
        {
            if (this.renderManager.options.entityShadows && this.shadowSize > 0.0F && !entityIn.isInvisible() && this.renderManager.isRenderShadow())
            {
                double d0 = this.renderManager.getDistanceToCamera(entityIn.posX, entityIn.posY, entityIn.posZ);
                float f = (float)((1.0D - d0 / 256.0D) * (double)this.shadowOpaque);

                if (f > 0.0F)
                {
                    this.renderShadow((EntityOcelotNEP)entityIn, x, y, z, f, partialTicks);
                }
            }
        }

        if (entityIn.canRenderOnFire())
        {
        	Method renderEntityOnFire_reflected = ReflectionHelper.findMethod(Render.class, this, new String[]{"renderEntityOnFire", "func_76977_a"}, Entity.class, Double.TYPE, Double.TYPE, Double.TYPE, Float.TYPE);

        	try
        	{
				renderEntityOnFire_reflected.invoke(this, entityIn, x, y, z, partialTicks);
			}
        	catch (Exception e) {}
        }
	}

    private void renderShadow(EntityOcelotNEP entityIn, double x, double y, double z, float shadowAlpha, float partialTicks)
    {
        GlStateManager.enableBlend();
        GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
        this.renderManager.renderEngine.bindTexture((ResourceLocation)ReflectionHelper.getPrivateValue(Render.class, this, new String[]{"SHADOW_TEXTURES", "field_110778_a"}));
        World world = this.renderManager.worldObj;
        GlStateManager.depthMask(false);
        float f = this.shadowSize;

        f *= entityIn.getRenderSizeModifier();

        // Scale based on breed type and age
        f *= entityIn.isChild() ? 1F-0.5F*(((float)((EntityOcelot)entityIn).getGrowingAge())/-24000) : 1F;

        double d5 = entityIn.lastTickPosX + (entityIn.posX - entityIn.lastTickPosX) * (double)partialTicks;
        double d0 = entityIn.lastTickPosY + (entityIn.posY - entityIn.lastTickPosY) * (double)partialTicks;
        double d1 = entityIn.lastTickPosZ + (entityIn.posZ - entityIn.lastTickPosZ) * (double)partialTicks;
        int i = MathHelper.floor_double(d5 - (double)f);
        int j = MathHelper.floor_double(d5 + (double)f);
        int k = MathHelper.floor_double(d0 - (double)f);
        int l = MathHelper.floor_double(d0);
        int i1 = MathHelper.floor_double(d1 - (double)f);
        int j1 = MathHelper.floor_double(d1 + (double)f);
        double d2 = x - d5;
        double d3 = y - d0;
        double d4 = z - d1;
        Tessellator tessellator = Tessellator.getInstance();
        VertexBuffer bufferbuilder = tessellator.getBuffer();
        bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);

        for (BlockPos blockpos : BlockPos.getAllInBoxMutable(new BlockPos(i, k, i1), new BlockPos(j, l, j1)))
        {
            IBlockState iblockstate = world.getBlockState(blockpos.down());

            if (iblockstate.getRenderType() != EnumBlockRenderType.INVISIBLE && world.getLightFromNeighbors(blockpos) > 3)
            {
                Method renderShadowSingle_reflected = ReflectionHelper.findMethod(Render.class, this, new String[]{"renderShadowSingle", "func_188299_a"}, IBlockState.class, Double.TYPE, Double.TYPE, Double.TYPE, BlockPos.class, Float.TYPE, Float.TYPE, Double.TYPE, Double.TYPE, Double.TYPE);

            	try
            	{
            		renderShadowSingle_reflected.invoke(this, iblockstate, x, y, z, blockpos, shadowAlpha, f, d2, d3, d4);
    			}
            	catch (Exception e) {}
            }
        }

        tessellator.draw();
        GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
        GlStateManager.disableBlend();
        GlStateManager.depthMask(true);
    }
}


code:
package astrotibs.notenoughpets.client.render;

import java.lang.reflect.Method;

import astrotibs.notenoughpets.client.model.ModelParrotNEP;
import astrotibs.notenoughpets.entity.EntityParrotNEP;
import astrotibs.notenoughpets.util.SkinVariations;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.entity.RenderLiving;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

/**
 * Pasted in from 1.12
 */
@SideOnly(Side.CLIENT)
public class RenderParrotNEP extends RenderLiving<EntityParrotNEP>
{
	public RenderParrotNEP(RenderManager rendermanagerIn)
	{
        super(rendermanagerIn, new ModelParrotNEP(0), 0.3F);
	}

    /**
     * Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture.
     */
	@Override
    protected ResourceLocation getEntityTexture(EntityParrotNEP parrot)
    {
		if (parrot.getCustomNameTag().equals("Duster")) // Showbird born in 1925
		{
			return SkinVariations.parrotSkinArray[6];
		}
		else if (parrot.getCustomNameTag().equals("Peaches")) // Erin's lovebird
		{
			return SkinVariations.parrotSkinArray[8];
		}
		else if (parrot.getCustomNameTag().equals("Rex")) // MineKynoMine's rainbow lorikeet
		{
			return SkinVariations.parrotSkinArray[12];
		}

		// If there are no manual overrides, refer to the parrot's skin int
		return SkinVariations.parrotSkinArray[parrot.getVariant() % SkinVariations.parrotSkinArray.length];
    }

    /**
     * Defines what float the third param in setRotationAngles of ModelBase is
     */
    public float handleRotationFloat(EntityParrotNEP livingBase, float partialTicks)
    {
        return this.getCustomBob(livingBase, partialTicks);
    }

    private float getCustomBob(EntityParrotNEP parrot, float partialAnimationTicks)
    {
        float f = parrot.oFlap + (parrot.flap - parrot.oFlap) * partialAnimationTicks;
        float f1 = parrot.oFlapSpeed + (parrot.flapSpeed - parrot.oFlapSpeed) * partialAnimationTicks;
        return (MathHelper.sin(f) + 1.0F) * f1;
    }

	// v2.0.0 - Scale shadow based on entity size
	@Override
	public void doRenderShadowAndFire(Entity entityIn, double x, double y, double z, float yaw, float partialTicks)
	{
		if (this.renderManager.options != null)
        {
            if (this.renderManager.options.entityShadows && this.shadowSize > 0.0F && !entityIn.isInvisible() && this.renderManager.isRenderShadow())
            {
                double d0 = this.renderManager.getDistanceToCamera(entityIn.posX, entityIn.posY, entityIn.posZ);
                float f = (float)((1.0D - d0 / 256.0D) * (double)this.shadowOpaque);

                if (f > 0.0F)
                {
                    this.renderShadow((EntityParrotNEP)entityIn, x, y, z, f, partialTicks);
                }
            }
        }

        if (entityIn.canRenderOnFire())
        {
        	Method renderEntityOnFire_reflected = ReflectionHelper.findMethod(Render.class, this, new String[]{"renderEntityOnFire", "func_76977_a"}, Entity.class, Double.TYPE, Double.TYPE, Double.TYPE, Float.TYPE);

        	try
        	{
				renderEntityOnFire_reflected.invoke(this, entityIn, x, y, z, partialTicks);
			}
        	catch (Exception e) {}
        }
	}

    private void renderShadow(EntityParrotNEP entityIn, double x, double y, double z, float shadowAlpha, float partialTicks)
    {
        GlStateManager.enableBlend();
        GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
        this.renderManager.renderEngine.bindTexture((ResourceLocation)ReflectionHelper.getPrivateValue(Render.class, this, new String[]{"SHADOW_TEXTURES", "field_110778_a"}));
        World world = this.renderManager.worldObj;
        GlStateManager.depthMask(false);
        float f = this.shadowSize;

        f *= entityIn.getRenderSizeModifier();

        // Scale based on breed type and age
        f *= entityIn.isChild() ? 1F-0.5F*(((float)((EntityParrotNEP)entityIn).getGrowingAge())/-24000) : 1F;

        double d5 = entityIn.lastTickPosX + (entityIn.posX - entityIn.lastTickPosX) * (double)partialTicks;
        double d0 = entityIn.lastTickPosY + (entityIn.posY - entityIn.lastTickPosY) * (double)partialTicks;
        double d1 = entityIn.lastTickPosZ + (entityIn.posZ - entityIn.lastTickPosZ) * (double)partialTicks;
        int i = MathHelper.floor_double(d5 - (double)f);
        int j = MathHelper.floor_double(d5 + (double)f);
        int k = MathHelper.floor_double(d0 - (double)f);
        int l = MathHelper.floor_double(d0);
        int i1 = MathHelper.floor_double(d1 - (double)f);
        int j1 = MathHelper.floor_double(d1 + (double)f);
        double d2 = x - d5;
        double d3 = y - d0;
        double d4 = z - d1;
        Tessellator tessellator = Tessellator.getInstance();
        VertexBuffer bufferbuilder = tessellator.getBuffer();
        bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);

        for (BlockPos blockpos : BlockPos.getAllInBoxMutable(new BlockPos(i, k, i1), new BlockPos(j, l, j1)))
        {
            IBlockState iblockstate = world.getBlockState(blockpos.down());

            if (iblockstate.getRenderType() != EnumBlockRenderType.INVISIBLE && world.getLightFromNeighbors(blockpos) > 3)
            {
                Method renderShadowSingle_reflected = ReflectionHelper.findMethod(Render.class, this, new String[]{"renderShadowSingle", "func_188299_a"}, IBlockState.class, Double.TYPE, Double.TYPE, Double.TYPE, BlockPos.class, Float.TYPE, Float.TYPE, Double.TYPE, Double.TYPE, Double.TYPE);

            	try
            	{
            		renderShadowSingle_reflected.invoke(this, iblockstate, x, y, z, blockpos, shadowAlpha, f, d2, d3, d4);
    			}
            	catch (Exception e) {}
            }
        }

        tessellator.draw();
        GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
        GlStateManager.disableBlend();
        GlStateManager.depthMask(true);
    }
}


code:
package astrotibs.notenoughpets.client.render;

import java.lang.reflect.Method;

import astrotibs.notenoughpets.client.model.ModelWolfNEP;
import astrotibs.notenoughpets.entity.EntityWolfNEP;
import astrotibs.notenoughpets.util.SkinVariations;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.entity.RenderLiving;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.entity.passive.EntityWolf;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.ReflectionHelper;

public class RenderWolfNEP extends RenderLiving<EntityWolfNEP>
{

	public RenderWolfNEP(RenderManager renderManagerIn)
    {
		super(renderManagerIn, new ModelWolfNEP(), 0.5F);
		this.addLayer(new LayerWolfCollarNEP(this));
	}

	// summon notenoughcats.Wolf_NEC ~ ~ ~ {Owner:AstroTibs, DogType:0}
	// summon notenoughcats.Wolf_NEC ~ ~ ~ {Owner:AstroTibs, DogType:1, Age:-24000}
	// summon notenoughcats.Wolf_NEC ~ ~ ~ {DogType:2}

    @Override
	protected ResourceLocation getEntityTexture(EntityWolfNEP wolf)
    {
    	int wolfSkinIndex = 0; // Default to 0 in the event of the vanilla wolf

    	if (wolf instanceof EntityWolfNEP)
    	{
    		// First, check for manual overrides!
    		if (wolf.getCustomNameTag().equals("Wink")) // Stacy Plays's dog from Minecraft: Story Mode, referencing YouTuber Stacy Hinojosa
    		{
    			wolfSkinIndex = 0;
    		}
    		else if (wolf.getCustomNameTag().equals("Blocco")) // From Minecraft: Story Mode Season Two. Named after Juan Vaca's dog, Rocco
    		{
    			wolfSkinIndex = 1;
    		}
    		else if (wolf.getCustomNameTag().equals("Rexbutt")) // A good boi
    		{
    			wolfSkinIndex = 4;
    		}
    		else if (wolf.getCustomNameTag().equals("Doge"))
    		{
    			wolfSkinIndex = 5;
    		}
    		else if (wolf.getCustomNameTag().equals("Mojo")) // Brandt's dog
    		{
    			wolfSkinIndex = 6;
    		}
    		else if (wolf.getCustomNameTag().equals("Buddha")) // Count Dankula's infamous little gremlin
    		{
    			wolfSkinIndex = 7;
    		}
    		else if (wolf.getCustomNameTag().equals("Angelo")) // Rinoa's dog in Final Fantasy 8
    		{
    			wolfSkinIndex = 8;
    		}
    		else
    		{
    			// If there are no manual overrides, refer to the dog's skin int
        		wolfSkinIndex = ((EntityWolfNEP)wolf).getTameSkin();
        		wolfSkinIndex = Math.max(wolfSkinIndex >= SkinVariations.dogSkinArray.length ? 0 : wolfSkinIndex, 0);
    		}
    	}

    	// 0:Normal, 1:Angry, 2:Tame
        return SkinVariations.dogSkinArray[wolfSkinIndex][wolf.isTamed() ? 2 : (wolf.isAngry() ? 1 : 0)];
    }

    /**
     * Defines what float the third param in setRotationAngles of ModelBase is
     * Added to account for the new dogs
     */
    @Override
    protected float handleRotationFloat(EntityWolfNEP livingBase, float partialTicks)
    {
        return livingBase.getTailRotation();
    }

    /**
     * Allows the render to do state modifications necessary before the model is rendered.
     */
	// Scale dog based on breed
	@Override
    protected void preRenderCallback(EntityWolfNEP entitylivingbaseIn, float partialTickTime)
    {
        super.preRenderCallback(entitylivingbaseIn, partialTickTime);

        float dogBreedScale = EntityWolfNEP.dogBreedScale(entitylivingbaseIn);

        GlStateManager.scale(dogBreedScale, dogBreedScale, dogBreedScale);
    }

	// Scale shadow based on entity size
	@Override
	public void doRenderShadowAndFire(Entity entityIn, double x, double y, double z, float yaw, float partialTicks)
	{
		if (this.renderManager.options != null)
        {
            if (this.renderManager.options.entityShadows && this.shadowSize > 0.0F && !entityIn.isInvisible() && this.renderManager.isRenderShadow())
            {
                double d0 = this.renderManager.getDistanceToCamera(entityIn.posX, entityIn.posY, entityIn.posZ);
                float f = (float)((1.0D - d0 / 256.0D) * (double)this.shadowOpaque);

                if (f > 0.0F)
                {
                    this.renderShadow((EntityWolfNEP)entityIn, x, y, z, f, partialTicks);
                }
            }
        }

        if (entityIn.canRenderOnFire())
        {
        	Method renderEntityOnFire_reflected = ReflectionHelper.findMethod(Render.class, this, new String[]{"renderEntityOnFire", "func_76977_a"}, Entity.class, Double.TYPE, Double.TYPE, Double.TYPE, Float.TYPE);

        	try
        	{
				renderEntityOnFire_reflected.invoke(this, entityIn, x, y, z, partialTicks);
			}
        	catch (Exception e) {}
        }
	}

    private void renderShadow(EntityWolfNEP entityIn, double x, double y, double z, float shadowAlpha, float partialTicks)
    {
        GlStateManager.enableBlend();
        GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
        this.renderManager.renderEngine.bindTexture((ResourceLocation)ReflectionHelper.getPrivateValue(Render.class, this, new String[]{"SHADOW_TEXTURES", "field_110778_a"}));
        World world = this.renderManager.worldObj;
        GlStateManager.depthMask(false);
        float f = this.shadowSize;

        f *= entityIn.getRenderSizeModifier();

        // Scale based on breed type and age
        f *= EntityWolfNEP.dogBreedScale(entityIn);
        f *= entityIn.isChild() ? 1F-0.5F*(((float)((EntityWolf)entityIn).getGrowingAge())/-24000) : 1F;

        double d5 = entityIn.lastTickPosX + (entityIn.posX - entityIn.lastTickPosX) * (double)partialTicks;
        double d0 = entityIn.lastTickPosY + (entityIn.posY - entityIn.lastTickPosY) * (double)partialTicks;
        double d1 = entityIn.lastTickPosZ + (entityIn.posZ - entityIn.lastTickPosZ) * (double)partialTicks;
        int i = MathHelper.floor_double(d5 - (double)f);
        int j = MathHelper.floor_double(d5 + (double)f);
        int k = MathHelper.floor_double(d0 - (double)f);
        int l = MathHelper.floor_double(d0);
        int i1 = MathHelper.floor_double(d1 - (double)f);
        int j1 = MathHelper.floor_double(d1 + (double)f);
        double d2 = x - d5;
        double d3 = y - d0;
        double d4 = z - d1;
        Tessellator tessellator = Tessellator.getInstance();
        VertexBuffer bufferbuilder = tessellator.getBuffer();
        bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);

        for (BlockPos blockpos : BlockPos.getAllInBoxMutable(new BlockPos(i, k, i1), new BlockPos(j, l, j1)))
        {
            IBlockState iblockstate = world.getBlockState(blockpos.down());

            if (iblockstate.getRenderType() != EnumBlockRenderType.INVISIBLE && world.getLightFromNeighbors(blockpos) > 3)
            {
                Method renderShadowSingle_reflected = ReflectionHelper.findMethod(Render.class, this, new String[]{"renderShadowSingle", "func_188299_a"}, IBlockState.class, Double.TYPE, Double.TYPE, Double.TYPE, BlockPos.class, Float.TYPE, Float.TYPE, Double.TYPE, Double.TYPE, Double.TYPE);

            	try
            	{
            		renderShadowSingle_reflected.invoke(this, iblockstate, x, y, z, blockpos, shadowAlpha, f, d2, d3, d4);
    			}
            	catch (Exception e) {}
            }
        }

        tessellator.draw();
        GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
        GlStateManager.disableBlend();
        GlStateManager.depthMask(true);
    }
}


code:
package astrotibs.notenoughpets.client.render.layers;

import java.util.Map;
import java.util.UUID;
import java.util.WeakHashMap;

import javax.annotation.Nullable;

import astrotibs.notenoughpets.capabilities.shoulderriding.IShoulderRiding;
import astrotibs.notenoughpets.capabilities.shoulderriding.ShoulderRidingProvider;
import astrotibs.notenoughpets.client.model.ModelParrotNEP;
import astrotibs.notenoughpets.client.render.RenderParrotNEP;
import astrotibs.notenoughpets.entity.EntityParrotNEP;
import astrotibs.notenoughpets.util.SkinVariations;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.RenderLivingBase;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.entity.layers.LayerRenderer;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.RenderPlayerEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

@SideOnly(Side.CLIENT)
public class LayerEntityOnShoulder implements LayerRenderer<EntityPlayer>
{
    private final RenderManager renderManager;
    protected RenderLivingBase <? extends EntityLivingBase > leftRenderer;
    private ModelBase leftModel;
    private ResourceLocation leftResource;
    private UUID leftUniqueId;
    private Class<?> leftEntityClass;
    protected RenderLivingBase <? extends EntityLivingBase > rightRenderer;
    private ModelBase rightModel;
    private ResourceLocation rightResource;
    private UUID rightUniqueId;
    private Class<?> rightEntityClass;

    public LayerEntityOnShoulder(RenderManager renderManager)
    {
        this.renderManager = renderManager;
    }

    // Added on a whim based on EnderIO
    // https://github.com/SleepyTrousers/EnderIO/blob/release/1.11.2/enderio-base/src/main/java/crazypants/enderio/base/handler/darksteel/UpgradeRenderManager.java
	// no WeakHashSet in Java...
	private static final Map<RenderManager, Object> injected = new WeakHashMap<RenderManager, Object>();

	@SideOnly(Side.CLIENT)
	@SubscribeEvent
	public void onPlayerRenderPre(RenderPlayerEvent.Pre event)
	{
		final RenderManager renderManager = event.getRenderer().getRenderManager();

		if (renderManager != null && !injected.containsKey(renderManager))
		{
			//LogHelper.info("Render layer injected into render manager "+ event.getRenderer().getRenderManager());
			event.getRenderer().addLayer(new LayerEntityOnShoulder(renderManager));
			injected.put(renderManager, null);
		}
	}

	// summon notenoughcats:parrot_nec ~ ~ ~ {Owner:AstroTibs, Age:-24000}
	// summon notenoughcats:parrot_nec ~ ~ ~ {Owner:AstroTibs, Variant:4}

    @Override
    public void doRenderLayer(EntityPlayer entitylivingbaseIn, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, float scale)
    {
    	IShoulderRiding isr = entitylivingbaseIn.getCapability(ShoulderRidingProvider.SHOULDER_RIDING, null);

        {
            GlStateManager.enableRescaleNormal();
            GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);

            // Render the parrot on the left shoulder
            int leftShoulderVariant = isr.getLeftShoulderVariant();
            if (leftShoulderVariant != 0)
            {
            	LayerEntityOnShoulder.DataHolder layerentityonshoulder$dataholder = this.renderEntityOnShoulder(
            			entitylivingbaseIn, this.leftUniqueId,
            			leftShoulderVariant, isr.getLeftShoulderAge(), this.leftRenderer, this.leftModel, this.leftResource, this.leftEntityClass,
            			limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, scale, true);

                this.leftUniqueId = layerentityonshoulder$dataholder.entityId;
                this.leftRenderer = layerentityonshoulder$dataholder.renderer;
                this.leftResource = layerentityonshoulder$dataholder.textureLocation;
                this.leftModel = layerentityonshoulder$dataholder.model;
                this.leftEntityClass = layerentityonshoulder$dataholder.clazz;
            }

            // Render the parrot on the right shoulder
            int rightShoulderVariant = isr.getRightShoulderVariant();
            if (rightShoulderVariant != 0)
            {
                LayerEntityOnShoulder.DataHolder layerentityonshoulder$dataholder1 = this.renderEntityOnShoulder(
                		entitylivingbaseIn, this.rightUniqueId,
                		rightShoulderVariant, isr.getRightShoulderAge(), this.rightRenderer, this.rightModel, this.rightResource, this.rightEntityClass,
                		limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, scale, false);

                this.rightUniqueId = layerentityonshoulder$dataholder1.entityId;
                this.rightRenderer = layerentityonshoulder$dataholder1.renderer;
                this.rightResource = layerentityonshoulder$dataholder1.textureLocation;
                this.rightModel = layerentityonshoulder$dataholder1.model;
                this.rightEntityClass = layerentityonshoulder$dataholder1.clazz;
            }

            GlStateManager.disableRescaleNormal();
        }
    }

    private LayerEntityOnShoulder.DataHolder renderEntityOnShoulder(EntityPlayer entitylivingbaseIn, @Nullable UUID parrotUUID, int variant, int age,//NBTTagCompound parrotTagCompound,
    		RenderLivingBase <? extends EntityLivingBase > renderlivingbase, ModelBase modelbase, ResourceLocation resourceloc, Class<?> entityClazz,
    		float limbSwing, float limbSwingAmount, float partialTickTime, float ageInTicks, float netHeadYaw, float headPitch, float scaleFactor, boolean onLeftShoulder)
    {
    	renderlivingbase = new RenderParrotNEP(this.renderManager);
        modelbase = new ModelParrotNEP(age);
        resourceloc = SkinVariations.parrotSkinArray[variant == -1 ? 0 : variant];
        entityClazz = EntityParrotNEP.class;

        renderlivingbase.bindTexture(resourceloc);
        GlStateManager.pushMatrix();
        float f = entitylivingbaseIn.isSneaking() ? -1.3F : -1.5F;
        float f1 = onLeftShoulder ? 0.4F : -0.4F;
        GlStateManager.translate(f1, f, 0.0F);

        if (entityClazz == EntityParrotNEP.class)
        {
            ageInTicks = 0.0F;
        }

        modelbase.setLivingAnimations(entitylivingbaseIn, limbSwing, limbSwingAmount, partialTickTime);
        modelbase.setRotationAngles(limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scaleFactor, entitylivingbaseIn);
        modelbase.render(entitylivingbaseIn, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scaleFactor);
        GlStateManager.popMatrix();
        return new LayerEntityOnShoulder.DataHolder(parrotUUID, renderlivingbase, modelbase, resourceloc, entityClazz);
    }

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

    @SideOnly(Side.CLIENT)
    class DataHolder
    {
        public UUID entityId;
        public RenderLivingBase <? extends EntityLivingBase > renderer;
        public ModelBase model;
        public ResourceLocation textureLocation;
        public Class<?> clazz;

        public DataHolder(UUID parrotUUID, RenderLivingBase <? extends EntityLivingBase > renderlivingbase, ModelBase modelbase, ResourceLocation resourceloc, Class<?> entityClazz)
        {
            this.entityId = parrotUUID;
            this.renderer = renderlivingbase;
            this.model = modelbase;
            this.textureLocation = resourceloc;
            this.clazz = entityClazz;
        }
    }
}


code:
package astrotibs.notenoughpets.config;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import astrotibs.notenoughpets.util.Reference;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class GeneralConfig
{
	public static final String CAT_GENERAL = "general";
	public static final String CAT_MISC = "miscellaneous";
	public static final String CAT_EMERGENCY_UNDO = "emergency undo";
	public static final String CAT_ENABLE_NEC_ANIMALS = "enable nec animals";
	public static final String CAT_PARROT_IMITATION = "parrot imitation";

	public static Configuration config;

	public static int soundOccurrenceCat;
	public static int soundOccurrenceDog;
	public static int soundOccurrenceParrotAmbient;
	public static int soundOccurrenceParrotImitate;

	public static int villageSpawnCapCat;
	public static int villageSpawnCapDog;
	public static boolean strayCapFromVillageRadius;

	public static boolean versionChecker;
	public static boolean debugMessages;
	public static boolean swampHutCat;
	public static boolean swampHutCatName;

	public static int spawnLimitOcelot;
	public static int spawnLimitWolf;
	public static int spawnLimitMooshroom;
	public static int spawnLimitParrot;

	public static int villageSpawnRatePercent;

	public static float strayFractionCat;

	public static int[] strayDimensions;

	public static float dogFeedingItemsDefaultAmount;
	public static String[] dogFeedingItems;
	public static List<String> dogBreedingItem_a = new ArrayList<String>();
	public static float catFeedingItemsDefaultAmount;
	public static String[] catFeedingItems;
	public static List<String> catBreedingItem_a = new ArrayList<String>();
	public static float parrotFeedingItemsDefaultAmount;
	public static String[] parrotFeedingItems;
	public static List<String> parrotBreedingItem_a = new ArrayList<String>();

	public static String[] parrotMimicSounds;

	public static boolean followOwnerCat;
	public static boolean followOwnerDog;
	public static boolean followOwnerParrot;

	public static float followTeleportCat;
	public static float followTeleportDog;
	public static float followTeleportParrot;

	public static boolean healingFoodCat;
	public static boolean healingFoodParrot;
	public static boolean cookiesKillParrots;
	public static float parrotDismountFallHeight;

	public static boolean revertAnimalTypes;

	public static boolean enableNECCats;
	public static boolean enableNECDogs;
	public static boolean enableNECMooshrooms;
	public static boolean enableNEPParrots;
	public static boolean untamedOcelotsRemainVanilla;
	public static boolean untamedWolvesRemainVanilla;
	public static boolean tamedWolvesRemainVanilla;
	public static boolean enableParrotMimicry;

	public static void init(File configFile) {
		if (config == null) {
			config = new Configuration(configFile);
			loadConfiguration();
		}
	}

	// Config file explanations
	public static void loadConfiguration() {

		// ---------------------------- //
		// --------- General ---------- //
		// ---------------------------- //

		soundOccurrenceCat = config.getInt("Idle Sound Occurrence: Cat", CAT_GENERAL, 25, 0, 100, "Determines the frequency of occurrence of the idle sounds that a tamed cat makes as a percentage of typical Minecraft mob sound frequency. "
				+ "Set this to 50 for 50 percent, etc.");

		soundOccurrenceDog = config.getInt("Idle Sound Occurrence: Dog", CAT_GENERAL, 50, 0, 100, "Determines the frequency of occurrence of the idle sounds that a tamed dog makes as a percentage of typical Minecraft mob sound frequency. "
				+ "Set this to 50 for 50 percent, etc.");

		soundOccurrenceParrotAmbient = config.getInt("Idle Sound Occurrence: Parrot (Ambient)", CAT_GENERAL, 100, 0, 100, "Determines the frequency of occurrence of the idle sounds that a tamed parrot makes as a percentage of typical Minecraft mob sound frequency. "
				+ "Set this to 50 for 50 percent, etc.");
		soundOccurrenceParrotImitate = config.getInt("Idle Sound Occurrence: Parrot (Imitate)", CAT_GENERAL, 100, 0, 100, "The frequency that a parrot makes a sound imitating another mob as a percentage of a typical Minecraft parrot. "
				+ "Set this to 50 for 50 percent, etc.");

		villageSpawnCapCat = config.getInt("Village spawn cap: Cat", CAT_GENERAL, 10, 0, 100, "Maximum number of stray cats that can spawn in a village depends on the village's size, but will never be bigger than this value."); // Config value and name changed in v1.3.0
		villageSpawnCapDog = config.getInt("Village spawn cap: Dog", CAT_GENERAL, 10, 0, 100, "Maximum number of stray dogs that can spawn in a village depends on the village's size, but will never be bigger than this value.");
		strayCapFromVillageRadius = config.getBoolean("Use Village Radius To Limit Strays", CAT_GENERAL, false, "Use a cruder determination of the size of a village for the purpose of limiting the number of strays that can spawn. Set to true if you're using a mod that replaces vanilla villagers, or otherwise notice that strays never spawn.");
		villageSpawnRatePercent = config.getInt("Village spawn rate percent", CAT_GENERAL, 50, 0, 100, "Villages will check their stray animal populations against their limits every 1.5 seconds and, if there's room, will attempt to spawn a new stray this percent of the time.");
		strayFractionCat = config.getFloat("Village spawn cat fraction", CAT_GENERAL, 0.75F, 0.0F, 1.0F, "This fraction of village strays are cats. The rest are dogs.");

		followOwnerCat = config.getBoolean("Follow owner: Cat", CAT_GENERAL, true, "If false, tamed cats will never follow or teleport to their owners.");
		followOwnerDog = config.getBoolean("Follow owner: Dog", CAT_GENERAL, true, "If false, tamed dogs will never follow or teleport to their owners.");
		followOwnerParrot = config.getBoolean("Follow owner: Parrot", CAT_GENERAL, true, "If false, tamed parrots will never follow or teleport to their owners.");

		// Changed minimum values to 0.0F in order to allow teleport disabling -- v2.1.0
		followTeleportCat = config.getFloat("Follow teleport: Cat", CAT_GENERAL, 12.0F, 0.0F, 256.0F, "If not sitting or leashed, your tamed ocelot/cat will teleport to you when you're farther than this distance away. Set this to 0 to disable teleporting entirely.");
		followTeleportDog = config.getFloat("Follow teleport: Dog", CAT_GENERAL, 12.0F, 0.0F, 256.0F, "Same as the above setting, but for tamed wolves/dogs.");
		followTeleportParrot = config.getFloat("Follow teleport: Parrot", CAT_GENERAL, 12.0F, 0.0F, 256.0F, "Same as the above setting, but for tamed parrots.");

		healingFoodCat = config.getBoolean("Healing Food: Cat", CAT_GENERAL, true, "Using the taming food on a tamed cat will heal it.");
		healingFoodParrot = config.getBoolean("Healing Food: Parrot", CAT_GENERAL, true, "Using the taming food on a tamed parrot will heal it.");

		cookiesKillParrots = config.getBoolean("Cool Story, Theobromine", CAT_GENERAL, true, "If false, parrots are only poisoned when fed a cookie, but not killed.");
		parrotDismountFallHeight = config.getFloat("Parrot Dismount Fall Height", CAT_GENERAL, 1.1F, 0.0F, 512.0F, "Shoulder-perching parrots dismount when you fall at least this far. Vanilla is 0.5.");

		swampHutCat = config.getBoolean("Swamp Hut Cats", CAT_GENERAL, true, "Swamp huts often contain a black cat.");
		swampHutCatName = config.getBoolean("Swamp Hut Cat Name", CAT_GENERAL, true, "Black cats found in swamp huts spawn with a name.");

		spawnLimitOcelot = config.getInt("Area Spawn Limit: Ocelot", CAT_GENERAL, -1, -1, 10000, "If a 256-by-256 zone around a spawning ocelot has this many ocelots, the spawn is canceled. Set to -1 for no limit.");
		spawnLimitWolf = config.getInt("Area Spawn Limit: Wolf", CAT_GENERAL, -1, -1, 10000, "If a 256-by-256 zone around a spawning wolf has this many wolves, the spawn is canceled. Set to -1 for no limit.");
		spawnLimitMooshroom = config.getInt("Area Spawn Limit: Mooshroom", CAT_GENERAL, -1, -1, 10000, "If a 256-by-256 zone around a spawning mooshroom has this many mooshrooms, the spawn is canceled. Set to -1 for no limit.");
		spawnLimitParrot = config.getInt("Area Spawn Limit: Parrot", CAT_GENERAL, -1, -1, 10000, "If a 256-by-256 zone around a spawning parrot has this many parrots, the spawn is canceled. Set to -1 for no limit.");

		strayDimensions = config.get(CAT_GENERAL, "Stray Dimensions", new int[]{0}, "Strays can appear in villages within these dimension IDs (0 is Overworld, -1 is Nether, 1 is The End, etc).").getIntList();

		dogFeedingItemsDefaultAmount = config.getFloat("Feeding Items: Dog - Default Amount", CAT_GENERAL, 3.0F, 0.0F, Float.MAX_VALUE, "The amount to heal dogs/wolves when fed an item from \"Feeding Items: Dog\" that is not a food item");
		dogFeedingItems = config.getStringList("Feeding Items: Dog", CAT_GENERAL, new String[]{
		        "minecraft:porkchop",
		        "minecraft:cooked_porkchop",
		        "minecraft:beef",
		        "minecraft:cooked_beef",
		        "minecraft:chicken",
		        "minecraft:cooked_chicken",
		        "minecraft:rabbit",
		        "minecraft:cooked_rabbit",
		        "minecraft:mutton",
		        "minecraft:cooked_mutton",
		        "ore:listAllmeatraw",
		        "ore:listAllmeatcooked",
	    		},
	    		"Item that is used to heal and breed dogs and wolves. Can be of the form mod:thing, mod:thing:meta, or ore:oredict");
		dogBreedingItem_a.clear();
		for (int i=0; i<dogFeedingItems.length; i++) {dogBreedingItem_a.add(dogFeedingItems[i]);}

		catFeedingItemsDefaultAmount = config.getFloat("Feeding Items: Cat - Default Amount", CAT_GENERAL, 2.0F, 0.0F, Float.MAX_VALUE, "The amount to heal cats/ocelots when fed an item from \"Feeding Items: Cat\" that is not a food item");
		catFeedingItems = config.getStringList("Feeding Items: Cat", CAT_GENERAL, new String[]{
				"minecraft:fish:0",
				"minecraft:fish:1",
		        "minecraft:chicken",
		        "minecraft:rabbit",
		        "minecraft:cooked_rabbit",
				"ore:listAllfishraw",
	    		},
	    		"Item that is used to tame, heal, and breed cats and ocelots. Can be of the form mod:thing, mod:thing:meta, or ore:oredict");
		catBreedingItem_a.clear();
		for (int i=0; i<catFeedingItems.length; i++) {catBreedingItem_a.add(catFeedingItems[i]);}

		parrotFeedingItemsDefaultAmount = config.getFloat("Feeding Items: Parrot - Default Amount", CAT_GENERAL, 1.0F, 0.0F, Float.MAX_VALUE, "The amount to heal parrots when fed an item from \"Feeding Items: Parrot\" that is not a food item");
		parrotFeedingItems = config.getStringList("Feeding Items: Parrot", CAT_GENERAL, new String[]{
				"minecraft:wheat_seeds",
				"minecraft:pumpkin_seeds",
				"minecraft:melon_seeds",
				"minecraft:beetroot_seeds",
				"ore:listAllseed",
	    		},
	    		"Item that is used to tame, heal, and breed parrots. Can be of the form mod:thing, mod:thing:meta, or ore:oredict");
		parrotBreedingItem_a.clear();
		for (int i=0; i<parrotFeedingItems.length; i++) {parrotBreedingItem_a.add(parrotFeedingItems[i]);}

		// ---------------------------- //
		// ------ Miscellaneous ------- //
		// ---------------------------- //

		versionChecker = config.getBoolean("Version Checker", CAT_MISC, true, "Displays a client-side chat message on login if there's an update available.");
		debugMessages = config.getBoolean("Debug Messages", CAT_MISC, false, "Print extra debug messages to the console.");

		// -------------------------- //
		// --- Enable NEC animals --- //
		// -------------------------- //

		enableNECCats = config.getBoolean("Enable NEC version: Cat", CAT_ENABLE_NEC_ANIMALS, true, "If false, ocelots/cats will revert to their vanilla counterparts, removing many NEC features. Do this if you experience inter-mod compatibility issues.");
		enableNECDogs = config.getBoolean("Enable NEC version: Dog", CAT_ENABLE_NEC_ANIMALS, true, "If false, wolves/dogs will revert to their vanilla counterparts, removing many NEC features. Do this if you experience inter-mod compatibility issues.");
		enableNECMooshrooms = config.getBoolean("Enable NEC version: Mooshroom", CAT_ENABLE_NEC_ANIMALS, true, "If false, mooshrooms will revert to their vanilla counterparts, removing many NEC features. Do this if you experience inter-mod compatibility issues.");
		enableNEPParrots = config.getBoolean("Enable NEP version: Parrot", CAT_ENABLE_NEC_ANIMALS, true, "Parrots will spawn in jungles, like in 1.12");
		untamedOcelotsRemainVanilla = config.getBoolean("Untamed Ocelots Remain Vanilla", CAT_ENABLE_NEC_ANIMALS, false, "If true, wild-spawning ocelots (skin type 0) will remain vanilla until tamed");
		untamedWolvesRemainVanilla = config.getBoolean("Untamed Wolves Remain Vanilla", CAT_ENABLE_NEC_ANIMALS, false, "If true, wild-spawning wolves (skin type 0) will remain vanilla until tamed");
		tamedWolvesRemainVanilla = config.getBoolean("Tamed Wolves Remain Vanilla", CAT_ENABLE_NEC_ANIMALS, false, "If true, wild-spawning wolves (skin type 0) remain or become vanilla when tamed");

		// ---------------------------- //
		// --------- EMERGENCY -------- //
		// ---------------------------- //

		revertAnimalTypes = config.getBoolean("Revert NEC Animals", CAT_EMERGENCY_UNDO, false, Reference.MOD_NAME+" animals are different from vanilla Minecraft, so that they can obey things like new skin types and \"follow teleport range\" values. "
				+ "If you wish to remove "+ Reference.MOD_NAME+", set this to true, load your game, and then visit each such animal you wish to retain (so that it loads into the server memory). "
				+ "They will be reverted back to vanilla types. If you don't do this, they will vanish from your world when you remove " + Reference.MOD_NAME);

		// ------------------------ //
		// --- PARROT IMITATION --- //
		// ------------------------ //

		enableParrotMimicry = config.getBoolean("Enable Parrot Mimicry", CAT_PARROT_IMITATION, true, "If false, NEP parrots will not make mimic sounds. Do this if you experience issues.");

		parrotMimicSounds = config.getStringList("Parrot Mimic Sounds", CAT_PARROT_IMITATION, new String[] {
				"net.minecraft.entity.monster.EntityBlaze|"+Reference.MOD_ID+":entity.parrot.imitate.blaze|1.8",
				"net.minecraft.entity.monster.EntityCaveSpider|"+Reference.MOD_ID+":entity.parrot.imitate.spider|1.8",
				"net.minecraft.entity.monster.EntityCreeper|"+Reference.MOD_ID+":entity.parrot.imitate.creeper|1.8",
				//"net.minecraft.entity.monster.EntityElderGuardian|"+Reference.MOD_ID+":entity.parrot.imitate.elder_guardian|1.8", // Introduced in 1.11
				"net.minecraft.entity.boss.EntityDragon|"+Reference.MOD_ID+":entity.parrot.imitate.enderdragon|1.8",
				"net.minecraft.entity.monster.EntityEnderman|"+Reference.MOD_ID+":entity.parrot.imitate.enderman|1.7",
				"net.minecraft.entity.monster.EntityEndermite|"+Reference.MOD_ID+":entity.parrot.imitate.endermite|1.8",
				//"net.minecraft.entity.monster.EntityEvoker|"+Reference.MOD_ID+":entity.parrot.imitate.evocation_illager|1.8", // Introduced in 1.11
				"net.minecraft.entity.monster.EntityGhast|"+Reference.MOD_ID+":entity.parrot.imitate.ghast|1.8",
				//"net.minecraft.entity.monster.EntityHusk|"+Reference.MOD_ID+":entity.parrot.imitate.husk|1.8", // Introduced in 1.11
				//"net.minecraft.entity.monster.EntityIllusionIllager|"+Reference.MOD_ID+":entity.parrot.imitate.illusion_illager|1.8", // Introduced in 1.12
				"net.minecraft.entity.monster.EntityMagmaCube|"+Reference.MOD_ID+":entity.parrot.imitate.magmacube|1.8",
				"net.minecraft.entity.monster.EntityPigZombie|"+Reference.MOD_ID+":entity.parrot.imitate.zombie_pigman|1.8",
				//"net.minecraft.entity.monster.EntityPolarBear|"+Reference.MOD_ID+":entity.parrot.imitate.polar_bear|0.7", // Introduced in 1.10
				"net.minecraft.entity.monster.EntityShulker|"+Reference.MOD_ID+":entity.parrot.imitate.shulker|1.7",
				"net.minecraft.entity.monster.EntitySilverfish|"+Reference.MOD_ID+":entity.parrot.imitate.silverfish|1.8",
				"net.minecraft.entity.monster.EntitySkeleton|"+Reference.MOD_ID+":entity.parrot.imitate.skeleton|1.7",
				"net.minecraft.entity.monster.EntitySlime|"+Reference.MOD_ID+":entity.parrot.imitate.slime|1.8",
				"net.minecraft.entity.monster.EntitySpider|"+Reference.MOD_ID+":entity.parrot.imitate.spider|1.8",
				//"net.minecraft.entity.monster.EntityStray|"+Reference.MOD_ID+":entity.parrot.imitate.stray|1.6", // Introduced in 1.11
				//"net.minecraft.entity.monster.EntityVex|"+Reference.MOD_ID+":entity.parrot.imitate.vex|1.6", // Introduced in 1.11
				//"net.minecraft.entity.monster.EntityVindicator|"+Reference.MOD_ID+":entity.parrot.imitate.vindication_illager|1.7", // Introduced in 1.11
				"net.minecraft.entity.monster.EntityWitch|"+Reference.MOD_ID+":entity.parrot.imitate.witch|1.8",
				"net.minecraft.entity.boss.EntityWither|"+Reference.MOD_ID+":entity.parrot.imitate.wither|1.8",
				//"net.minecraft.entity.monster.EntityWitherSkeleton|"+Reference.MOD_ID+":entity.parrot.imitate.wither_skeleton|1.8", // Introduced in 1.11
				//"net.minecraft.entity.passive.EntityWolf|"+Reference.MOD_ID+":entity.parrot.imitate.wolf|1.8",
				"net.minecraft.entity.monster.EntityZombie|"+Reference.MOD_ID+":entity.parrot.imitate.zombie|1.8",
				//"net.minecraft.entity.monster.EntityZombieVillager|"+Reference.MOD_ID+":entity.parrot.imitate.zombie_villager|1.8", // Introduced in 1.11
	    		},
	    		"List of entities for parrots to mimic. Format is: classPath|soundPath|pitch\n"+
	    				"classPath: The address to the entity class.\n"
	    				+ "soundPath: the sound address, typically in the sounds.json file.\n"
	    				+ "pitch: the average pitch/speed factor, between 0.4 and 2.0, at which this mimicked sound will be played, where 1.0 is unshifted.");

		if (config.hasChanged()) config.save();
	}

	@SubscribeEvent
	public void onConfigurationChangedEvent(ConfigChangedEvent.OnConfigChangedEvent event) {
		if (event.getModID().equalsIgnoreCase(Reference.MOD_ID)) {
			this.loadConfiguration();
		}
	}

}


code:
package astrotibs.notenoughpets.config;

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

import astrotibs.notenoughpets.ModNotEnoughPets;
import astrotibs.notenoughpets.util.Reference;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.ConfigCategory;
import net.minecraftforge.common.config.ConfigElement;
import net.minecraftforge.fml.client.config.GuiConfig;
import net.minecraftforge.fml.client.config.GuiMessageDialog;
import net.minecraftforge.fml.client.config.IConfigElement;
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
import net.minecraftforge.fml.client.event.ConfigChangedEvent.OnConfigChangedEvent;
import net.minecraftforge.fml.client.event.ConfigChangedEvent.PostConfigChangedEvent;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.eventhandler.Event.Result;

/**
 * @author AstroTibs
 * Adapted from Jabelar's Magic Beans:
 * https://github.com/jabelar/MagicBeans-1.7.10/blob/52dc91bfa2e515dcd6ebe116453dc98951f03dcb/src/main/java/com/blogspot/jabelarminecraft/magicbeans/gui/GuiConfig.java
 * and FunWayGuy's EnviroMine:
 * https://github.com/EnviroMine/EnviroMine-1.7/blob/1652062539adba36563450caefa1879127ccb950/src/main/java/enviromine/client/gui/menu/config/EM_ConfigMenu.java
 */
public class NEPGuiConfig extends GuiConfig
{

	public NEPGuiConfig(GuiScreen guiScreen)
	{
		super(
				guiScreen,         // parentScreen: the parent GuiScreen object
				getElements(),     // configElements: a List of IConfigProperty objects
                Reference.MOD_ID,  // modID: the mod ID for the mod whose config settings will be edited
				false,             // allRequireWorldRestart: send true if all configElements on this screen require a world restart
				false,             // allRequireMcRestart: send true if all configElements on this screen require MC to be restarted
				getHeader()        // title: the desired title for this screen. For consistency it is recommended that you pass the path of the config file being edited.
				);
	}

	// I was going to use this to warn the player if they had an old config folder but I kind of don't care
	private static String getHeader() {
		return TextFormatting.YELLOW
				+ ModNotEnoughPets.configDirectory.getAbsolutePath();
	}

	@SuppressWarnings({"unchecked", "rawtypes"})
	private static List<IConfigElement> getElements()
	{
		List<IConfigElement> subCats = new ArrayList<IConfigElement>();
		//List<IConfigElement> subCats;
		ConfigCategory cc;

		// General config
		subCats = new ArrayList<IConfigElement>();

		cc = GeneralConfig.config.getCategory(GeneralConfig.CAT_GENERAL);
		cc.setComment("General things such as the village spawn cap and how frequently a tamed cat makes noise");
		subCats.add( new ConfigElement(cc) );

		cc = GeneralConfig.config.getCategory(GeneralConfig.CAT_MISC);
		cc.setComment("The version checker is here");
		subCats.add( new ConfigElement(cc) );

		cc = GeneralConfig.config.getCategory(GeneralConfig.CAT_PARROT_IMITATION);
		cc.setComment("Manage the list of mob sounds the parrot will imitate");
		cc.setRequiresMcRestart(true);
		subCats.add( new ConfigElement(cc) );

		cc = GeneralConfig.config.getCategory(GeneralConfig.CAT_ENABLE_NEC_ANIMALS);
		cc.setComment("Disable NEC versions of various animals in order to increase inter-mod compatibility");
		cc.setRequiresMcRestart(true);
		subCats.add( new ConfigElement(cc) );

		cc = GeneralConfig.config.getCategory(GeneralConfig.CAT_EMERGENCY_UNDO);
		cc.setComment(TextFormatting.DARK_RED+"If you wish to remove "+Reference.MOD_NAME+ " from your game, you'll want to set \"revert cats\" to true, reload your world, and visit all the cats you want to keep.");
		cc.setRequiresMcRestart(true);
		subCats.add( new ConfigElement(cc) );

		return subCats;
	}

	@Override
    protected void actionPerformed(GuiButton button)
    {
        if (button.id == 2000) // The topmost "Done" button
        {
            boolean flag = true;

            try
            {
                if ((configID != null || this.parentScreen == null || !(this.parentScreen instanceof NEPGuiConfig))
                        && (this.entryList.hasChangedEntry(true)))
                {
                    boolean requiresMcRestart = this.entryList.saveConfigElements();

                    if (Loader.isModLoaded(modID))
                    {
                        ConfigChangedEvent event = new OnConfigChangedEvent(modID, configID, isWorldRunning, requiresMcRestart);
                        MinecraftForge.EVENT_BUS.post(event);

                        if (!event.getResult().equals(Result.DENY))
                        {
                        	MinecraftForge.EVENT_BUS.post(new PostConfigChangedEvent(modID, configID, isWorldRunning, requiresMcRestart));
                        	GeneralConfig.loadConfiguration(); // To force-sync the config options
                        }
                        if (requiresMcRestart)
                        {
                            flag = false;
                            mc.displayGuiScreen(new GuiMessageDialog(parentScreen, "fml.configgui.gameRestartTitle", new TextComponentString(I18n.format("fml.configgui.gameRestartRequired")), "fml.configgui.confirmRestartMessage"));
                        }

                        if (this.parentScreen instanceof NEPGuiConfig)
                            ((NEPGuiConfig) this.parentScreen).needsRefresh = true;
                    }
                }
            }
            catch (Throwable e) {
                e.printStackTrace();
            }

            if (flag)

                this.mc.displayGuiScreen(this.parentScreen);
        }
    }

}


code:
package astrotibs.notenoughpets.config;

import java.util.Set;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.fml.client.IModGuiFactory;

public class NEPGuiFactory implements IModGuiFactory
{
    @Override
    public void initialize(Minecraft minecraftInstance) { //Called when instantiated to initialize with the active Minecraft instance
    }

    @Override
    public Class<? extends GuiScreen> mainConfigGuiClass() { //Allows the main menu mod "Config" button to work
        return NEPGuiConfig.class;
    }

    @Override
    public Set<RuntimeOptionCategoryElement> runtimeGuiCategories() { // Not sure if this is implemented yet
        return null;
    }

    @Override
    public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) { // Allows for custom buttons or widgets
        return null;
    }

}


code:
package astrotibs.notenoughpets.entity;

/**
 * This is the interface used in 1.12. It is distinct from the EntityFlying interface used for Ghasts.
 * Yes, it is empty. IDK man
 */
public interface EntityFlying
{
}


code:
package astrotibs.notenoughpets.entity;

import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.passive.EntityCow;
import net.minecraft.entity.passive.EntityMooshroom;
import net.minecraft.entity.passive.EntityOcelot;
import net.minecraft.init.Blocks;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.world.World;

public class EntityMooshroomNEP extends EntityMooshroom
{
	private static final DataParameter<Integer> MOOSHROOM_VARIANT = EntityDataManager.<Integer>createKey(EntityOcelot.class, DataSerializers.VARINT);

	public EntityMooshroomNEP(World world) {
		super(world);
	}

    protected void entityInit()
    {
        super.entityInit();
        this.dataManager.register(MOOSHROOM_VARIANT, Integer.valueOf(this.worldObj.rand.nextInt(4)==0 ? 1 : 0));
    }

    /**
     * (abstract) Protected helper method to write subclass entity data to NBT.
     */
    public void writeEntityToNBT(NBTTagCompound tag)
    {
        super.writeEntityToNBT(tag);
        tag.setInteger("MooshroomType", this.getVarietySkin());
    }

    /**
     * (abstract) Protected helper method to read subclass entity data from NBT.
     */
    public void readEntityFromNBT(NBTTagCompound tag)
    {
        super.readEntityFromNBT(tag);
        this.setVarietySkin(tag.getInteger("MooshroomType"));
    }

    public int getVarietySkin()
    {
    	return ((Integer)this.dataManager.get(MOOSHROOM_VARIANT)).intValue();
    }

    public void setVarietySkin(int type)
    {
    	this.dataManager.set(MOOSHROOM_VARIANT, Integer.valueOf(type));
    }

    // v1.3.0
    @Override
    public EntityMooshroomNEP createChild(EntityAgeable entityAgeable)
    {
        return new EntityMooshroomNEP(this.worldObj);
    }

    @Override
    public boolean isShearable(ItemStack item, net.minecraft.world.IBlockAccess world, net.minecraft.util.math.BlockPos pos){ return getGrowingAge() >= 0; }

    @Override
    public java.util.List<ItemStack> onSheared(ItemStack item, net.minecraft.world.IBlockAccess world, net.minecraft.util.math.BlockPos pos, int fortune)
    {
        this.setDead();
        this.worldObj.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY + (double)(this.height / 2.0F), this.posZ, 0.0D, 0.0D, 0.0D, new int[0]);

        EntityCow entitycow = new EntityCow(this.worldObj);
        entitycow.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, this.rotationPitch);
        entitycow.setHealth(this.getHealth());
        entitycow.renderYawOffset = this.renderYawOffset;

        if (this.hasCustomName())
        {
            entitycow.setCustomNameTag(this.getCustomNameTag());
        }

        this.worldObj.spawnEntityInWorld(entitycow);

        java.util.List<ItemStack> ret = new java.util.ArrayList<ItemStack>();
        for (int i = 0; i < 5; ++i)
        {
            ret.add(new ItemStack(this.getVarietySkin()==0 ? Blocks.RED_MUSHROOM : Blocks.BROWN_MUSHROOM));
        }

        this.playSound(SoundEvents.ENTITY_MOOSHROOM_SHEAR, 1.0F, 1.0F);
        return ret;
    }
}