Today, I'm going to show you how to create a basic biped mob in Minecraft. I know I skipped over stuff like armor, creative tabs, tools, etc., but I can do all of that later, putting aside the fact that every single tutorial on these forums as those things. Anyways, let's get started. So, for today, I'm going to give you straight out of my mod. In Zeuscraft, I've added an absurd amount of biped mobs (BTW, biped is basically the model for the player); nearly 18 bipeds. So I'm going to take one of them, Zeus, and show you how to create the biped mob. I call it NPC because it helps people envision it better, but an NPC is still a mob nonetheless.
Creating a Biped NPC
So I do this backwards from most people - we're going to start off by creating a render file. Now, render files usually are not that long for normal mobs, but for NPCs and players, we have to render stuff like their held item, their armor, etc., so it's going to be much longer than normal. So here is our first file, we're going to put it in a new package called fisherman77.zeuscraft.mobs.
Optionally, if you know that you're going to have a ton of mobs, you can put all the render files in a separate package like fisherman77.zeuscraft.client.render, or you could group the entity (AI) files and render files in groups like in my case putting the immortals from Greek mythology in fisherman77.zeuscraft.olympians -- whatever works for you.
RenderZeus.java:
package fisherman77.zeuscraft.common.mobs.olympus;
import com.google.common.collect.Maps;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.util.Map;
import net.minecraft.block.Block;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.entity.RenderLiving;
import net.minecraft.client.renderer.tileentity.TileEntitySkullRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.EnumArmorMaterial;
import net.minecraft.item.Item;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
import static net.minecraftforge.client.IItemRenderer.ItemRenderType.EQUIPPED;
import static net.minecraftforge.client.IItemRenderer.ItemRendererHelper.BLOCK_3D;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.IItemRenderer;
import net.minecraftforge.client.MinecraftForgeClient;
@SideOnly(Side.CLIENT)
public class RenderZeus extends RenderLiving
{
protected ModelBiped modelBipedMain;
protected float field_77070_b;
protected ModelBiped field_82423_g;
protected ModelBiped field_82425_h;
private static final Map field_110859_k = Maps.newHashMap();
private static final ResourceLocation skin = new ResourceLocation("zeuscraft", "textures/entities/olympus/zeus.png");
/** List of armor texture filenames. */
public static String[] bipedArmorFilenamePrefix = new String[] {"leather", "chainmail", "iron", "diamond", "gold"};
public RenderZeus(ModelBiped par1ModelBiped, float par2)
{
this(par1ModelBiped, par2, 1.0F);
}
public RenderZeus(ModelBiped par1ModelBiped, float par2, float par3)
{
super(par1ModelBiped, par2);
this.modelBipedMain = par1ModelBiped;
this.field_77070_b = par3;
this.func_82421_b();
}
protected void func_82421_b()
{
this.field_82423_g = new ModelBiped(1.0F);
this.field_82425_h = new ModelBiped(0.5F);
}
@Deprecated //Use the more sensitve version getArmorResource below
public static ResourceLocation func_110857_a(ItemArmor par0ItemArmor, int par1)
{
return func_110858_a(par0ItemArmor, par1, (String)null);
}
@Deprecated //Use the more sensitve version getArmorResource below
public static ResourceLocation func_110858_a(ItemArmor par0ItemArmor, int par1, String par2Str)
{
String s1 = String.format("textures/models/armor/%s_layer_%d%s.png", new Object[] {bipedArmorFilenamePrefix[par0ItemArmor.renderIndex], Integer.valueOf(par1 == 2 ? 2 : 1), par2Str == null ? "" : String.format("_%s", new Object[]{par2Str})});
ResourceLocation resourcelocation = (ResourceLocation)field_110859_k.get(s1);
if (resourcelocation == null)
{
resourcelocation = new ResourceLocation(s1);
field_110859_k.put(s1, resourcelocation);
}
return resourcelocation;
}
/**
* More generic ForgeHook version of the above function, it allows for Items to have more control over what texture they provide.
*
* @param entity Entity wearing the armor
* @param stack ItemStack for the armor
* @param slot Slot ID that the item is in
* @param type Subtype, can be null or "overlay"
* @return ResourceLocation pointing at the armor's texture
*/
public static ResourceLocation getArmorResource(Entity entity, ItemStack stack, int slot, String type)
{
ItemArmor item = (ItemArmor)stack.getItem();
String s1 = String.format("textures/models/armor/%s_layer_%d%s.png",
bipedArmorFilenamePrefix[item.renderIndex], (slot == 2 ? 2 : 1), type == null ? "" : String.format("_%s", type));
s1 = ForgeHooksClient.getArmorTexture(entity, stack, s1, slot, type);
ResourceLocation resourcelocation = (ResourceLocation)field_110859_k.get(s1);
if (resourcelocation == null)
{
resourcelocation = new ResourceLocation(s1);
field_110859_k.put(s1, resourcelocation);
}
return resourcelocation;
}
protected int func_130006_a(EntityZeus par1EntityLiving, int par2, float par3)
{
ItemStack itemstack = par1EntityLiving.func_130225_q(3 - par2);
if (itemstack != null)
{
Item item = itemstack.getItem();
if (item instanceof ItemArmor)
{
ItemArmor itemarmor = (ItemArmor)item;
this.func_110776_a(getArmorResource(par1EntityLiving, itemstack, par2, null));
ModelBiped modelbiped = par2 == 2 ? this.field_82425_h : this.field_82423_g;
modelbiped.bipedHead.showModel = par2 == 0;
modelbiped.bipedHeadwear.showModel = par2 == 0;
modelbiped.bipedBody.showModel = par2 == 1 || par2 == 2;
modelbiped.bipedRightArm.showModel = par2 == 1;
modelbiped.bipedLeftArm.showModel = par2 == 1;
modelbiped.bipedRightLeg.showModel = par2 == 2 || par2 == 3;
modelbiped.bipedLeftLeg.showModel = par2 == 2 || par2 == 3;
modelbiped = ForgeHooksClient.getArmorModel(par1EntityLiving, itemstack, par2, modelbiped);
this.setRenderPassModel(modelbiped);
modelbiped.onGround = this.mainModel.onGround;
modelbiped.isRiding = this.mainModel.isRiding;
modelbiped.isChild = this.mainModel.isChild;
float f1 = 1.0F;
//Move out of if to allow for more then just CLOTH to have color
int j = itemarmor.getColor(itemstack);
if (j != -1)
{
float f2 = (float)(j >> 16 & 255) / 255.0F;
float f3 = (float)(j >> 8 & 255) / 255.0F;
float f4 = (float)(j & 255) / 255.0F;
GL11.glColor3f(f1 * f2, f1 * f3, f1 * f4);
if (itemstack.isItemEnchanted())
{
return 31;
}
return 16;
}
GL11.glColor3f(f1, f1, f1);
if (itemstack.isItemEnchanted())
{
return 15;
}
return 1;
}
}
return -1;
}
protected void func_130013_c(EntityZeus par1EntityLiving, int par2, float par3)
{
ItemStack itemstack = par1EntityLiving.func_130225_q(3 - par2);
if (itemstack != null)
{
Item item = itemstack.getItem();
if (item instanceof ItemArmor)
{
this.func_110776_a(getArmorResource(par1EntityLiving, itemstack, par2, "overlay"));
float f1 = 1.0F;
GL11.glColor3f(f1, f1, f1);
}
}
}
public void doRenderLiving(EntityZeus par1EntityLiving, double par2, double par4, double par6, float par8, float par9)
{
float f2 = 1.0F;
GL11.glColor3f(f2, f2, f2);
ItemStack itemstack = par1EntityLiving.getHeldItem();
this.func_82420_a(par1EntityLiving, itemstack);
double d3 = par4 - (double)par1EntityLiving.yOffset;
if (par1EntityLiving.isSneaking())
{
d3 -= 0.125D;
}
super.doRenderLiving(par1EntityLiving, par2, d3, par6, par8, par9);
this.field_82423_g.aimedBow = this.field_82425_h.aimedBow = this.modelBipedMain.aimedBow = false;
this.field_82423_g.isSneak = this.field_82425_h.isSneak = this.modelBipedMain.isSneak = false;
this.field_82423_g.heldItemRight = this.field_82425_h.heldItemRight = this.modelBipedMain.heldItemRight = 0;
}
protected ResourceLocation func_110856_a(EntityZeus par1EntityZeus)
{
return null;
}
protected void func_82420_a(EntityZeus par1EntityLiving, ItemStack par2ItemStack)
{
this.field_82423_g.heldItemRight = this.field_82425_h.heldItemRight = this.modelBipedMain.heldItemRight = par2ItemStack != null ? 1 : 0;
this.field_82423_g.isSneak = this.field_82425_h.isSneak = this.modelBipedMain.isSneak = par1EntityLiving.isSneaking();
}
protected void func_130005_c(EntityZeus par1EntityLiving, float par2)
{
float f1 = 1.0F;
GL11.glColor3f(f1, f1, f1);
super.renderEquippedItems(par1EntityLiving, par2);
ItemStack itemstack = par1EntityLiving.getHeldItem();
ItemStack itemstack1 = par1EntityLiving.func_130225_q(3);
float f2;
if (itemstack1 != null)
{
GL11.glPushMatrix();
this.modelBipedMain.bipedHead.postRender(0.0625F);
IItemRenderer customRenderer = MinecraftForgeClient.getItemRenderer(itemstack1, EQUIPPED);
boolean is3D = (customRenderer != null && customRenderer.shouldUseRenderHelper(EQUIPPED, itemstack1, BLOCK_3D));
if (itemstack1.getItem() instanceof ItemBlock)
{
if (is3D || RenderBlocks.renderItemIn3d(Block.blocksList[itemstack1.itemID].getRenderType()))
{
f2 = 0.625F;
GL11.glTranslatef(0.0F, -0.25F, 0.0F);
GL11.glRotatef(90.0F, 0.0F, 1.0F, 0.0F);
GL11.glScalef(f2, -f2, -f2);
}
this.renderManager.itemRenderer.renderItem(par1EntityLiving, itemstack1, 0);
}
else if (itemstack1.getItem().itemID == Item.skull.itemID)
{
f2 = 1.0625F;
GL11.glScalef(f2, -f2, -f2);
String s = "";
if (itemstack1.hasTagCompound() && itemstack1.getTagCompound().hasKey("SkullOwner"))
{
s = itemstack1.getTagCompound().getString("SkullOwner");
}
TileEntitySkullRenderer.skullRenderer.func_82393_a(-0.5F, 0.0F, -0.5F, 1, 180.0F, itemstack1.getItemDamage(), s);
}
GL11.glPopMatrix();
}
if (itemstack != null)
{
GL11.glPushMatrix();
if (this.mainModel.isChild)
{
f2 = 0.5F;
GL11.glTranslatef(0.0F, 0.625F, 0.0F);
GL11.glRotatef(-20.0F, -1.0F, 0.0F, 0.0F);
GL11.glScalef(f2, f2, f2);
}
this.modelBipedMain.bipedRightArm.postRender(0.0625F);
GL11.glTranslatef(-0.0625F, 0.4375F, 0.0625F);
IItemRenderer customRenderer = MinecraftForgeClient.getItemRenderer(itemstack, EQUIPPED);
boolean is3D = (customRenderer != null && customRenderer.shouldUseRenderHelper(EQUIPPED, itemstack, BLOCK_3D));
if (itemstack.getItem() instanceof ItemBlock && (is3D || RenderBlocks.renderItemIn3d(Block.blocksList[itemstack.itemID].getRenderType())))
{
f2 = 0.5F;
GL11.glTranslatef(0.0F, 0.1875F, -0.3125F);
f2 *= 0.75F;
GL11.glRotatef(20.0F, 1.0F, 0.0F, 0.0F);
GL11.glRotatef(45.0F, 0.0F, 1.0F, 0.0F);
GL11.glScalef(-f2, -f2, f2);
}
else if (itemstack.itemID == Item.bow.itemID)
{
f2 = 0.625F;
GL11.glTranslatef(0.0F, 0.125F, 0.3125F);
GL11.glRotatef(-20.0F, 0.0F, 1.0F, 0.0F);
GL11.glScalef(f2, -f2, f2);
GL11.glRotatef(-100.0F, 1.0F, 0.0F, 0.0F);
GL11.glRotatef(45.0F, 0.0F, 1.0F, 0.0F);
}
else if (Item.itemsList[itemstack.itemID].isFull3D())
{
f2 = 0.625F;
if (Item.itemsList[itemstack.itemID].shouldRotateAroundWhenRendering())
{
GL11.glRotatef(180.0F, 0.0F, 0.0F, 1.0F);
GL11.glTranslatef(0.0F, -0.125F, 0.0F);
}
this.func_82422_c();
GL11.glScalef(f2, -f2, f2);
GL11.glRotatef(-100.0F, 1.0F, 0.0F, 0.0F);
GL11.glRotatef(45.0F, 0.0F, 1.0F, 0.0F);
}
else
{
f2 = 0.375F;
GL11.glTranslatef(0.25F, 0.1875F, -0.1875F);
GL11.glScalef(f2, f2, f2);
GL11.glRotatef(60.0F, 0.0F, 0.0F, 1.0F);
GL11.glRotatef(-90.0F, 1.0F, 0.0F, 0.0F);
GL11.glRotatef(20.0F, 0.0F, 0.0F, 1.0F);
}
this.renderManager.itemRenderer.renderItem(par1EntityLiving, itemstack, 0);
if (itemstack.getItem().requiresMultipleRenderPasses())
{
for (int x = 1; x < itemstack.getItem().getRenderPasses(itemstack.getItemDamage()); x++)
{
this.renderManager.itemRenderer.renderItem(par1EntityLiving, itemstack, x);
}
}
GL11.glPopMatrix();
}
}
protected void func_82422_c()
{
GL11.glTranslatef(0.0F, 0.1875F, 0.0F);
}
protected void func_82439_b(EntityLivingBase par1EntityLivingBase, int par2, float par3)
{
this.func_130013_c((EntityZeus)par1EntityLivingBase, par2, par3);
}
/**
* Queries whether should render the specified pass or not.
*/
protected int shouldRenderPass(EntityLivingBase par1EntityLivingBase, int par2, float par3)
{
return this.func_130006_a((EntityZeus)par1EntityLivingBase, par2, par3);
}
protected void renderEquippedItems(EntityLivingBase par1EntityLivingBase, float par2)
{
this.func_130005_c((EntityZeus)par1EntityLivingBase, par2);
}
public void renderPlayer(EntityLivingBase par1EntityLivingBase, double par2, double par4, double par6, float par8, float par9)
{
this.doRenderLiving((EntityZeus)par1EntityLivingBase, par2, par4, par6, par8, par9);
}
protected ResourceLocation func_110775_a(Entity par1Entity)
{
return skin;
}
/**
* Actually renders the given argument. This is a synthetic bridge method, always casting down its argument and then
* handing it off to a worker function which does the actual work. In all probabilty, the class Render is generic
* (Render<T extends Entity) and this method has signature public void doRender(T entity, double d, double d1,
* double d2, float f, float f1). But JAD is pre 1.5 so doesn't do that.
*/
public void doRender(Entity par1Entity, double par2, double par4, double par6, float par8, float par9)
{
this.doRenderLiving((EntityZeus)par1Entity, par2, par4, par6, par8, par9);
}
}
Alright, now we have the important notes: texture: Up at the beginning of the class you probably see something like this:
private static final ResourceLocation skin = new ResourceLocation("zeuscraft", "textures/entities/olympus/zeus.png");
This is why we have a separate Render file for each mob/entity. It used to be to where textures were specified somewhere else, to where you could use the same render file multiple times for different mobs, but now the render files contain the textures. So, according to this, my texture file would be in:
zeus.png (the texture file), should be in the same format as if you were applying a skin to your in-game player, due to the fact that we are using the same model. So what you can do, is you could even go to PMC and download a quality-made skin to use and title that zeus.png, instead of trying to make your own! Don't forget to give credits to the original author if you do.
Now, we go to the entity file. In this file, we'll create the AI for our mob, so here we can make it do what we want to and act a certain way, whether its as cowardly as a pig, as fun to ride as a horse, or make it flying and beastly as a ender dragon. Simply put, this is where the magic happens, and this is why I like mobs so much. However, today, we'll just be creating a basic AI.
Now a little lot of explanation: this.setSize(1.0F, 1.75F); - this sets the hitbox for the entity. Normally, you would simply put 1.0F, 1.0F, but I found that the hitbox was a little messed up height-wise by default, therefore, I experimented with it until I got 1.75, which seems to work pretty solid. It goes (WIDTH, HEIGHT), just as you would do if I was plotting coordinates on a 2d plane, (X, Y).
this.getNavigator().setAvoidsWater(true); - Do you want your entity to prefer not to walk on water when it's wandering around? Most land mobs have this as true, especially if they can't swim because you didn't add in the next line:
Before I continue, a quick explanation of AI: It used to be to where you had to hard code stuff into each entity class using stuff like onLivingUpdate(), onUpdate(), and methods like that. Now, with the introduction of AI, you can simply list actions in the order of priority in which you want your entity to do them. This doesn't totally avert the situation, as mobs like squids still primarily rely on non-AI kinds of things, but it helps for most of your situations.
As you review the AI section, you'll notice that the first number in the parentheses increases, starting at 0, and then 1, 2, 3, and so on. that's because that gives Minecraft the priorities it is supposed to value each action. To make it simpler, I put swimming as 1st priority, because if our mob is in water, we'd rather it focus on swimming and not sinking, rather than looking at the closest player, which is the 3rd priority. (Yes, it is confusing that the 1st priority has a 0 rather than a 1, but deal with it.)
If the first action in the AI is not applicable, so in our case if the mob is on land, then this line will be skipped and we'll move on to the next one, which would be wandering, since it has a 1 after the parentheses, and then once a cycle or two of wandering is over, the mob will look to watch the nearest player. The first priority is always on call though, because if let's say I push a wandering Zeus into the water, it will use the first priority, which is swimming, and then continue down. On the other hand, if I were just to leave it be in-game, then it would look at me for a while, and then go back to the top of the list, skip swimming because it wouldn't be in water since I put in that method before that made it avoid water, and then it would start wandering again. If you're still confused, read this over, then continue reading the rest of the AI, and if you still don't get it, leave a reply on this thread. Now to continue AI:
this.tasks.addTask(0, new EntityAISwimming(this)); - Do you want your mob to be able to swim, or sink to the bottom and eventually die of suffocation? Most of the time, you would want your mob to swim, but say if you have a desert mob, like the Citipati in Paleocraft, it shouldn't know how to swim, since it doesn't have life-threatening deep water in its natural environment. As long as this method is here in the first priority (0 is after the first parentheses), your mob will be sure to swim. If I didn't want my mob to be able to swim, then I would take this method out, but I would have to change the numbers of the following AI to start with 0.
this.tasks.addTask(1, new EntityAIWander(this, 0.5D)); - Your mob will walk around randomly around, like almost all mobs do. 0.5D is the speed. To show you what numbers to speed is like, refer to the moveSpeed line in the upcoming sections
this.tasks.addTask(2, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F)); - This makes it to where your mob will watch the nearest player. EntityPlayer.class specifies what entity to look at, so I could make it EntityChicken.class if I wanted to to make your mob stare at chickens. 6.0F is the distance at which it notices and starts to stare at the player, but you don't really need to worry at this, because heighten it and it might just get kind of weird when you've got mobs staring at you a mile away.
I mean, I guess if you're doing a Herobrine thing it might be more scary, but anyways, onward.
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true)); - It used to be that when you wanted to make a mob neutral (when I say neutral, I don't mean passive or aggressive, but attacks when attacked), you had to go into something like EntityZombiePigman or EntityWolf and use that code to help you, but now with this new AI stuff, we can simply put this method in here, and our mod will become neutral.
You'll also notice that it now says "targetTasks" rather than"tasks" and that the numbering restarts at 1 after the parentheses. Well, that's because targetTasks has directly to do with other mobs/players, so some of the AI in target tasks would be like hostility to players or a specific type of mob, or following an owner if the mob has been tamed. Target tasks are a completely different group of AI, but don't worry, Minecraft is smart enough to know where it all belongs on the grand scheme of priorities for your mob's AI.
func_110148_a(SharedMonsterAttributes.field_111263_d).func_111128_a(0.5); //moveSpeed - Well, I basically explained it for you with that comment. This line adds in the movespeed for the mob. The higher the number goes, the faster, the lower, the slower. Here's a quick reference that I kind of go by:
0.2 to 0.3 = very slow
0.4 = slow
0.5 to 0.6 = normal
0.7 = fast
0.8 to 0.9 = very fast
1.0 = a blur
func_110148_a(SharedMonsterAttributes.field_111267_a).func_111128_a(9); //maxHealth - As the comment says, this sets the max health for the mob. That 9 is what sets it. Now how this works, is that each number is a half a heart, so 8 would mean the mob has 4 hearts of health, 9 means the mob has 4.5 hearts of health, and 10 means 5 hearts of health. As a quick reference, a chicken has 4 (2 hearts), a player has 20 (10 hearts), and and the wither has the most out of any mob in the game, 300 (150 hearts) (enderdragon has 200 = 100 hearts).
func_110148_a(SharedMonsterAttributes.field_111264_e).func_111128_a(10); //attackStrength - This adds, as you might have guessed, adds the mob's damage. Again, it's the "half-heart system" where every number represents another half-heart. So this mob would deal 5 hearts of damage. Refer here for the full guide on damage: http://www.minecraft...net/wiki/Damage (there's a section called "Damage inflicted by mobs")
public EnumCreatureAttribute getCreatureAttribute()
{
return EnumCreatureAttribute.UNDEAD;
}
I totally forgot what this does at the moment, hence it is unimportant, but I'll edit this later to tell you what it is, but you can keep it at UNDEAD. It's something to do with the way the mob reacts to potions.
protected boolean isAIEnabled()
{
return true;
}
This enables the AI that we talked about before. If you turn it to false, or do not include this, you will not have any AI. Contrary to what you might expect, we do not always use this for more advanced AI, so we won't ALWAYS have this, but we certainly will for now.
protected boolean canDespawn()
{
return false;
}
I just included this in this tutorial. It could be it's own tutorial, since it isn't 100% necessary, but I figured it's so small, why not? So if I turn this to true, as is with most creatures, then after some time, my mob will despawn. Otherwise, if I have an important mob, such as Zeus, where you're constantly interacting with him and doing quests (not in this tutorial), I don't want him to disappear into thin air, so I would set this to return false; and he will never despawn.
NOTE: DO NOT SET THIS TO FALSE ON MOBS THAT DON'T NEED IT. MORE MOBS NEVER GOING AWAY = MORE COMPUTER POWER NEEDED = SLOWER GAME. IF YOU ARE SELFISH AND IGNORE THIS WARNING, I WILL MENTALLY SLAP YOU ACROSS THE FACE , AND YOUR MOD WILL UNNECESSARILY SLOW DOWN PEOPLE'S GAMES, MAKING IT LESS POPULAR.
Now that we got that out of the way, let's move on to registering it in our main class.
Zeuscraft.java:
package fisherman77.zeuscraft.common; //The package your mod is in
import net.minecraft.block.Block;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityEggInfo;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.item.Item;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraftforge.common.MinecraftForge;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.Init;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.Mod.PreInit;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkMod;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.registry.EntityRegistry;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.LanguageRegistry;
import cpw.mods.fml.common.network.NetworkMod.SidedPacketHandler;
import cpw.mods.fml.common.SidedProxy;
import fisherman77.zeuscraft.common.mobs.olympus.EntityZeus;
//need to import render class too. already deleted it up here for organization -- woops
@NetworkMod(clientSideRequired=true,serverSideRequired=true, //Whether client side and server side are needed
clientPacketHandlerSpec = @SidedPacketHandler(channels = {"Zeuscraft"}, packetHandler = ZeuscraftClientPacketHandler.class), //For clientside packet handling
serverPacketHandlerSpec = @SidedPacketHandler(channels = {"Zeuscraft"}, packetHandler = ZeuscraftServerPacketHandler.class)) //For serverside packet handling
//MOD BASICS
@Mod(modid="Zeuscraft",name="Zeuscraft",version="Dev Build")
public class Zeuscraft {
@Instance("Zeuscraft") //The instance, this is very important later on
public static Zeuscraft instance = new Zeuscraft();
@SidedProxy(clientSide = "fisherman77.zeuscraft.client.ZeuscraftClientProxy", serverSide = "fisherman77.zeuscraft.common.ZeuscraftCommonProxy") //Tells Forge the location of your proxies
public static ZeuscraftCommonProxy proxy;
@PreInit
public void PreInit(FMLPreInitializationEvent e){
}
@Init
public void InitZeuscraft(FMLInitializationEvent event){ //Your main initialization method
//MOBS
proxy.registerRenderers();
//NPCs
//Zeus
registerEntity(EntityZeus.class, "Zeus", 0xeaeae9, 0xc99a03);
LanguageRegistry.instance().addStringLocalization("entity.Zeus.name", "Zeus");
//MULTIPLAYER ABILITY
NetworkRegistry.instance().registerGuiHandler(this, proxy); //Registers the class that deals with GUI data
}
public void registerEntity(Class<? extends Entity> entityClass, String entityName, int bkEggColor, int fgEggColor) {
int id = EntityRegistry.findGlobalUniqueEntityId();
EntityRegistry.registerGlobalEntityID(entityClass, entityName, id);
EntityList.entityEggs.put(Integer.valueOf(id), new EntityEggInfo(id, bkEggColor, fgEggColor));
}
public void addSpawn(Class<? extends EntityLiving> entityClass, int spawnProb, int min, int max, BiomeGenBase[] biomes) {
if (spawnProb > 0) {
EntityRegistry.addSpawn(entityClass, spawnProb, min, max, EnumCreatureType.creature, biomes);
}
}
}
Now to explain the two lines of code that really matter for this: registerEntity(EntityZeus.class, "Zeus", 0xabcde9, 0xe98a03); - EntityZeus.class specifies the entity file that we're using, and if you've been following along, you should have to import it since it's from another package. The 0x... stuff is the colors for the eggs. They are HTML color codes. A good reference: http://www.w3schools...colorpicker.asp Just pick your color, and copy the 6 digit/letter code after the 0x. It does NOT have to be all uppercase. "Zeus" is the name that Minecraft will use as the mob's default name, which when it's all done comes out to be "entity.Zeus.name".
LanguageRegistry.instance().addStringLocalization("entity.Zeus.name", "Zeus"); - We don't want it to be called "entity.Zeus.name" in Minecraft, so we use LanguageRegistry to replace that with simply "Zeus".
Last file:
ZeuscraftClientProxy.java:
package fisherman77.zeuscraft.client;
import cpw.mods.fml.client.registry.RenderingRegistry;
import fisherman77.zeuscraft.common.mobs.olympus.EntityZeus;
import fisherman77.zeuscraft.common.mobs.olympus.RenderZeus;
import net.minecraft.client.model.ModelBiped;
import net.minecraftforge.client.MinecraftForgeClient;
public class ZeuscraftClientProxy extends ZeuscraftCommonProxy {
public void registerRenderInformation(){
}
public void registerRenderers(){
float shadowSize = 0.5F;
//MOBS
RenderingRegistry.registerEntityRenderingHandler(EntityZeus.class, new RenderZeus(new ModelBiped(), shadowSize));
}
}
This ties everything all together. You'll have to import the classes into this class, as you can see that I've done at the very top. Now we tie together the AI (entity file -- EntityZeus.java), rendering/texture (render file -- RenderZeus.java), and the model (model file -- ModelBiped, which is already in the game, so we didn't have to do).
Lastly, we have the shadowSize. as you can see above this line that it's a variable with the value 0.5F. The shadow is that gray circle that appears underneath mobs in-game that you've probably never noticed. I just do 0.5F for all my mobs that are normal-sized.
And that's it. Now, before we launch it up, make sure that you have your textures in the eclipse/Minecaft/bin folder that I detailed earlier. Now, simply fire up the game and go to the creative menu. Search "spawn zeus" or go to the spawn eggs in the tab with all blocks and items. Now right click, and you should see your mob in-game. Have fun. The even better news - this is just the beginning, there's an unlimited amount of things you can do with mobs!
fisherman, just an FYI for your Linux based MCP set up. You need to make sure the users allow the install.sh, install.py and forge.py are executable as a program. Then make sure they open terminal, navigate to the folder and type ./install.sh without being root. It has to be that way or it will NOT work properly.
Awesome mob tut! Maybe now I can finally change from "extend vanilla mob and change it" style coding What a shame about the way they changed Render to use ResourceLocation instead of an external variable. I was thinking, however, that since you always have access to the EntityLivingBase to be rendered, couldn't you just create a ResourceLocation variable within your entity class and access it from the Render, like you did there with Armor?
Hi! I'm currently developing a Dead Space mod and I need coding help, because right now I'm the only coder of my mod and I haven't done ANY progress to tge mod since I updated it to 1.6.2. I really want to get more into modeling and texturing, but I can't do that, because I have to code everything and I'm not a java programmer (not even a close). I just know the basics of java coding. I really want to update the mod soon, so if anyone would like to help me, just PM to MCForums or YouTube account. Thanks!
btw, I'm not asking to do everything, just the parts I don't know how to do! I'm sure you guys want a smooth, lag and crash free mod!
Sorry, kind of bogged down right now with Paleocraft and Zeuscraft, but I'll be posting more mob tutorials now
fisherman, just an FYI for your Linux based MCP set up. You need to make sure the users allow the install.sh, install.py and forge.py are executable as a program. Then make sure they open terminal, navigate to the folder and type ./install.sh without being root. It has to be that way or it will NOT work properly.
Thank you. I'm on Mac 99% of the time, and have a really crappy PC desktop, so I'm kind of blind to Linux.
Awesome mob tut! Maybe now I can finally change from "extend vanilla mob and change it" style coding What a shame about the way they changed Render to use ResourceLocation instead of an external variable. I was thinking, however, that since you always have access to the EntityLivingBase to be rendered, couldn't you just create a ResourceLocation variable within your entity class and access it from the Render, like you did there with Armor?
You can certainly try that! Let me know how it goes.
Thank you so much. I'm doing a fairly ambitious mod as my first mod and a mob was the last thing I needed to figure out. No one was showing the new 1.6 style so it's greatly appreciated.
I got close to finishing my custom villager type, but I wasn't sure how to register it and you answered everything perfectly. I'm really looking forward to seeing more tutorials.
I'm having problems with the textures. I put the assets folder in, but i dont know how the format for showing where it is works...
basically:
i have the images in the asset folder (imbedded in all the nesting folders)
the asset folder is in the bin folder
i put in the right format ("folderNameInAssets:imageName") in the registericon in the item/block
but the images dont show up....
do i have to link part of the assets folder in the package explorer, and if i do, what part and where do i put it?
How Create a 3D item? for Example a Sword, I need add a 3D Sword in my mod, As i do (I need the code, model the swords is very easy), and the code for put the Sword in the hand of Steve, but only if you can, but only the code for the sword to add...
BTW Its pretty long be careful if you press 'show'
[ForgeModLoader] An error occured trying to load a proxy into {clientSide=fisherman77.zeuscraft.client.ZeuscraftClientProxy, serverSide=fisherman77.zeuscraft.common.ZeuscraftCommonProxy}.liam.myths.Myths
java.lang.ClassNotFoundException: fisherman77.zeuscraft.client.ZeuscraftClientProxy
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:179)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at cpw.mods.fml.common.ModClassLoader.loadClass(ModClassLoader.java:58)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at cpw.mods.fml.common.ProxyInjector.inject(ProxyInjector.java:58)
at cpw.mods.fml.common.FMLModContainer.constructMod(FMLModContainer.java:519)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
at com.google.common.eventbus.EventBus.post(EventBus.java:267)
at cpw.mods.fml.common.LoadController.sendEventToModContainer(LoadController.java:194)
at cpw.mods.fml.common.LoadController.propogateStateMessage(LoadController.java:174)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
at com.google.common.eventbus.EventBus.post(EventBus.java:267)
at cpw.mods.fml.common.LoadController.distributeStateMessage(LoadController.java:105)
at cpw.mods.fml.common.Loader.loadMods(Loader.java:510)
at cpw.mods.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:182)
at net.minecraft.client.Minecraft.startGame(Minecraft.java:470)
at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:796)
at net.minecraft.client.main.Main.main(Main.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.minecraft.launchwrapper.Launch.launch(Launch.java:57)
at net.minecraft.launchwrapper.Launch.main(Launch.java:18)
Caused by: java.lang.NullPointerException
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:171)
... 39 more
2013-09-25 19:32:39 [SEVERE] [ForgeModLoader] Fatal errors were detected during the transition from CONSTRUCTING to PREINITIALIZATION. Loading cannot continue
2013-09-25 19:32:39 [SEVERE] [ForgeModLoader]
mcp{8.04} [Minecraft Coder Pack] (minecraft.jar) Unloaded->Constructed
FML{6.2.35.804} [Forge Mod Loader] (coremods) Unloaded->Constructed
Forge{9.10.0.804} [Minecraft Forge] (coremods) Unloaded->Constructed
Zeuscraft{Dev Build} [Zeuscraft] (bin) Unloaded->Errored
2013-09-25 19:32:39 [SEVERE] [ForgeModLoader] The following problems were captured during this phase
2013-09-25 19:32:39 [SEVERE] [ForgeModLoader] Caught exception from Zeuscraft
cpw.mods.fml.common.LoaderException: java.lang.ClassNotFoundException: fisherman77.zeuscraft.client.ZeuscraftClientProxy
at cpw.mods.fml.common.ProxyInjector.inject(ProxyInjector.java:75)
at cpw.mods.fml.common.FMLModContainer.constructMod(FMLModContainer.java:519)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
at com.google.common.eventbus.EventBus.post(EventBus.java:267)
at cpw.mods.fml.common.LoadController.sendEventToModContainer(LoadController.java:194)
at cpw.mods.fml.common.LoadController.propogateStateMessage(LoadController.java:174)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
at com.google.common.eventbus.EventBus.post(EventBus.java:267)
at cpw.mods.fml.common.LoadController.distributeStateMessage(LoadController.java:105)
at cpw.mods.fml.common.Loader.loadMods(Loader.java:510)
at cpw.mods.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:182)
at net.minecraft.client.Minecraft.startGame(Minecraft.java:470)
at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:796)
at net.minecraft.client.main.Main.main(Main.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.minecraft.launchwrapper.Launch.launch(Launch.java:57)
at net.minecraft.launchwrapper.Launch.main(Launch.java:18)
Caused by: java.lang.ClassNotFoundException: fisherman77.zeuscraft.client.ZeuscraftClientProxy
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:179)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at cpw.mods.fml.common.ModClassLoader.loadClass(ModClassLoader.java:58)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at cpw.mods.fml.common.ProxyInjector.inject(ProxyInjector.java:58)
... 33 more
Caused by: java.lang.NullPointerException
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:171)
... 39 more
2013-09-25 19:32:39 [INFO] [STDOUT] ---- Minecraft Crash Report ----
2013-09-25 19:32:39 [INFO] [STDOUT] // On the bright side, I bought you a teddy bear!
2013-09-25 19:32:39 [INFO] [STDOUT]
2013-09-25 19:32:39 [INFO] [STDOUT] Time: 9/25/13 7:32 PM
2013-09-25 19:32:39 [INFO] [STDOUT] Description: There was a severe problem during mod loading that has caused the game to fail
2013-09-25 19:32:39 [INFO] [STDOUT]
2013-09-25 19:32:39 [INFO] [STDOUT] cpw.mods.fml.common.LoaderException: java.lang.ClassNotFoundException: fisherman77.zeuscraft.client.ZeuscraftClientProxy
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.ProxyInjector.inject(ProxyInjector.java:75)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.FMLModContainer.constructMod(FMLModContainer.java:519)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at java.lang.reflect.Method.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventBus.post(EventBus.java:267)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.LoadController.sendEventToModContainer(LoadController.java:194)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.LoadController.propogateStateMessage(LoadController.java:174)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at java.lang.reflect.Method.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventBus.post(EventBus.java:267)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.LoadController.distributeStateMessage(LoadController.java:105)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.Loader.loadMods(Loader.java:510)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:182)
2013-09-25 19:32:39 [INFO] [STDOUT] at net.minecraft.client.Minecraft.startGame(Minecraft.java:470)
2013-09-25 19:32:39 [INFO] [STDOUT] at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:796)
2013-09-25 19:32:39 [INFO] [STDOUT] at net.minecraft.client.main.Main.main(Main.java:93)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at java.lang.reflect.Method.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at net.minecraft.launchwrapper.Launch.launch(Launch.java:57)
2013-09-25 19:32:39 [INFO] [STDOUT] at net.minecraft.launchwrapper.Launch.main(Launch.java:18)
2013-09-25 19:32:39 [INFO] [STDOUT] Caused by: java.lang.ClassNotFoundException: fisherman77.zeuscraft.client.ZeuscraftClientProxy
2013-09-25 19:32:39 [INFO] [STDOUT] at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:179)
2013-09-25 19:32:39 [INFO] [STDOUT] at java.lang.ClassLoader.loadClass(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at java.lang.ClassLoader.loadClass(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.ModClassLoader.loadClass(ModClassLoader.java:58)
2013-09-25 19:32:39 [INFO] [STDOUT] at java.lang.Class.forName0(Native Method)
2013-09-25 19:32:39 [INFO] [STDOUT] at java.lang.Class.forName(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.ProxyInjector.inject(ProxyInjector.java:58)
2013-09-25 19:32:39 [INFO] [STDOUT] ... 33 more
2013-09-25 19:32:39 [INFO] [STDOUT] Caused by: java.lang.NullPointerException
2013-09-25 19:32:39 [INFO] [STDOUT] at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:171)
2013-09-25 19:32:39 [INFO] [STDOUT] ... 39 more
2013-09-25 19:32:39 [INFO] [STDOUT]
2013-09-25 19:32:39 [INFO] [STDOUT]
2013-09-25 19:32:39 [INFO] [STDOUT] A detailed walkthrough of the error, its code path and all known details is as follows:
2013-09-25 19:32:39 [INFO] [STDOUT] ---------------------------------------------------------------------------------------
2013-09-25 19:32:39 [INFO] [STDOUT]
2013-09-25 19:32:39 [INFO] [STDOUT] -- System Details --
2013-09-25 19:32:39 [INFO] [STDOUT] Details:
2013-09-25 19:32:39 [INFO] [STDOUT] Minecraft Version: 1.6.2
2013-09-25 19:32:39 [INFO] [STDOUT] Operating System: Windows 7 (amd64) version 6.1
2013-09-25 19:32:39 [INFO] [STDOUT] Java Version: 1.7.0_21, Oracle Corporation
2013-09-25 19:32:39 [INFO] [STDOUT] Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode), Oracle Corporation
2013-09-25 19:32:39 [INFO] [STDOUT] Memory: 941485448 bytes (897 MB) / 1056309248 bytes (1007 MB) up to 1056309248 bytes (1007 MB)
2013-09-25 19:32:39 [INFO] [STDOUT] JVM Flags: 3 total; -Xincgc -Xmx1024M -Xms1024M
2013-09-25 19:32:39 [INFO] [STDOUT] AABB Pool Size: 0 (0 bytes; 0 MB) allocated, 0 (0 bytes; 0 MB) used
2013-09-25 19:32:39 [INFO] [STDOUT] Suspicious classes: FML and Forge are installed
2013-09-25 19:32:39 [INFO] [STDOUT] IntCache: cache: 0, tcache: 0, allocated: 0, tallocated: 0
2013-09-25 19:32:39 [INFO] [STDOUT] FML: MCP v8.04 FML v6.2.35.804 Minecraft Forge 9.10.0.804 4 mods loaded, 4 mods active
2013-09-25 19:32:39 [INFO] [STDOUT] mcp{8.04} [Minecraft Coder Pack] (minecraft.jar) Unloaded->Constructed
2013-09-25 19:32:39 [INFO] [STDOUT] FML{6.2.35.804} [Forge Mod Loader] (coremods) Unloaded->Constructed
2013-09-25 19:32:39 [INFO] [STDOUT] Forge{9.10.0.804} [Minecraft Forge] (coremods) Unloaded->Constructed
2013-09-25 19:32:39 [INFO] [STDOUT] Zeuscraft{Dev Build} [Zeuscraft] (bin) Unloaded->Errored
2013-09-25 19:32:39 [INFO] [STDOUT] #@!@# Game crashed! Crash report saved to: #@!@# F:\Minecraft Mods\Test\mcp\jars\.\crash-reports\crash-2013-09-25_19.32.39-client.txt
BTW Its pretty long be careful if you press 'show'
[ForgeModLoader] An error occured trying to load a proxy into {clientSide=fisherman77.zeuscraft.client.ZeuscraftClientProxy, serverSide=fisherman77.zeuscraft.common.ZeuscraftCommonProxy}.liam.myths.Myths
java.lang.ClassNotFoundException: fisherman77.zeuscraft.client.ZeuscraftClientProxy
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:179)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at cpw.mods.fml.common.ModClassLoader.loadClass(ModClassLoader.java:58)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at cpw.mods.fml.common.ProxyInjector.inject(ProxyInjector.java:58)
at cpw.mods.fml.common.FMLModContainer.constructMod(FMLModContainer.java:519)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
at com.google.common.eventbus.EventBus.post(EventBus.java:267)
at cpw.mods.fml.common.LoadController.sendEventToModContainer(LoadController.java:194)
at cpw.mods.fml.common.LoadController.propogateStateMessage(LoadController.java:174)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
at com.google.common.eventbus.EventBus.post(EventBus.java:267)
at cpw.mods.fml.common.LoadController.distributeStateMessage(LoadController.java:105)
at cpw.mods.fml.common.Loader.loadMods(Loader.java:510)
at cpw.mods.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:182)
at net.minecraft.client.Minecraft.startGame(Minecraft.java:470)
at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:796)
at net.minecraft.client.main.Main.main(Main.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.minecraft.launchwrapper.Launch.launch(Launch.java:57)
at net.minecraft.launchwrapper.Launch.main(Launch.java:18)
Caused by: java.lang.NullPointerException
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:171)
... 39 more
2013-09-25 19:32:39 [SEVERE] [ForgeModLoader] Fatal errors were detected during the transition from CONSTRUCTING to PREINITIALIZATION. Loading cannot continue
2013-09-25 19:32:39 [SEVERE] [ForgeModLoader]
mcp{8.04} [Minecraft Coder Pack] (minecraft.jar) Unloaded->Constructed
FML{6.2.35.804} [Forge Mod Loader] (coremods) Unloaded->Constructed
Forge{9.10.0.804} [Minecraft Forge] (coremods) Unloaded->Constructed
Zeuscraft{Dev Build} [Zeuscraft] (bin) Unloaded->Errored
2013-09-25 19:32:39 [SEVERE] [ForgeModLoader] The following problems were captured during this phase
2013-09-25 19:32:39 [SEVERE] [ForgeModLoader] Caught exception from Zeuscraft
cpw.mods.fml.common.LoaderException: java.lang.ClassNotFoundException: fisherman77.zeuscraft.client.ZeuscraftClientProxy
at cpw.mods.fml.common.ProxyInjector.inject(ProxyInjector.java:75)
at cpw.mods.fml.common.FMLModContainer.constructMod(FMLModContainer.java:519)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
at com.google.common.eventbus.EventBus.post(EventBus.java:267)
at cpw.mods.fml.common.LoadController.sendEventToModContainer(LoadController.java:194)
at cpw.mods.fml.common.LoadController.propogateStateMessage(LoadController.java:174)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
at com.google.common.eventbus.EventBus.post(EventBus.java:267)
at cpw.mods.fml.common.LoadController.distributeStateMessage(LoadController.java:105)
at cpw.mods.fml.common.Loader.loadMods(Loader.java:510)
at cpw.mods.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:182)
at net.minecraft.client.Minecraft.startGame(Minecraft.java:470)
at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:796)
at net.minecraft.client.main.Main.main(Main.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.minecraft.launchwrapper.Launch.launch(Launch.java:57)
at net.minecraft.launchwrapper.Launch.main(Launch.java:18)
Caused by: java.lang.ClassNotFoundException: fisherman77.zeuscraft.client.ZeuscraftClientProxy
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:179)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at cpw.mods.fml.common.ModClassLoader.loadClass(ModClassLoader.java:58)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at cpw.mods.fml.common.ProxyInjector.inject(ProxyInjector.java:58)
... 33 more
Caused by: java.lang.NullPointerException
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:171)
... 39 more
2013-09-25 19:32:39 [INFO] [STDOUT] ---- Minecraft Crash Report ----
2013-09-25 19:32:39 [INFO] [STDOUT] // On the bright side, I bought you a teddy bear!
2013-09-25 19:32:39 [INFO] [STDOUT]
2013-09-25 19:32:39 [INFO] [STDOUT] Time: 9/25/13 7:32 PM
2013-09-25 19:32:39 [INFO] [STDOUT] Description: There was a severe problem during mod loading that has caused the game to fail
2013-09-25 19:32:39 [INFO] [STDOUT]
2013-09-25 19:32:39 [INFO] [STDOUT] cpw.mods.fml.common.LoaderException: java.lang.ClassNotFoundException: fisherman77.zeuscraft.client.ZeuscraftClientProxy
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.ProxyInjector.inject(ProxyInjector.java:75)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.FMLModContainer.constructMod(FMLModContainer.java:519)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at java.lang.reflect.Method.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventBus.post(EventBus.java:267)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.LoadController.sendEventToModContainer(LoadController.java:194)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.LoadController.propogateStateMessage(LoadController.java:174)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at java.lang.reflect.Method.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
2013-09-25 19:32:39 [INFO] [STDOUT] at com.google.common.eventbus.EventBus.post(EventBus.java:267)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.LoadController.distributeStateMessage(LoadController.java:105)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.Loader.loadMods(Loader.java:510)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:182)
2013-09-25 19:32:39 [INFO] [STDOUT] at net.minecraft.client.Minecraft.startGame(Minecraft.java:470)
2013-09-25 19:32:39 [INFO] [STDOUT] at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:796)
2013-09-25 19:32:39 [INFO] [STDOUT] at net.minecraft.client.main.Main.main(Main.java:93)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at java.lang.reflect.Method.invoke(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at net.minecraft.launchwrapper.Launch.launch(Launch.java:57)
2013-09-25 19:32:39 [INFO] [STDOUT] at net.minecraft.launchwrapper.Launch.main(Launch.java:18)
2013-09-25 19:32:39 [INFO] [STDOUT] Caused by: java.lang.ClassNotFoundException: fisherman77.zeuscraft.client.ZeuscraftClientProxy
2013-09-25 19:32:39 [INFO] [STDOUT] at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:179)
2013-09-25 19:32:39 [INFO] [STDOUT] at java.lang.ClassLoader.loadClass(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at java.lang.ClassLoader.loadClass(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.ModClassLoader.loadClass(ModClassLoader.java:58)
2013-09-25 19:32:39 [INFO] [STDOUT] at java.lang.Class.forName0(Native Method)
2013-09-25 19:32:39 [INFO] [STDOUT] at java.lang.Class.forName(Unknown Source)
2013-09-25 19:32:39 [INFO] [STDOUT] at cpw.mods.fml.common.ProxyInjector.inject(ProxyInjector.java:58)
2013-09-25 19:32:39 [INFO] [STDOUT] ... 33 more
2013-09-25 19:32:39 [INFO] [STDOUT] Caused by: java.lang.NullPointerException
2013-09-25 19:32:39 [INFO] [STDOUT] at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:171)
2013-09-25 19:32:39 [INFO] [STDOUT] ... 39 more
2013-09-25 19:32:39 [INFO] [STDOUT]
2013-09-25 19:32:39 [INFO] [STDOUT]
2013-09-25 19:32:39 [INFO] [STDOUT] A detailed walkthrough of the error, its code path and all known details is as follows:
2013-09-25 19:32:39 [INFO] [STDOUT] ---------------------------------------------------------------------------------------
2013-09-25 19:32:39 [INFO] [STDOUT]
2013-09-25 19:32:39 [INFO] [STDOUT] -- System Details --
2013-09-25 19:32:39 [INFO] [STDOUT] Details:
2013-09-25 19:32:39 [INFO] [STDOUT] Minecraft Version: 1.6.2
2013-09-25 19:32:39 [INFO] [STDOUT] Operating System: Windows 7 (amd64) version 6.1
2013-09-25 19:32:39 [INFO] [STDOUT] Java Version: 1.7.0_21, Oracle Corporation
2013-09-25 19:32:39 [INFO] [STDOUT] Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode), Oracle Corporation
2013-09-25 19:32:39 [INFO] [STDOUT] Memory: 941485448 bytes (897 MB) / 1056309248 bytes (1007 MB) up to 1056309248 bytes (1007 MB)
2013-09-25 19:32:39 [INFO] [STDOUT] JVM Flags: 3 total; -Xincgc -Xmx1024M -Xms1024M
2013-09-25 19:32:39 [INFO] [STDOUT] AABB Pool Size: 0 (0 bytes; 0 MB) allocated, 0 (0 bytes; 0 MB) used
2013-09-25 19:32:39 [INFO] [STDOUT] Suspicious classes: FML and Forge are installed
2013-09-25 19:32:39 [INFO] [STDOUT] IntCache: cache: 0, tcache: 0, allocated: 0, tallocated: 0
2013-09-25 19:32:39 [INFO] [STDOUT] FML: MCP v8.04 FML v6.2.35.804 Minecraft Forge 9.10.0.804 4 mods loaded, 4 mods active
2013-09-25 19:32:39 [INFO] [STDOUT] mcp{8.04} [Minecraft Coder Pack] (minecraft.jar) Unloaded->Constructed
2013-09-25 19:32:39 [INFO] [STDOUT] FML{6.2.35.804} [Forge Mod Loader] (coremods) Unloaded->Constructed
2013-09-25 19:32:39 [INFO] [STDOUT] Forge{9.10.0.804} [Minecraft Forge] (coremods) Unloaded->Constructed
2013-09-25 19:32:39 [INFO] [STDOUT] Zeuscraft{Dev Build} [Zeuscraft] (bin) Unloaded->Errored
2013-09-25 19:32:39 [INFO] [STDOUT] #@!@# Game crashed! Crash report saved to: #@!@# F:\Minecraft Mods\Test\mcp\jars\.\crash-reports\crash-2013-09-25_19.32.39-client.txt
Well, you've got to make your own proxy class and fill that in there. ZeuscraftClientProxy.java and ZeuscraftCommonProxy.java are two classes that you do not have.
I don't think I'm gonna call this an "NPC" since it isn't a biped/humanoid, and that's what I think of when I think of NPCs, but even though it's called a "Mob", it's basically just the same thing as the last tutorial, it's just that now we've got a custom Techne Model file (yay! not.) on our hands to deal with. I'll be using my Paleocraft model as an example for this.
Creating a Mob with a Custom Model
So, I'll be skipping the Entity and main mod implementation file in this tutorial, why?
You can use the same one from a Biped NPC tutorial for this tutorial
That would take up a lot of time and space that isn't necessary
We're focusing on importing our custom Techne models into the game!
So we begin with a brand new file in our fisherman77.tutorialmod.mobs package, or whatever you have called it, for me it'll be fisherman77.paleocraft.mobs. Create a new file titled, ModelMasso (change "Masso" to whatever your mob is called).
Now here's the fun part. You've gotta export your model out of Techne! I mod on a Mac, and Techne unfortunately is not yet cross-platform compatible, but I believe you go File>Export>Export as Java File or something like that. Now save the java file, open it up in Eclipse, TextWrangler, Xcode, or some other simple code-viewer application, and then copy and paste all of that code into your Model----.java file in Eclipse.
Yes. You will get errors. Fortunately, Eclipse is so smart that it has solutions ready to go. The first one will probably be the package declaration. Techne hasn't been updated in a while (I don't think) and so is still back in the ModLoader days when we used to put all our stuff in the net.minecraft.src package, but now we're in Forge, so mouse over that error and fix it by clicking that option to change your package declaration to whatever the package in which your class is in. Next, we've gotta import a bunch of stuff, but this can also be done by hovering over the red-underlined errors with your mouse and then clicking the "Import ..." option. If I remember correctly, you'll have to import ModelRenderer.java and Entity.java, and maybe something else. Now there will be an error with the setRotationAngles method. hover over that error and click the first fix. We'll work on animations in another tutorial.
Now here's the last thing to look for. Occasionally, Techne makes hiccups in its exporting and you the modder have to fix them. If you respond with errors due to your inability to see this (which happens with most complex models), then I will respond with a link to this tutorial and a nicely put "READ!!!", so pay attention now.
You should see something along these lines repeated over and over again for each part of your model in you model file:
This is gonna give you errors due to the fact that your asking Minecraft not to mirror the texture for TailBase before it's even declared as what TailBase exactly is. So, simply delete the first line and the last line in this little snippet above (the parts that have "TailBase.mirror = false;"). If you experience problems with texture mirroring later on, you can fiddle with the one line that's left that says "TailBase.mirror = true;" and try changing that to false.
You're gonna need to change the EntityMasso files to whatever the name of your entity class is, but it should be pretty self-explanatory.
Lastly, in PaleocraftClientProxy, same as the Basic NPC tutorial, but you'll have to change the render and model files, so that the line looks more like this:
RenderingRegistry.registerEntityRenderingHandler(EntityMasso.class, new RenderMasso(new ModelMassospondylus(), shadowSize));
Thanks so much for these tutorials! I quit on a mod when they updated to 1.6 and everything went screwy, but I think you're info is gonna help me pick it back up. Thanks, man!
Well, your code looks pretty solid. I'm dumbfounded. I might even try to import this mod into my own workspace to work with it.
Try removing this line in your Common Proxy (just for testing purposes):
If the sword gets its name back, then the problem is with the hoe. If the sword still has "hoe" in-game, then the problem must be with the sword.
When i take away the
All the tool's name will become CopperShovel, I think the problem is in the common proxy, but i cant solve it.
Creating a Biped NPC
So I do this backwards from most people - we're going to start off by creating a render file. Now, render files usually are not that long for normal mobs, but for NPCs and players, we have to render stuff like their held item, their armor, etc., so it's going to be much longer than normal. So here is our first file, we're going to put it in a new package called fisherman77.zeuscraft.mobs.
Optionally, if you know that you're going to have a ton of mobs, you can put all the render files in a separate package like fisherman77.zeuscraft.client.render, or you could group the entity (AI) files and render files in groups like in my case putting the immortals from Greek mythology in fisherman77.zeuscraft.olympians -- whatever works for you.
RenderZeus.java:
Alright, now we have the important notes:
texture: Up at the beginning of the class you probably see something like this:
This is why we have a separate Render file for each mob/entity. It used to be to where textures were specified somewhere else, to where you could use the same render file multiple times for different mobs, but now the render files contain the textures. So, according to this, my texture file would be in:
"Forge [MC Version]/forge/mcp/eclipse/Minecraft/bin/assets/zeuscraft/textures/entities/olympus/zeus.png"
zeus.png (the texture file), should be in the same format as if you were applying a skin to your in-game player, due to the fact that we are using the same model. So what you can do, is you could even go to PMC and download a quality-made skin to use and title that zeus.png, instead of trying to make your own! Don't forget to give credits to the original author if you do.
Now, we go to the entity file. In this file, we'll create the AI for our mob, so here we can make it do what we want to and act a certain way, whether its as cowardly as a pig, as fun to ride as a horse, or make it flying and beastly as a ender dragon. Simply put, this is where the magic happens, and this is why I like mobs so much. However, today, we'll just be creating a basic AI.
EntityZeus.java:
Now a
littlelot of explanation:this.setSize(1.0F, 1.75F); - this sets the hitbox for the entity. Normally, you would simply put 1.0F, 1.0F, but I found that the hitbox was a little messed up height-wise by default, therefore, I experimented with it until I got 1.75, which seems to work pretty solid. It goes (WIDTH, HEIGHT), just as you would do if I was plotting coordinates on a 2d plane, (X, Y).
this.getNavigator().setAvoidsWater(true); - Do you want your entity to prefer not to walk on water when it's wandering around? Most land mobs have this as true, especially if they can't swim because you didn't add in the next line:
Before I continue, a quick explanation of AI: It used to be to where you had to hard code stuff into each entity class using stuff like onLivingUpdate(), onUpdate(), and methods like that. Now, with the introduction of AI, you can simply list actions in the order of priority in which you want your entity to do them. This doesn't totally avert the situation, as mobs like squids still primarily rely on non-AI kinds of things, but it helps for most of your situations.
As you review the AI section, you'll notice that the first number in the parentheses increases, starting at 0, and then 1, 2, 3, and so on. that's because that gives Minecraft the priorities it is supposed to value each action. To make it simpler, I put swimming as 1st priority, because if our mob is in water, we'd rather it focus on swimming and not sinking, rather than looking at the closest player, which is the 3rd priority. (Yes, it is confusing that the 1st priority has a 0 rather than a 1, but deal with it.)
If the first action in the AI is not applicable, so in our case if the mob is on land, then this line will be skipped and we'll move on to the next one, which would be wandering, since it has a 1 after the parentheses, and then once a cycle or two of wandering is over, the mob will look to watch the nearest player. The first priority is always on call though, because if let's say I push a wandering Zeus into the water, it will use the first priority, which is swimming, and then continue down. On the other hand, if I were just to leave it be in-game, then it would look at me for a while, and then go back to the top of the list, skip swimming because it wouldn't be in water since I put in that method before that made it avoid water, and then it would start wandering again. If you're still confused, read this over, then continue reading the rest of the AI, and if you still don't get it, leave a reply on this thread. Now to continue AI:
this.tasks.addTask(0, new EntityAISwimming(this)); - Do you want your mob to be able to swim, or sink to the bottom and eventually die of suffocation? Most of the time, you would want your mob to swim, but say if you have a desert mob, like the Citipati in Paleocraft, it shouldn't know how to swim, since it doesn't have life-threatening deep water in its natural environment. As long as this method is here in the first priority (0 is after the first parentheses), your mob will be sure to swim. If I didn't want my mob to be able to swim, then I would take this method out, but I would have to change the numbers of the following AI to start with 0.
this.tasks.addTask(1, new EntityAIWander(this, 0.5D)); - Your mob will walk around randomly around, like almost all mobs do. 0.5D is the speed. To show you what numbers to speed is like, refer to the moveSpeed line in the upcoming sections
this.tasks.addTask(2, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F)); - This makes it to where your mob will watch the nearest player. EntityPlayer.class specifies what entity to look at, so I could make it EntityChicken.class if I wanted to to make your mob stare at chickens. 6.0F is the distance at which it notices and starts to stare at the player, but you don't really need to worry at this, because heighten it and it might just get kind of weird when you've got mobs staring at you a mile away.
I mean, I guess if you're doing a Herobrine thing it might be more scary, but anyways, onward.
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true)); - It used to be that when you wanted to make a mob neutral (when I say neutral, I don't mean passive or aggressive, but attacks when attacked), you had to go into something like EntityZombiePigman or EntityWolf and use that code to help you, but now with this new AI stuff, we can simply put this method in here, and our mod will become neutral.
You'll also notice that it now says "targetTasks" rather than"tasks" and that the numbering restarts at 1 after the parentheses. Well, that's because targetTasks has directly to do with other mobs/players, so some of the AI in target tasks would be like hostility to players or a specific type of mob, or following an owner if the mob has been tamed. Target tasks are a completely different group of AI, but don't worry, Minecraft is smart enough to know where it all belongs on the grand scheme of priorities for your mob's AI.
func_110148_a(SharedMonsterAttributes.field_111263_d).func_111128_a(0.5); //moveSpeed - Well, I basically explained it for you with that comment. This line adds in the movespeed for the mob. The higher the number goes, the faster, the lower, the slower. Here's a quick reference that I kind of go by:
0.2 to 0.3 = very slow
0.4 = slow
0.5 to 0.6 = normal
0.7 = fast
0.8 to 0.9 = very fast
1.0 = a blur
func_110148_a(SharedMonsterAttributes.field_111267_a).func_111128_a(9); //maxHealth - As the comment says, this sets the max health for the mob. That 9 is what sets it. Now how this works, is that each number is a half a heart, so 8 would mean the mob has 4 hearts of health, 9 means the mob has 4.5 hearts of health, and 10 means 5 hearts of health. As a quick reference, a chicken has 4 (2 hearts), a player has 20 (10 hearts), and and the wither has the most out of any mob in the game, 300 (150 hearts) (enderdragon has 200 = 100 hearts).
For the full guide, go here and scroll down to the Mob Health section (I'm to lazy to get the anchor link): http://www.minecraft...net/wiki/Health
func_110148_a(SharedMonsterAttributes.field_111264_e).func_111128_a(10); //attackStrength - This adds, as you might have guessed, adds the mob's damage. Again, it's the "half-heart system" where every number represents another half-heart. So this mob would deal 5 hearts of damage. Refer here for the full guide on damage: http://www.minecraft...net/wiki/Damage (there's a section called "Damage inflicted by mobs")
public EnumCreatureAttribute getCreatureAttribute()
{
return EnumCreatureAttribute.UNDEAD;
}
I totally forgot what this does at the moment, hence it is unimportant, but I'll edit this later to tell you what it is, but you can keep it at UNDEAD. It's something to do with the way the mob reacts to potions.
protected boolean isAIEnabled()
{
return true;
}
This enables the AI that we talked about before. If you turn it to false, or do not include this, you will not have any AI. Contrary to what you might expect, we do not always use this for more advanced AI, so we won't ALWAYS have this, but we certainly will for now.
protected boolean canDespawn()
{
return false;
}
I just included this in this tutorial. It could be it's own tutorial, since it isn't 100% necessary, but I figured it's so small, why not? So if I turn this to true, as is with most creatures, then after some time, my mob will despawn. Otherwise, if I have an important mob, such as Zeus, where you're constantly interacting with him and doing quests (not in this tutorial), I don't want him to disappear into thin air, so I would set this to return false; and he will never despawn.
NOTE: DO NOT SET THIS TO FALSE ON MOBS THAT DON'T NEED IT. MORE MOBS NEVER GOING AWAY = MORE COMPUTER POWER NEEDED = SLOWER GAME. IF YOU ARE SELFISH AND IGNORE THIS WARNING, I WILL MENTALLY SLAP YOU ACROSS THE FACE , AND YOUR MOD WILL UNNECESSARILY SLOW DOWN PEOPLE'S GAMES, MAKING IT LESS POPULAR.
Now that we got that out of the way, let's move on to registering it in our main class.
Zeuscraft.java:
Now to explain the two lines of code that really matter for this:
registerEntity(EntityZeus.class, "Zeus", 0xabcde9, 0xe98a03); - EntityZeus.class specifies the entity file that we're using, and if you've been following along, you should have to import it since it's from another package. The 0x... stuff is the colors for the eggs. They are HTML color codes. A good reference: http://www.w3schools...colorpicker.asp Just pick your color, and copy the 6 digit/letter code after the 0x. It does NOT have to be all uppercase. "Zeus" is the name that Minecraft will use as the mob's default name, which when it's all done comes out to be "entity.Zeus.name".
LanguageRegistry.instance().addStringLocalization("entity.Zeus.name", "Zeus"); - We don't want it to be called "entity.Zeus.name" in Minecraft, so we use LanguageRegistry to replace that with simply "Zeus".
Last file:
ZeuscraftClientProxy.java:
Lastly, we have the shadowSize. as you can see above this line that it's a variable with the value 0.5F. The shadow is that gray circle that appears underneath mobs in-game that you've probably never noticed. I just do 0.5F for all my mobs that are normal-sized.
And that's it. Now, before we launch it up, make sure that you have your textures in the eclipse/Minecaft/bin folder that I detailed earlier. Now, simply fire up the game and go to the creative menu. Search "spawn zeus" or go to the spawn eggs in the tab with all blocks and items. Now right click, and you should see your mob in-game. Have fun. The even better news - this is just the beginning, there's an unlimited amount of things you can do with mobs!
Error log, and I'll be happy to help
Sorry, kind of bogged down right now with Paleocraft and Zeuscraft, but I'll be posting more mob tutorials now
Thank you. I'm on Mac 99% of the time, and have a really crappy PC desktop, so I'm kind of blind to Linux.
You can certainly try that! Let me know how it goes.
Natural spawning's a different tutorial.
Really needed this. I thought no one really was reading anything. Thank you.
That's coming up pretty soon.
Just import the following to your Zeuscraft.class
Thanks again, keep it up.
basically:
i have the images in the asset folder (imbedded in all the nesting folders)
the asset folder is in the bin folder
i put in the right format ("folderNameInAssets:imageName") in the registericon in the item/block
but the images dont show up....
do i have to link part of the assets folder in the package explorer, and if i do, what part and where do i put it?
Owner of the Decoysoft mod
http://www.minecraftforum.net/forums/mapping-and-modding/minecraft-mods/wip-mods/2488195-decoydragons-mod-wip
2017 Skypro suiter. Owner of Rogue the Dutch AD.
https://twitter.com/MadMareCreation
http://rogueofamegakure.deviantart.com/
http://www.furaffinity.net/user/rogueofamegakure/
I have an error, says that there is no class but I believe as you put your
BTW Its pretty long be careful if you press 'show'
Well, you've got to make your own proxy class and fill that in there. ZeuscraftClientProxy.java and ZeuscraftCommonProxy.java are two classes that you do not have.
Creating a Mob with a Custom Model
So, I'll be skipping the Entity and main mod implementation file in this tutorial, why?
Now here's the fun part. You've gotta export your model out of Techne! I mod on a Mac, and Techne unfortunately is not yet cross-platform compatible, but I believe you go File>Export>Export as Java File or something like that. Now save the java file, open it up in Eclipse, TextWrangler, Xcode, or some other simple code-viewer application, and then copy and paste all of that code into your Model----.java file in Eclipse.
Yes. You will get errors. Fortunately, Eclipse is so smart that it has solutions ready to go. The first one will probably be the package declaration. Techne hasn't been updated in a while (I don't think) and so is still back in the ModLoader days when we used to put all our stuff in the net.minecraft.src package, but now we're in Forge, so mouse over that error and fix it by clicking that option to change your package declaration to whatever the package in which your class is in. Next, we've gotta import a bunch of stuff, but this can also be done by hovering over the red-underlined errors with your mouse and then clicking the "Import ..." option. If I remember correctly, you'll have to import ModelRenderer.java and Entity.java, and maybe something else. Now there will be an error with the setRotationAngles method. hover over that error and click the first fix. We'll work on animations in another tutorial.
Now here's the last thing to look for. Occasionally, Techne makes hiccups in its exporting and you the modder have to fix them. If you respond with errors due to your inability to see this (which happens with most complex models), then I will respond with a link to this tutorial and a nicely put "READ!!!", so pay attention now.
You should see something along these lines repeated over and over again for each part of your model in you model file:
That's the right way it should generate. The problem is when you start seeing this:
This is gonna give you errors due to the fact that your asking Minecraft not to mirror the texture for TailBase before it's even declared as what TailBase exactly is. So, simply delete the first line and the last line in this little snippet above (the parts that have "TailBase.mirror = false;"). If you experience problems with texture mirroring later on, you can fiddle with the one line that's left that says "TailBase.mirror = true;" and try changing that to false.
Now in our render file, RenderMasso:
You're gonna need to change the EntityMasso files to whatever the name of your entity class is, but it should be pretty self-explanatory.
Lastly, in PaleocraftClientProxy, same as the Basic NPC tutorial, but you'll have to change the render and model files, so that the line looks more like this:
That should be it.
I'm also known as TANNAR in some places.