[Creating Mods] Modding tutorials [21/5/11]
#41
Posted 14 December 2010 - 06:04 PM
#42
Posted 14 December 2010 - 10:27 PM
starbuck4619 said:
#43
Posted 14 December 2010 - 10:38 PM
#44
Posted 15 December 2010 - 01:48 PM
In this tutorial I will explain how to create custom block behavior rather than the default behavior. It all basically comes down to overwriting methods in Block.class. This can create blocks which when clicked - exhibit some behavior (see example below), having the block be a redstone power source, explode well... basically anything is possible..
Deployable House Example
So below I am going to provide an example of adding to our Example block class a feature that when the block is clicked it will create a basic house - this allows a simple way of creating a deployable house.
This code will need to be added to the BlockExample class.
public void onBlockClicked(World world, int i, int j, int k, EntityPlayer entityplayer)
{
// Basic Building
int block = Block.wood.blockID;
int size = 5;
for (int i1 = 0; i1 < size; i1++)
{
for (int j1 = 0; j1 < size; j1++)
{
//Walls
// i == ++ k == 0
world.setBlockWithNotify(i+i1,j+j1,k,block);
// i == ++ k == 4
world.setBlockWithNotify(i+i1,j+j1,k+(size-1),block);
// i == 0 k == ++
world.setBlockWithNotify(i,j+j1,k+i1,block);
// i == 4 k == ++
world.setBlockWithNotify(i+(size-1),j+j1,k+i1,block);
//Roof
world.setBlockWithNotify(i+i1,j+(size-1),k+j1,block);
//Floor
world.setBlockWithNotify(i+i1,j,k+j1,block);
}
}
//Door
world.setBlockWithNotify(i+1,j+2,k,0);
world.setBlockWithNotify(i+1,j+1,k,0);
//Windows
int offset = size % 2 == 0 ? (size / 2) - 1 : (size / 2);
world.setBlockWithNotify(i,j+offset,k+offset,Block.glass.blockID);
world.setBlockWithNotify(i+offset,j+offset,k,Block.glass.blockID);
world.setBlockWithNotify(i+(size-1),j+offset,k+offset,Block.glass.blockID);
world.setBlockWithNotify(i+offset,j+offset,k+(size-1),Block.glass.blockID);
//Utilities
world.setBlockWithNotify(i+1,j+1,k+(size-2),Block.crate.blockID);
world.setBlockWithNotify(i+(size-2),j+1,k+1,Block.workbench.blockID);
world.setBlockWithNotify(i+(size-2),j+1,k+(size-2),Block.stoneOvenIdle.blockID);
}
This will produce a house that looks like follows when clicked.

So like the above example you can create custom block behavior by overwriting methods found in the Block class to create some awesome functionality as seen above in the deployable house example.
#45
Posted 15 December 2010 - 01:57 PM
In this tutorial I will explain how to create your own custom NPC. I must warn anyone who attempts this though - it is substantially more complex than adding a new block to the game. So in this example I am going to create a new NPC that is modelled off a cow - a mad cow, this mob will initially be friendly but I will also show you how to make it agressive.
To begin with you need to create the "logic" class, the logic for extended elements to the game is handled under the Entity classes. You can basically add anything to an entity class to achieve custom game behaviour. So lets create an entity class named EntityExample.java to make a new peaceful NPC.
package net.minecraft.src;
public class EntityExample extends EntityAnimals
{
public EntityExample(World world)
{
super(world);
texture = "/mob/example.png";
setSize(0.9F, 1.3F);
}
public void writeEntityToNBT(NBTTagCompound nbttagcompound)
{
super.writeEntityToNBT(nbttagcompound);
}
public void readEntityFromNBT(NBTTagCompound nbttagcompound)
{
super.readEntityFromNBT(nbttagcompound);
}
protected String getLivingSound()
{
return "mob.example";
}
protected String getHurtSound()
{
return "mob.example";
}
protected String getDeathSound()
{
return "mob.example";
}
protected float getSoundVolume()
{
return 0.4F;
}
protected int getDropItemId()
{
return 0;
}
}
The above code should be pretty self explanatory as to what it does but I will quickly go over the details.
getSoundVolume() returns a number from 0 - 1 which is the "volume" of the creatures sound. This can be translated into a percent by multiplying by 100.
getLivingSound, getHurtSound, getDeathSound return the location of the "track" to play when each of those things happen. The tracks can be found in the resources directory. For this example I am just going to copy another mobs
sounds rather than create my own.
read and write entity to NBT allows the creature to be saved and loaded from your save.
So the next step would be to make sure you have all the sounds and textures which are specified in your class, using NPC you need to add the sounds to:
/jars/resources/newsound/mob/example.ogg and the texture needs to be added to:
/temp/minecraft/mob/example.png
You can get my MadCow texture below:

