NecromancyMinecraft Wiki
Advertisement

Intro[]

The Necro API is an API that allows minecraft modders to add their own models to the necromancy mod. Currently the only things that are supported are adding their models and defining the attributes and animation of every bodypart, but in the future the API will allow you to add your own AI's and custom attributes as well as an event system.

Installing The API[]

The API can be downloaded from the forum http://www.minecraftforum.net/topic/1571429-162-the-necromancy-mod-14-necro-api-12/. Download the zip and extract it next to your own source code.


Creating The Model[]

Let's start off by creating the model. To do this you need a new class. If your model extends ModelBiped or ModelQuadruped, you can make your class extend NecroEntityBiped or NecroEntityQuadruped and skip this step. For this example I will be adding the zombie. Create a new class like so:

import com.sirolf2009.necroapi.NecroEntityBase;

public class NecroEntityZombie() extends NecroEntityBase {
    public NecroEntityZombie() {
        super("Zombie");
        texture = new ResourceLocation("textures/entity/zombie/zombie.png");
        textureHeight = 64;
    }
}

Here we simply create a class, make it extend NecroEntityBase and call the super constructor. After that we define the texture with a ResourceLocation. Because the zombie texture is 64X64 rather than the default 64X32, we need to set the texture height to 64. The parameter for the super constructor is the name of the mob. Next up are the actual models. A model is cut up in 5 different parts: the head, the torso, the left arm, the right arm and the legs. Unlike in normal minecraft models, the model is not made out of ModelRenderer's but instead we will use the class BodyPart. Let's start with the head as it is the easiest.

import com.sirolf2009.necroapi.NecroEntityBase;
import com.sirolf2009.necroapi.BodyPart;

public class NecroEntityZombie() extends NecroEntityBase {
    public NecroEntityZombie() {
        super("Zombie");
        texture = new ResourceLocation("textures/entity/zombie/zombie.png");
        textureHeight = 64;
    }

    @Override
    public BodyPart[] initHead(ModelBase model) {
        BodyPart head = new BodyPart(this, model, 0, 0);
        head.addBox(-4, -4, -4, 8, 8, 8, 0.0F);
        return new BodyPart[] { head };
    }
}

Let's go over this line by line. The first line creates a new BodyPart called head. The first parameter is the class itself. In the second parameter, you pass the model on. The third and fourth parameters are the X and Y offset for the texture. After that we create add a new box. The box is 8x8x8 and is put at the coord -4,-4,-4. The coord 0,0,0 is where the head is attached to the torso. The last line returns a new array containing the head we just created.

Next up are the legs, they are done like so.

import com.sirolf2009.necroapi.NecroEntityBase;
import com.sirolf2009.necroapi.BodyPart;

public class NecroEntityZombie() extends NecroEntityBase {
    public NecroEntityZombie() {
        super("Zombie");
        texture = new ResourceLocation("textures/entity/zombie/zombie.png");
        textureHeight = 64;
    }

    @Override
    public BodyPart[] initHead(ModelBase model) {
        BodyPart head = new BodyPart(this, model, 0, 0);
        head.addBox(-4, -4, -4, 8, 8, 8, 0.0F);
        return new BodyPart[] { head };
    }