The sound is just the cow sound copied and renamed to example.ogg.
This now means that the entity class is finished.
Next you need to create a Model class. A model class basically provides minecraft with the details required to generate the "model" of the entity within minecraft. So these details are dependent upon your example.png texture. Since I am modelling this example off a cow I will be using mostly the same details as the ModelCow
class.
package net.minecraft.src;
public class ModelExample extends ModelQuadraped
{
public ModelExample()
{
super(12, 0.0F);
head = new ModelRenderer(0, 0);
head.addBox(-4F, -4F, -6F, 8, 8, 6, 0.0F);
head.setPosition(0.0F, 4F, -8F);
horn1 = new ModelRenderer(22, 0);
horn1.addBox(-4F, -5F, -4F, 1, 3, 1, 0.0F);
horn1.setPosition(0.0F, 3F, -7F);
horn2 = new ModelRenderer(22, 0);
horn2.addBox(4F, -5F, -4F, 1, 3, 1, 0.0F);
horn2.setPosition(0.0F, 3F, -7F);
udders = new ModelRenderer(52, 0);
udders.addBox(-2F, -3F, 0.0F, 4, 6, 2, 0.0F);
udders.setPosition(0.0F, 14F, 6F);
udders.rotateAngleX = 1.570796F;
body = new ModelRenderer(18, 4);
body.addBox(-6F, -10F, -7F, 12, 18, 10, 0.0F);
body.setPosition(0.0F, 5F, 2.0F);
leg1.offsetX--;
leg2.offsetX++;
leg1.offsetZ += 0.0F;
leg2.offsetZ += 0.0F;
leg3.offsetX--;
leg4.offsetX++;
leg3.offsetZ--;
leg4.offsetZ--;
}
public void render(float f, float f1, float f2, float f3, float f4, float f5)
{
super.render(f, f1, f2, f3, f4, f5);
horn1.render(f5);
horn2.render(f5);
udders.render(f5);
}
public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5)
{
super.setRotationAngles(f, f1, f2, f3, f4, f5);
horn1.rotateAngleY = head.rotateAngleY;
horn1.rotateAngleX = head.rotateAngleX;
horn2.rotateAngleY = head.rotateAngleY;
horn2.rotateAngleX = head.rotateAngleX;
}
ModelRenderer udders;
ModelRenderer horn1;
ModelRenderer horn2;
}
So as seen above we specify postions and orientation of the new creature. To create a totally new creature with all new dimensions and orientation you would need to play around with these numbers in the constructor a bit.
After creating the Model class we need to create a Render class, the render class provides a way of linking the Model class to the Entity class. Therefore we will create a new class named RenderExample.java the code is pretty bare boned and all it basically does is overwrite doRender and func_171_a to specify the
specific Entity class.
package net.minecraft.src;
public class RenderExample extends RenderLiving
{
public RenderExample(ModelBase modelbase, float f)
{
super(modelbase, f);
}
public void doRenderLiving(EntityLiving entityliving, double d, double d1, double d2,
float f, float f1)
{
super.doRenderLiving((EntityExample)entityliving, d, d1, d2, f, f1);
}
public void doRender(Entity entity, double d, double d1, double d2,
float f, float f1)
{
doRenderLiving((EntityExample)entity, d, d1, d2, f, f1);
}
}
Now we have created all the necessary classes for our new NPC so the next step is to let minecraft know about them so that they can be generated. To do this you need to add some code to RenderManager.java within the constructor at the bottom of the list.
entityRenderMap.put(EntityExample.class, new RenderExample(new ModelExample(),0.7F));
And you also need to add them to the necessary biome generator lists, this is done in the MobSpawnerBase class. Within the constructor add the Entity to the biomeCreature array.
EntityExample.class
After this is complete you can now compile and run your new NPC.
If you wish to create an aggressive NPC this is achieved by changing the Entity class slightly so that it extends EntityMobs instead of EntityAnimals. You will also need to change the MobSpawnerBase list if you want it to spawn at night rather than during the day.
Like the block class to achieve customisation of NPCs all that needs to be done is you need to overwrite the methods in the EntityCreature or EntityMobs classes this will allow the mobs to do basically anything.
End Result:
#46
Posted 15 December 2010 - 02:18 PM
simo_415 said:
That would be more than awesome because then everyone can make custom npcs =D
#47
Posted 15 December 2010 - 08:21 PM
*** Minecraft Coder Pack Version 2.5 ***
Exception in thread "main" java.lang.NoClassDefFoundError: Start
Caused by: java.lang.ClassNotFoundException: Start
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Could not find the main class: Start. Program will exit.
Press any key to continue . . .
I keep getting it even with unmodified files, i just decompile (successful), then recompile (seems successful) and i get this when running the game.
Can anyone help? xD
*EDIT*
[loading paulscode\sound\codecs\CodecWav.class(paulscode\sound\codecs:CodecWav.class)]
sources\minecraft\net\minecraft\src\SoundManager.java:96: cannot find symbol
symbol : class a
location: package paulscode.sound.codecs
SoundSystemConfig.setCodec("xm", paulscode.sound.codecs.a.class);
^
sources\minecraft\net\minecraft\src\SoundManager.java:97: cannot find symbol
symbol : class a
location: package paulscode.sound.codecs
SoundSystemConfig.setCodec("s3m", paulscode.sound.codecs.a.class);
^
sources\minecraft\net\minecraft\src\SoundManager.java:98: cannot find symbol
symbol : class a
location: package paulscode.sound.codecs
SoundSystemConfig.setCodec("mod", paulscode.sound.codecs.a.class);
^
[checking net.minecraft.src.MouseHelper]
Maybe this means something to someone? xD
*EDIT2*
Fixed it xD I just reinstalled minecraft to reset the files on there
#48
Posted 16 December 2010 - 12:31 AM
XDMickeYXD said:
simo_415 said:
That would be more than awesome because then everyone can make custom npcs =D
Added.
I am only teaching how to add things using MCP, extra utilities and Modloaders I am not going to give instructions on as this should be covered in their respective threads. Using the instructions given on those threads you should be able to covert any of my tutorials to become compatible with their mods.
#49
Posted 16 December 2010 - 12:33 AM
Camel1 said:
Good to hear =)
That error is usually due to the compiling failing - you have to compile start.java to get start.class
#51
Posted 16 December 2010 - 04:44 AM
"We didn't want to go, we didn't want to kill them, but its persistent silence and outstretched arms horrified and comforted us at the same time..."
#52
Posted 16 December 2010 - 05:56 AM
alecn1519 said:
There should be examples of this on risugami's thread.
#53
Posted 16 December 2010 - 03:17 PM
In this tutorial I will describe how the map generation works and how to create your own custom map generation. What I mean by map generation is when a new world is created or new chunks are created that terrain that appears is generated terrain - this tutorial will show you how to customise how this happens. I have made quite a few map generation mods now and in my opinion I would have to say they are the most fun. Here are some examples:
Forests

Tall Tree Forests

Ruins

Infinite Track

So as you can see there is a nice variety of map generation available. In this tutorial I will show you how to create a map generator to place random quantities of TNT on the map (a bit of fun =D).
To begin with you will need to create a new WorldGen class, the naming convention is as follows WorldGen[NAME] so for this example I will create a class called WorldGenExample. The bare bones class requires a constructor and generate method. Here it is below:
package net.minecraft.src;
import java.util.Random;
public class WorldGenExample extends WorldGenerator
{
public WorldGenExample()
{
}
public boolean generate(World world, Random random, int i, int j, int k)
{
}
}
Within the generate method we want to put all the logic of the generator. The i, j, k parameters are the block coordinate within minecraft, in general not every block is called and only one block per chunk is called - so keep in mind that each time the generate method is called it is (generally) the only time it will be called for that chunk.
To create the random TNT I am going to add this code to the generate method:
// Gives this a 1 in 10 chance of generating
if (random.nextInt(10) == 0)
{
// Loops 64 times, this could create up to 64 TNT
for (int z = 0; z < 64; z++)
{
int i1 = i + random.nextInt(8) - random.nextInt(8);
int j1 = j + random.nextInt(8) - random.nextInt(8);
int k1 = k + random.nextInt(8) - random.nextInt(8);
// Checks that there is nothing in the current location and there is grass beneath.
if(world.getBlockId(i1, j1, k1) == 0 && world.getBlockId(i1, j1 - 1, k1) == Block.grass.blockID && Block.tnt.canPlaceBlockAt(world, i1, j1, k1))
{
world.setBlockAndMetadata(i1, j1, k1, Block.tnt.blockID, random.nextInt(4));
}
}
}
After coding the logic of your terrain generation you need to let minecraft know about it so that it can generate the terrain. To do this you need to edit ChunkProviderGenerate, specifically the populate method. This method should be pretty self explanatory - it generates Lakes then Dungeons then Clay, etc etc. You need to add your class to this method - where you put it in this list is very important. If you put it at the top of the method, it is a lot more likely to be generated than having it at the bottom of the method - the choice is yours, I am putting this towards the bottom of the method, specifically below the WorldGenLiquids calls.
(new WorldGenExample()).generate(worldObj, rand, k + rand.nextInt(16), rand.nextInt(112) + 16, l + rand.nextInt(16));
Finally after compiling and generating a new world or exploring new areas in a current world you should be able to find TNT spawns. You may want to configure the randomness and quantity per request to be more to your liking.
#54
Posted 16 December 2010 - 03:21 PM
simo_415 said:
Now can you make armor tutorial after?
#55
Posted 16 December 2010 - 03:24 PM
Club559 said:
simo_415 said:
Now can you make armor tutorial after?
Sure, I will probably do it tomorrow morning.
#56
Posted 16 December 2010 - 03:34 PM
Making your mod compatible with modloader
Hey guys
Here I will be telling you how to make your mod compatible with modloader. If you are using MCP, you have ran into this bump of sadness. If you have noticed, these tutorials require editing main Minecraft class files. No more doing that with modloader!
EDIT: I have deleted the download for modloader MCP source because Risugami's epicness has finally made it compatible if you just decompile modloader! Just put the modloader files in your minecraft.jar inside of the MCP jars folder, decompile, and you got yourself a working modloader.
It includes every function on the newest modloader, seeing as you're decompiling the current one.
Anyways, this includes some great functions! First of all, you will have to put mod_ at the front of your mod's name, and put this at the top of the code:
public class mod_MyMod extends BaseMod
Now in Beta 1.2_02, there's something you have to do like this:
public String Version()
{
return "1.2_02";
}
If you want to register a block from there, use this inside your public class:
public static final Block example;
static
{
example = (new BlockExample(92, 1)).setHardness(1.5F).setStepSound(Block.soundStoneFootstep);
}
Notice "Block" in front of soundStoneFootstep. This is required as it is being defined in an outside class.
And for the other functions
public void AddRecipes(CraftingManager recipes)
public int AddSmelting(int id)
public int AddFuel(int id)
public void AddEntityID()
public void GenerateNether(World world, Random random, int chunkX, int chunkZ)
public void GenerateSurface(World world, Random random, int chunkX, int chunkZ)
Soon to come: How to use those functions with tutorials explained above!
#57
Posted 16 December 2010 - 03:38 PM
In BaseMod, you will find a lot of functions to prevent your mod from overwriting the classes that most mods would use if it weren't for modloader. Here is how to use them.
public void AddEntityID()
This tutorial has modloader code for NPC making that includes this function used in it.
public int AddFuel(int id)
Here is an example code I got from an example mod I made. Since there is no fuel tutorial, the number is how long it will take to smelt. Wood is 300, sticks are 100, coal is 1600, and lava buckets are 20000.
public int AddFuel(int id)
{
if(id == Item.flint.shiftedIndex)
{
return 2400;
}
return 0;
}
public void AddRecipes(CraftingManager recipes)
Read the crafting tutorial on this. An example code:
public void AddRecipes(CraftingManager recipes)
{
recipes.addRecipe(new ItemStack(Item.diamond), new Object[] {
"#", Character.valueOf('#'), Block.dirt
});
}
public int AddSmelting(int id)
Read up on the smelting tutorial for more information.
public int AddSmelting(int id)
{
if(id == Block.dirt.blockID)
{
return Item.diamond.shiftedIndex;
}
}
I still have to have explanations for the following:
public void GenerateNether(World world, Random random, int chunkX, int chunkZ)
{
}
public void GenerateSurface(World world, Random random, int chunkX, int chunkZ)
{
}
Until then, have fun with your new modloader mod!
Coming soon:
Part 2 - ModLoader functions
World generation explanations...
#58
Posted 16 December 2010 - 04:39 PM
Club559 said:
That's right
sweet, thanks! I will add it to the original post.
#59
Posted 16 December 2010 - 04:45 PM
#60
Posted 16 December 2010 - 04:50 PM
NoNamed said:
The recipe given in this example should never fail if you have the BlockExample class; try this standard recipe:
addRecipe(new ItemStack(Block.stone, 1), new Object[] {"##", "##", Character.valueOf('#'), Block.dirt});
Make sure you recompile and make sure that there are no compile errors, read my original post regarding compiling and debugging.
**edit**
As an afterthought, view the console window while minecraft is open, load a world and press the escape key. The console window should output "100 recipes".