    @Override
    public BodyPart[] initLegs(ModelBase model) {
        float[] torsoPos = { -4F, -2F, -2F };
        BodyPart legLeft = new BodyPart(this, torsoPos, model, 0, 16);
        legLeft.addBox(-4.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        legLeft.setRotationPoint(0.0F, 12.0F, 0.0F);
        BodyPart legRight = new BodyPart(this, torsoPos, model, 0, 16);
        legRight.addBox(0.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        legRight.setRotationPoint(0.0F, 12.0F, 0.0F);
        legLeft.mirror = true;
        return new BodyPart[] { legLeft, legRight };
    }
}

As you can see, the legs are a bit more tricky. The first thing you should notice is the float array. This is the location where the torso will be attached to the legs. It is added to the constructor of the bodyparts. The rest is pretty much the same as the head. Note that it doesn't matter in what order you put the bodyparts when you are returning the array.

Now we will add the arms and the torso.

import com.sirolf2009.necroapi.NecroEntityBase;
import com.sirolf2009.necroapi.BodyPart;

public class NecroEntityZombie() extends NecroEntityBase {
    public NecroEntityZombie() {
        super("Zombie");
        texture = new ResourceLocation("textures/entity/zombie/zombie.png");
        textureHeight = 64;
    }

    @Override
    public BodyPart[] initHead(ModelBase model) {
        BodyPart head = new BodyPart(this, model, 0, 0);
        head.addBox(-4, -4, -4, 8, 8, 8, 0.0F);
        return new BodyPart[] { head };
    }

    @Override
    public BodyPart[] initTorso(ModelBase model) {
        float[] headPos = { 4.0F, -4.0F, 2.0F };
        float[] armLeftPos = { -4F, 0.0F, 2.0F };
        float[] armRightPos = { 8F, 0.0F, 2.0F };
        BodyPart torso = new BodyPart(this, armLeftPos, armRightPos, headPos, model, 16, 16);
        torso.addBox(0.0F, 0.0F, 0.0F, 8, 12, 4, 0.0F);
        return new BodyPart[] { torso };
    }

    @Override
    public BodyPart[] initArmLeft(ModelBase model) {
        BodyPart armLeft = new BodyPart(this, model, 40, 16);
        armLeft.addBox(0.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        armLeft.mirror = true;
        return new BodyPart[] { armLeft };
    }

    @Override
    public BodyPart[] initArmRight(ModelBase model) {
        BodyPart armRight = new BodyPart(this, model, 40, 16);
        armRight.addBox(0.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        return new BodyPart[] { armRight };
    }

    @Override
    public BodyPart[] initLegs(ModelBase model) {
        float[] torsoPos = { -4F, -2F, -2F };
        BodyPart legLeft = new BodyPart(this, torsoPos, model, 0, 16);
        legLeft.addBox(-4.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        legLeft.setRotationPoint(0.0F, 12.0F, 0.0F);
        BodyPart legRight = new BodyPart(this, torsoPos, model, 0, 16);
        legRight.addBox(0.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        legRight.setRotationPoint(0.0F, 12.0F, 0.0F);
        legLeft.mirror = true;
        return new BodyPart[] { legLeft, legRight };
    }
}

The arms are done the same as the head, but the torso does something new. Because the torso has 3 parts that are attached to it, we need 3 float arrays. They all define the coords of where the bodypart has to connect. After that the arrays are passed on to the BodyPart constructor. Keep in mind that the order in which you add the arrays is important. Congratulations, you have now added the model and we can continue to the animation.

Animating[]

I will continue using the zombie model that we have created in the previous section. We want to add a new method for the animating.

import com.sirolf2009.necroapi.NecroEntityBase;
import com.sirolf2009.necroapi.BodyPart;
import com.sirolf2009.necroapi.BodyPartLocation;

public class NecroEntityZombie() extends NecroEntityBase {
    public NecroEntityZombie() {
        super("Zombie");
        texture = new ResourceLocation("textures/entity/zombie/zombie.png");
        textureHeight = 64;
    }

    @Override
    public BodyPart[] initHead(ModelBase model) {
        BodyPart head = new BodyPart(this, model, 0, 0);
        head.addBox(-4, -4, -4, 8, 8, 8, 0.0F);
        return new BodyPart[] { head };
    }

    @Override
    public BodyPart[] initTorso(ModelBase model) {
        float[] headPos = { 4.0F, -4.0F, 2.0F };
        float[] armLeftPos = { -4F, 0.0F, 2.0F };
        float[] armRightPos = { 8F, 0.0F, 2.0F };
        BodyPart torso = new BodyPart(this, armLeftPos, armRightPos, headPos, model, 16, 16);
        torso.addBox(0.0F, 0.0F, 0.0F, 8, 12, 4, 0.0F);
        return new BodyPart[] { torso };
    }

    @Override
    public BodyPart[] initArmLeft(ModelBase model) {
        BodyPart armLeft = new BodyPart(this, model, 40, 16);
        armLeft.addBox(0.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        armLeft.mirror = true;
        return new BodyPart[] { armLeft };
    }

    @Override
    public BodyPart[] initArmRight(ModelBase model) {
        BodyPart armRight = new BodyPart(this, model, 40, 16);
        armRight.addBox(0.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        return new BodyPart[] { armRight };
    }

    @Override
    public BodyPart[] initLegs(ModelBase model) {
        float[] torsoPos = { -4F, -2F, -2F };
        BodyPart legLeft = new BodyPart(this, torsoPos, model, 0, 16);
        legLeft.addBox(-4.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        legLeft.setRotationPoint(0.0F, 12.0F, 0.0F);
        BodyPart legRight = new BodyPart(this, torsoPos, model, 0, 16);
        legRight.addBox(0.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        legRight.setRotationPoint(0.0F, 12.0F, 0.0F);
        legLeft.mirror = true;
        return new BodyPart[] { legLeft, legRight };
    }

    @Override
    public void setRotationAngles(float par1, float par2, float par3, float par4, float par5, float par6, Entity par7Entity, BodyPart[] bodypart, BodyPartLocation location) {
        if (location == BodyPartLocation.Head) {
            bodypart[0].rotateAngleY = par4 / (180F / (float) Math.PI);
            bodypart[0].rotateAngleX = par5 / (180F / (float) Math.PI);
            bodypart[1].rotateAngleY = par4 / (180F / (float) Math.PI);
            bodypart[1].rotateAngleX = par5 / (180F / (float) Math.PI);
        }
        if (location == BodyPartLocation.ArmLeft) {
            bodypart[0].rotateAngleX = MathHelper.cos(par1 * 0.6662F) * 2.0F * par2 * 0.5F;
            bodypart[0].rotateAngleZ = 0.0F;
        }
        if (location == BodyPartLocation.ArmRight) {
            bodypart[0].rotateAngleX = MathHelper.cos(par1 * 0.6662F + (float) Math.PI) * 2.0F * par2 * 0.5F;
            bodypart[0].rotateAngleZ = 0.0F;
        }
        if (location == BodyPartLocation.Legs) {
            bodypart[0].rotateAngleX = MathHelper.cos(par1 * 0.6662F) * 1.4F * par2;
            bodypart[1].rotateAngleX = MathHelper.cos(par1 * 0.6662F + (float) Math.PI) * 1.4F * par2;
            bodypart[0].rotateAngleY = 0.0F;
            bodypart[1].rotateAngleY = 0.0F;
        }
    }
}

You should notice that it looks a lot like minecraft's setRotationAngles method. This method does add 2 new parameters however. The first new parameter is the actual bodypart. The second parameter is an enum that tells you the location of the bodypart. In the first line of this method, we check if the location is the head. If so we rotate it. The rotation for this is the same as minecraft's rotation for Bipeds. Because we only returned one BodyPart in our initHead method, we only need to rotate bodypart[0]. Because we returned the 2 BodyParts in our initLegs method, we have to rotate both bodypart[0] and bodypart[1]. After this, the minion is animated, but we still haven't defined how it is created, or what it's attributes are. We will do that in the next section

Items And Attributes[]

For this part I will assume that you have followed everything above. We now have a class called NecroEntityZombie and we have defined the models and the animations. We will now define what items are bound to the minion like so.

import com.sirolf2009.necroapi.NecroEntityBase;
import com.sirolf2009.necroapi.BodyPart;
import com.sirolf2009.necroapi.BodyPartLocation;

public class NecroEntityZombie() extends NecroEntityBase {
    public NecroEntityZombie() {
        super("Zombie");
        headItem = new ItemStack(Item.skull, 1, 2);
        torsoItem = new ItemStack(Item.rottenFlesh, 1);
        armItem = new ItemStack(Item.rottenFlesh, 1);
        legItem = new ItemStack(Item.rottenFlesh, 1);
        texture = new ResourceLocation("textures/entity/zombie/zombie.png");
        textureHeight = 64;
    }

    @Override
    public void initRecipes() {
        initDefaultRecipes(Item.rottenFlesh);
    }

    @Override
    public BodyPart[] initHead(ModelBase model) {
        BodyPart head = new BodyPart(this, model, 0, 0);
        head.addBox(-4, -4, -4, 8, 8, 8, 0.0F);
        return new BodyPart[] { head };
    }

    @Override
    public BodyPart[] initTorso(ModelBase model) {
        float[] headPos = { 4.0F, -4.0F, 2.0F };
        float[] armLeftPos = { -4F, 0.0F, 2.0F };
        float[] armRightPos = { 8F, 0.0F, 2.0F };
        BodyPart torso = new BodyPart(this, armLeftPos, armRightPos, headPos, model, 16, 16);
        torso.addBox(0.0F, 0.0F, 0.0F, 8, 12, 4, 0.0F);
        return new BodyPart[] { torso };
    }

    @Override
    public BodyPart[] initArmLeft(ModelBase model) {
        BodyPart armLeft = new BodyPart(this, model, 40, 16);
        armLeft.addBox(0.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        armLeft.mirror = true;
        return new BodyPart[] { armLeft };
    }

    @Override
    public BodyPart[] initArmRight(ModelBase model) {
        BodyPart armRight = new BodyPart(this, model, 40, 16);
        armRight.addBox(0.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        return new BodyPart[] { armRight };
    }

    @Override
    public BodyPart[] initLegs(ModelBase model) {
        float[] torsoPos = { -4F, -2F, -2F };
        BodyPart legLeft = new BodyPart(this, torsoPos, model, 0, 16);
        legLeft.addBox(-4.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        legLeft.setRotationPoint(0.0F, 12.0F, 0.0F);
        BodyPart legRight = new BodyPart(this, torsoPos, model, 0, 16);
        legRight.addBox(0.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        legRight.setRotationPoint(0.0F, 12.0F, 0.0F);
        legLeft.mirror = true;
        return new BodyPart[] { legLeft, legRight };
    }

    @Override
    public void setRotationAngles(float par1, float par2, float par3, float par4, float par5, float par6, Entity par7Entity, BodyPart[] bodypart, BodyPartLocation location) {
        if (location == BodyPartLocation.Head) {
            bodypart[0].rotateAngleY = par4 / (180F / (float) Math.PI);
            bodypart[0].rotateAngleX = par5 / (180F / (float) Math.PI);
            bodypart[1].rotateAngleY = par4 / (180F / (float) Math.PI);
            bodypart[1].rotateAngleX = par5 / (180F / (float) Math.PI);
        }
        if (location == BodyPartLocation.ArmLeft) {
            bodypart[0].rotateAngleX = MathHelper.cos(par1 * 0.6662F) * 2.0F * par2 * 0.5F;
            bodypart[0].rotateAngleZ = 0.0F;
        }
        if (location == BodyPartLocation.ArmRight) {
            bodypart[0].rotateAngleX = MathHelper.cos(par1 * 0.6662F + (float) Math.PI) * 2.0F * par2 * 0.5F;
            bodypart[0].rotateAngleZ = 0.0F;
        }
        if (location == BodyPartLocation.Legs) {
            bodypart[0].rotateAngleX = MathHelper.cos(par1 * 0.6662F) * 1.4F * par2;
            bodypart[1].rotateAngleX = MathHelper.cos(par1 * 0.6662F + (float) Math.PI) * 1.4F * par2;
            bodypart[0].rotateAngleY = 0.0F;
            bodypart[1].rotateAngleY = 0.0F;
        }
    }
}

If you look at the constructor you will see that we set the head item to a zombie skull, the other parts are set to rotten flesh. This means that if you put a zombie skull in the altar, the minion will get a zombie head. If you put rotten flesh in any other altar slot, you will get the corresponding zombie part. You should also notice a new method called initRecipes which calls another method called initDefaultRecipes. This creates the recipes with the default recipes (the recipes that the generic entities use) and puts rotten flesh in the "blank" slot.

Now we will add the attributes, we need another method for this called setAttributes. It should look like this.

import com.sirolf2009.necroapi.NecroEntityBase;
import com.sirolf2009.necroapi.BodyPart;
import com.sirolf2009.necroapi.BodyPartLocation;

public class NecroEntityZombie() extends NecroEntityBase {
    public NecroEntityZombie() {
        super("Zombie");
        headItem = new ItemStack(Item.skull, 1, 2);
        torsoItem = new ItemStack(Item.rottenFlesh, 1);
        armItem = new ItemStack(Item.rottenFlesh, 1);
        legItem = new ItemStack(Item.rottenFlesh, 1);
        texture = new ResourceLocation("textures/entity/zombie/zombie.png");
        textureHeight = 64;
    }

    @Override
    public void initRecipes() {
        initDefaultRecipes(Item.rottenFlesh);
    }

    @Override
    public BodyPart[] initHead(ModelBase model) {
        BodyPart head = new BodyPart(this, model, 0, 0);
        head.addBox(-4, -4, -4, 8, 8, 8, 0.0F);
        return new BodyPart[] { head };
    }

    @Override
    public BodyPart[] initTorso(ModelBase model) {
        float[] headPos = { 4.0F, -4.0F, 2.0F };
        float[] armLeftPos = { -4F, 0.0F, 2.0F };
        float[] armRightPos = { 8F, 0.0F, 2.0F };
        BodyPart torso = new BodyPart(this, armLeftPos, armRightPos, headPos, model, 16, 16);
        torso.addBox(0.0F, 0.0F, 0.0F, 8, 12, 4, 0.0F);
        return new BodyPart[] { torso };
    }

    @Override
    public BodyPart[] initArmLeft(ModelBase model) {
        BodyPart armLeft = new BodyPart(this, model, 40, 16);
        armLeft.addBox(0.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        armLeft.mirror = true;
        return new BodyPart[] { armLeft };
    }

    @Override
    public BodyPart[] initArmRight(ModelBase model) {
        BodyPart armRight = new BodyPart(this, model, 40, 16);
        armRight.addBox(0.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        return new BodyPart[] { armRight };
    }

    @Override
    public BodyPart[] initLegs(ModelBase model) {
        float[] torsoPos = { -4F, -2F, -2F };
        BodyPart legLeft = new BodyPart(this, torsoPos, model, 0, 16);
        legLeft.addBox(-4.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        legLeft.setRotationPoint(0.0F, 12.0F, 0.0F);
        BodyPart legRight = new BodyPart(this, torsoPos, model, 0, 16);
        legRight.addBox(0.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        legRight.setRotationPoint(0.0F, 12.0F, 0.0F);
        legLeft.mirror = true;
        return new BodyPart[] { legLeft, legRight };
    }

    @Override
    public void setRotationAngles(float par1, float par2, float par3, float par4, float par5, float par6, Entity par7Entity, BodyPart[] bodypart, BodyPartLocation location) {
        if (location == BodyPartLocation.Head) {
            bodypart[0].rotateAngleY = par4 / (180F / (float) Math.PI);
            bodypart[0].rotateAngleX = par5 / (180F / (float) Math.PI);
            bodypart[1].rotateAngleY = par4 / (180F / (float) Math.PI);
            bodypart[1].rotateAngleX = par5 / (180F / (float) Math.PI);
        }
        if (location == BodyPartLocation.ArmLeft) {
            bodypart[0].rotateAngleX = MathHelper.cos(par1 * 0.6662F) * 2.0F * par2 * 0.5F;
            bodypart[0].rotateAngleZ = 0.0F;
        }
        if (location == BodyPartLocation.ArmRight) {
            bodypart[0].rotateAngleX = MathHelper.cos(par1 * 0.6662F + (float) Math.PI) * 2.0F * par2 * 0.5F;
            bodypart[0].rotateAngleZ = 0.0F;
        }
        if (location == BodyPartLocation.Legs) {
            bodypart[0].rotateAngleX = MathHelper.cos(par1 * 0.6662F) * 1.4F * par2;
            bodypart[1].rotateAngleX = MathHelper.cos(par1 * 0.6662F + (float) Math.PI) * 1.4F * par2;
            bodypart[0].rotateAngleY = 0.0F;
            bodypart[1].rotateAngleY = 0.0F;
        }
    }

    @Override
    public void setAttributes(EntityLivingBase minion, BodyPartLocation location) {
        if(location == BodyPartLocation.Head) {
   head[0].attributes.func_111150_b(SharedMonsterAttributes.field_111267_a).func_111128_a(2.0D); //health
			head[0].attributes.func_111150_b(SharedMonsterAttributes.field_111265_b).func_111128_a(40.0D); //followrange
			head[0].attributes.func_111150_b(SharedMonsterAttributes.field_111266_c).func_111128_a(0.0D); //knockback res
			head[0].attributes.func_111150_b(SharedMonsterAttributes.field_111263_d).func_111128_a(0.0D); //speed
			head[0].attributes.func_111150_b(SharedMonsterAttributes.field_111264_e).func_111128_a(1.0D); //damage
        } else if(location == BodyPartLocation.Torso) {
			torso[0].attributes.func_111150_b(SharedMonsterAttributes.field_111267_a).func_111128_a(12.0D); //health
			torso[0].attributes.func_111150_b(SharedMonsterAttributes.field_111265_b).func_111128_a(0.0D); //followrange
			torso[0].attributes.func_111150_b(SharedMonsterAttributes.field_111266_c).func_111128_a(0.0D); //knockback res
			torso[0].attributes.func_111150_b(SharedMonsterAttributes.field_111263_d).func_111128_a(0.0D); //speed
			torso[0].attributes.func_111150_b(SharedMonsterAttributes.field_111264_e).func_111128_a(0.0D); //damage
        } else if(location == BodyPartLocation.ArmLeft) {
			armLeft[0].attributes.func_111150_b(SharedMonsterAttributes.field_111267_a).func_111128_a(2.0D); //health
			armLeft[0].attributes.func_111150_b(SharedMonsterAttributes.field_111265_b).func_111128_a(0.0D); //followrange
			armLeft[0].attributes.func_111150_b(SharedMonsterAttributes.field_111266_c).func_111128_a(0.0D); //knockback res
			armLeft[0].attributes.func_111150_b(SharedMonsterAttributes.field_111263_d).func_111128_a(0.0D); //speed
			armLeft[0].attributes.func_111150_b(SharedMonsterAttributes.field_111264_e).func_111128_a(1.0D); //damage
        } else if(location == BodyPartLocation.ArmRight) {
			armRight[0].attributes.func_111150_b(SharedMonsterAttributes.field_111267_a).func_111128_a(2.0D); //health
			armRight[0].attributes.func_111150_b(SharedMonsterAttributes.field_111265_b).func_111128_a(0.0D); //followrange
			armRight[0].attributes.func_111150_b(SharedMonsterAttributes.field_111266_c).func_111128_a(0.0D); //knockback res
			armRight[0].attributes.func_111150_b(SharedMonsterAttributes.field_111263_d).func_111128_a(0.0D); //speed
			armRight[0].attributes.func_111150_b(SharedMonsterAttributes.field_111264_e).func_111128_a(1.0D); //damage
        } else if(location == BodyPartLocation.Legs) {
			legs[0].attributes.func_111150_b(SharedMonsterAttributes.field_111267_a).func_111128_a(2.0D); //health
			legs[0].attributes.func_111150_b(SharedMonsterAttributes.field_111265_b).func_111128_a(0.0D); //followrange
			legs[0].attributes.func_111150_b(SharedMonsterAttributes.field_111266_c).func_111128_a(0.0D); //knockback res
			legs[0].attributes.func_111150_b(SharedMonsterAttributes.field_111263_d).func_111128_a(0.23D); //speed
			legs[0].attributes.func_111150_b(SharedMonsterAttributes.field_111264_e).func_111128_a(0.0D); //damage
        }
    }
}

This only has 2 parameters. The minion entity, in case you want to add special bodypart combo's (eg. a full set of your mob will give him a speed boost) and the location of the bodypart. After that you add your attributes to the bodypart and defines its value. You only need to add the attributes to the first index of the array.

Registering Your Minion And Exporting[]

To register your minion you have to add this line

NecroEntityRegistry.RegisterEntity(new NecroEntityZombie());

to your generic class. I would advise doing this in either init or pre-init.

To export your mod you simply compile it as you normally would. Just make sure that you also compile the API along with it and upload the API in the same zip as your mod. If you forget to include the api, your mod will crash on startup.

Final Words[]

If you decide to use the API, don't forget to add your mobs to the minion page. If you are having trouble or if you have a question, feel free to leave a comment here or on the minecraft forums

Advertisement