NO LONGER BEING MAINTAINED. Slowly transferring everything to here. However, feel free to post error messages here, I'd be happy to answer them.
Old post:
For a long time I had wanted to learn how to mod Minecraft and thanks to the great tutorials out there I've been able to. But now it's my turn to give back and help the users that come to this page on how Minecraft is modded. Let's begin!
Note: After you're done with your code, highlight all of your code and type ctrl and I. This will correct indentations. Now, highlight everything and type ctrl + shift + O. This will import all of the correct packages.
Moar note: I will continue adding tutorials, so this is still a WIP.
Step 1- Setting up:
The first thing you want to do is to download a few things that will make decompiling, coding and moding Minecraft infinitesimally easier. They are MCP, which allows you to decompile Minecraft fairly easily, albeit taking a long time.
Next is MinecraftForge; download the src or source package.
Furthermore, you need JDK, or Java Development Kit. This allows you to edit Java classes and jars.
Lastly, Eclipse. This is what allows you to code classes for java. I prefer Java IDE but whatever you find attractive or already use is completely up to you.
After downloading, install JDK. After insalling, you need to set a path to the folder you installed it in. Click on your start menu button and then right click on Computer and select properties. When that window opens up, click on Advanced System Settings and go to the advanced tab. At the very bottom there should be a button labeled Environment Variables. Click on that, and under system variables there should be a label called Path. Double click on it, and scroll to the end of the text. Then paste this at the end of the line, DO NOT REPLACE THE ENTIRE LINE.
;C:\Program Files (x86)\Java\jre7\bin
Then you're ready for the next step.
After, unzip the MCP folder (if using winrar, don't click unzip here, just normally unzip it.) and name it whatever you want your mod to be called. I will be naming mine Tutorial, for the sake of this thread.
Next, unzip the MinecraftForge src folder (this time you can click unzip here) and drag the folder called forge inside your unzipped MCP folder.
Your mod folder should now look like this.
After this is done, go inside the forge folder. There should be a .cmd file named install.cmd inside. Run it, or if you want to use python run install.py or install.sh for what's compatible with your computer. This process takes a long time. Do something else while you're waiting.
Once you're done, go back to the forge folder, and enter the folder called fml (forge modloader) and inside should be a folder called eclipse. Copy that file and return to your mod name folder, in my case tutorial. Paste the eclipse folder and override the current one, accepting all of the "do you want to replace" stuff.
Now you are ready to set up eclipse. Open it up, and the first thing it should ask you to is to select a workspace. Find your mod folder and enter it. Choose the folder "eclipse" as your workspace, for it is already set up with the decompiled Minecraft. Eclipse should then open up and you can start modding!
Step 2 - Main Mod File, Proxy And CommonProxy:
Now that you have eclipse open, there should be a tab called package explorer to the left of the screen. There should be a folder called Minecraft there. Extend it, and then extend the src folder inside of it. This is where all of the code for Minecraft is located.
Your first step is to left click on src and select new and then package. Package names tend to be a website or email address. An example of a package name is com.blfngl.common, com for the extension of my site (that doesn't exit ), blfngl for the domain name, and common because it's the main section of my mod. For a website use one that you own, if you own one, don't do com.google.common.
After you create your package, the next thing you want to do is create your main mod file. Left click on your package and create a new class. The class can be named many things. Most users like their main file to be mod_ModNameHere or ModNameHereMain. You can name it whatever you want, but try to keep your code organized. Mine will be called TutorialMain.
Inside your main file, you should paste this code:
package tutorial.common;
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.PostInit;
import cpw.mods.fml.common.Mod.PreInit;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkMod;
@Mod(modid="tutorial", name="Tutorial Mod", version="1.4.7")
@NetworkMod(clientSideRequired=true, serverSideRequired=false)
public class TutorialMain
{
// The instance of your mod that Forge uses, in my case tutorial.
@Instance("tutorial")
public static TutorialMain instance;
// Says where the client and server 'proxy' code is loaded.
@SidedProxy(clientSide="com.tutorial.common.client.TutorialClientProxy", serverSide="com.tutorial.common.TutorialCommonProxy")
public static TutorialCommonProxy proxy;
@PreInit
public void preInit(FMLPreInitializationEvent event)
{
// Stub Method
}
@Init
public void load(FMLInitializationEvent event) {
proxy.registerRenderers();
}
@PostInit
public void postInit(FMLPostInitializationEvent event) {
// Stub Method
}
}
The first section:
@Mod(modid="tutorial", name="Tutorial Mod", version="1.4.7")
@NetworkMod(clientSideRequired=true, serverSideRequired=false)
public class Generic {
modid is what your mod will be named in the code, not it's title. Keep it short and sweet, if you're doing something like Alabaster mod name it alabaster.
name is the mod's display name. Now you can name it Alabaster Mod.
version is pretty obvious.
Inside NetworkMod clientSideRequired means that the client must have it to join a server that has your mod. Keep this as true.
serverSideRequired means that if you have this mod and you join a vanilla server, it will still be compatible with your client. Keep this on false.
The next section:
// The instance of your mod that Forge uses, in my case tutorial.
@Instance("tutorial")
public static TutorialMain instance;
// Says where the client and server 'proxy' code is loaded.
@SidedProxy(clientSide="com.tutorial.common.client.TutorialClientProxy", serverSide="com.tutorial.common.TutorialCommonProxy")
public static TutorialCommonProxy proxy;
@PreInit
public void preInit(FMLPreInitializationEvent event)
{
// Stub Method
}
@Init
public void load(FMLInitializationEvent event) {
proxy.registerRenderers();
}
@PostInit
public void postInit(FMLPostInitializationEvent event) {
// Stub Method
}
Instance should be the same as modid. If not, you can't run your mod and Minecraft will crash.
public static TutorialMain instance; should be the name of your mod's main class, this one is TutorialMain.
SidedProxy determines where your proxies are. These are what let you connect to servers. The first proxy you make should be TutorialCommonProxy, which should go in the same package your main file is in. The next proxy should be called TutorialClientProxy. This goes in a new package, in this case com.tutorial.client. Make both classes but don't edit them yet.
Under SidedProxy is also where some of your coding will go.
PreInit loads sounds and other things.
Init is where most registries occur, like names and recipes.
PostInit isn't used in this tutorial.
Now we want to go and make the two proxy classes. Make a new class in your mod.common package named TutorialCommonProxy. This is mainly for preloading textures.
package tutorial.common;
public class TutorialCommonProxy {
public static String ITEMS_PNG = "/blfngl/tutorial/textures/items.png";
public static String BLOCK_PNG = "/blfngl/tutorial/textures/blocks.png";
// Client stuff
public void registerRenderers() {
// Nothing here as the server doesn't render graphics!
}
}
As you can see here, the blocks and items that we will be adding need their textures rendered before hand. To add texture files will be covered later. Now we move onto the client proxy. Make a new class called tutorialClientProxy in your tutorial.client package. This is where the textures are notified for the server and mob registering takes place.
package tutorial.client;
public class TutorialClientProxy extends TutorialCommonProxy {
@Override
public void registerRenderers()
{
MinecraftForgeClient.preloadTexture(ITEMS_PNG);
MinecraftForgeClient.preloadTexture(BLOCK_PNG);
}
}
This needs to extend you common proxy to get the texture files for the server. Now we can move on to our first item.
Step 3 - Items:
Items are relatively easy to code with minecraftforge. If you're upgrading from modloader your code can stay almost the same. The first thing we want to do when creating a new item is to define it in your TutorialMain class under @sidedproxy.
To define the item, you must declare it as a public static final
public static final Item TungstenIngot = (new Item(902)).setUnlocalizedName("TungstenIngot").setCreativeTab(CreativeTabs.tabMisc);
.setUnlocalizedName is the new method Forge uses to get a name, in 1.4.7 it was .setItemName.
The word item in front of TungstenIngot is telling minecraft what type of object this is. TungstenIngot is naming the variable. This is what your mod will refer to when it needs to call it. 902 is the ID that your item will receive.
.setCreativeTab is fairly obvious.
Now, if you want your item to be unique, you must make an ItemTungstenIngot class. To call the unique item, instead of writing Item(id) fill in the item with the name of the unique item's class file. If you're making a large mod, I recommend making a new package in the src folder name tutorial.item or something similar.
An item's code is written like this, this is mainly used for custom items that have effects:
package tutorial.item;
public class ItemTungstenIngot extends Item {
public ItemTungstenIngot(int par1){
super(par1);
this.setCreativeTab(CreativeTabs.tabMaterials);
}
@Override
@SideOnly(Side.CLIENT)
public EnumRarity getRarity(ItemStack par1ItemStack){
return EnumRarity.common;
}
public void onCreated(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer)
{
par1ItemStack.addEnchantment(Enchantment.knockback, 3);
}
@Override
//This will be explained later
public void func_94581_a(IconRegister iconRegister)
{
iconIndex = iconRegister.func_94245_a("blfngl" + ":" + this.getUnlocalizedName().substring(this.getUnlocalizedName().indexOf(".") + 1));
}
}
Before you do anything else, make sure you hit ctrl+shift+o. This will organize all the imports that you'll need for your mod to work.The first section displays how this class is extending Item, which turns this into its own item. Inside this class are where some of the properties go. EnumRarity can determine whether this will have a glow on the item. onCreated means when it's crafted it will gain this enchantment. The last section shows how this item gains its texture.
After you're done with this, go back to your main mod file. You now need to add it's in game name and a recipe if you want. This next section of code goes under your public void init method.
This tells minecraft that the item known as TungstenIngot should have an in game name of Tungsten Ingot. I will explain recipes and smelting later on.
And that's all there is to a basic item.
Step 4 - Blocks:
Blocks are also very simple. There are several ways in which you can declare your block. It can be a normal block, an ore block, a leaf block, a flower block or a half slab block. This section will cover ore blocks.
To declare a block, simply put this section of code under your sided proxy:
public static final BlockOre TutorialBlock = (new BlockTutorialBlock(170, 0, Material.rock));
public static final BlockOre TutorialBlock defines the block's code name and type. new BlockTutorialBlock is the class you will need to make in order for the block to exist in the game. After that, the number 170 is it's ID, number 0 is it's texture indices in your blocks.png folder (textures tutorial coming soon...) and Material.rock defines what type of tool is required to mine it.
This next section of code is the content of your BlockTutorialBlock class:
package tutorial.common;
import java.util.Random;
public class BlockTutorialBlock extends BlockOre {
public BlockTutorialBlock(int id, int texture, Material material) {
super(id, texture);
setHardness(4.0F);
setStepSound(Block.soundStoneFootstep);
setUnlocalizedName("TutorialBlock");
setCreativeTab(CreativeTabs.tabBlock);
}
//Will explain this later
public void func_94332_a(IconRegister iconRegister)
{
this.field_94336_cN = iconRegister.func_94245_a("blfngl" + ":" + this.getUnlocalizedName().substring(this.getUnlocalizedName().indexOf(".") + 1));
}
public int idDropped(int par1, Random random, int par2) {
return TutorialMain.TutorialItem.itemID;
}
}
First things first. In your super, setHardness determines what kind of tool your block requires to be mined. 4.0F is at least iron. 5.0 is diamond, 3.0 is gold, 2.0 is stone and 1.0 is wood. If you want your block to be unbreakeable, set it to -1.0F. setBlockName is the code name, so what you defined it with public static final. setStepSound is what sound your block makes when you walk on it. setCreativeTab is pretty obvious.
The @Override with the texture file is what texture your block will load. idDropped is what item your block will drop.
And that's all there is to a basic block.
Step 5 - Block and Item Textures:
With minecraftforge, textures are implemented via texture maps. A texture map is a large png file with many textures on it instead of multiple small files. A base version of this can be found here. Each box is a 16x16 section in which you will put your texture. The box on the top left is zero, the one to it's right one and so on an so forth.
Now, textures are in there own file. Minecraft will stitch together the large file automatically now, so if you're coming from ModLoader you should be thankful. For everyone updating to 1.5 from 1.4 forge, they need to cut up their old items.png and blocks.png to make the separate files.
Note: This looks very strange. But it's correct.
To declare a texture in a block, add this to your BlockTutorialBlock class:
public void func_94332_a(IconRegister iconRegister)
{
this.field_94336_cN = iconRegister.func_94245_a("yourfolderhere:tutorialblock");
}
To declare a texture for an item, add this to your ItemTutorialItem class:
public void func_94581_a(IconRegister iconRegister)
{
iconIndex = iconRegister.func_94245_a("yourfolderhere:tutorialitem");
}
Now it gets trippy. Inside the quotes, the first string, in this case "yourfolderhere" is a reference to a folder that you must make inside a new folder called mods. Meaning, the file structure inside your .zip for your mod would be \mod\yourfolderhere. Inside yourfolderhere you must make two new folders, one called items and one called blocks. Those are where the separate textures go. Here's an example:
Note: You can't add more than one colon. If you do, the file won't be found. It must be in this weird format.
The string after the colon is the image's name. If my image was butterBar.png, I would put butterBar behind the colon. Make sure your images are in .png format!
If you still need some clarification feel free to leave a comment or pm me.
That's the texture tutorial for ya.
Step 6 - New Mobs and Entities:
These guys can be a little tricky at times.
The first thing you want to do is go into your TutorialMain.class and add this to your code under your init section:
EntityRegistry.registerGlobalEntityID(EntityTutorialMob.class is the class file that you will create that defines your mob. "TutorialMob" is the name that minecraft uses to recognize your mob.
ModLoader.getUniqueEntityId() will find a unique number for minecraft to recognize your mob. You can replace this with a number, but then if another mod has the same number with one of it's mobs. they'll conflict.
The numbers after that define the spawn eggs colors. 230, 0 creates a bluish background with black dots. Not really sure what color scale this one uses
LanguageRegistry.instance().addStringLocalization("entity.TutorialMob.name" is calling the name that you called your mob. en_US sets the language and Tutorial Mob is the ingame name of it. Now to create the TutorialMob.class. Instead of writing about the code after this section, I'm going to put the comments inside the code.
package blfngl.tutorial.entity;
public class EntityTutorialMob extends EntityAnimal
{
public EntityTutorialMob(World par1World)
{
super(par1World);
this.texture = "/blfngl/tutorial/textures/TutorialMob.png";
this.setSize(0.9F, 1.3F);
this.getNavigator().setAvoidsWater(true);
this.tasks.addTask(0, new EntityAISwimming(this));
this.tasks.addTask(1, new EntityAIPanic(this, 0.38F));
this.tasks.addTask(2, new EntityAIMate(this, 0.2F));
this.tasks.addTask(3, new EntityAITempt(this, 0.25F, Item.wheat.itemID, false));
this.tasks.addTask(4, new EntityAIFollowParent(this, 0.25F));
this.tasks.addTask(5, new EntityAIWander(this, 0.2F));
this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
this.tasks.addTask(7, new EntityAILookIdle(this));
}
/**
* Returns true if the newer Entity AI code should be run. If false, your mob will be like the old mobs, no pathfinding and whatnot.
*/
public boolean isAIEnabled()
{
return true;
}
//Maximum health
public int getMaxHealth()
{
return 20;
}
/**
* Returns the sound this mob makes while it's alive. I'll be teaching how to add custom sounds a little bit later.
*/
protected String getLivingSound()
{
return "mob.cow.say";
}
/**
* Returns the sound this mob makes when it is hurt.
*/
protected String getHurtSound()
{
return "mob.cow.hurt";
}
/**
* Returns the sound this mob makes on death.
*/
protected String getDeathSound()
{
return "mob.cow.hurt";
}
/**
* Plays step sound at it's coordinates
*/
protected void playStepSound(int par1, int par2, int par3, int par4)
{
this.playSound("mob.cow.step", 0.15F, 1.0F);
}
/**
* Returns the volume for the sounds this mob makes.
*/
protected float getSoundVolume()
{
return 0.4F;
}
/**
* Returns the item ID for the item the mob drops on death. If you want it to drop your item, replace Item.leather.itemID with TutorialMain.TutorialItem.itemID
*/
protected int getDropItemId()
{
return Item.leather.itemID;
}
/**
* Drop 0-2 items of this living's type. @param par1 - Whether this entity has recently been hit by a player. @param
* par2 - Level of Looting used to kill this mob.
*/
protected void dropFewItems(boolean par1, int par2)
{
int var3 = this.rand.nextInt(3) + this.rand.nextInt(1 + par2);
int var4;
for (var4 = 0; var4 < var3; ++var4)
{
this.dropItem(Item.leather.itemID, 1); //One is the quantity of things dropped
}
var3 = this.rand.nextInt(3) + 1 + this.rand.nextInt(1 + par2);
for (var4 = 0; var4 < var3; ++var4)
{
if (this.isBurning())
{
this.dropItem(Item.enderPearl.itemID, 1);
}
else
{
this.dropItem(Item.ingotGold.itemID, 1);
}
}
}
/**
* This function is used when two same-species animals in 'love mode' breed to generate the new baby animal.
*/
public EntityBrahmin spawnBabyAnimal(EntityAgeable par1EntityAgeable)
{
return new EntityBrahmin(this.worldObj);
}
public EntityAgeable createChild(EntityAgeable par1EntityAgeable)
{
return this.spawnBabyAnimal(par1EntityAgeable);
}
}
Now on to the mobs rendering. Inside your ClientProxy add this under your registerRenderers method:
RenderingRegistry.instance().registerEntityRenderingHandler(EntityTutorialMob.class, new RenderTutorialMob(new ModelCow(), 0.5F));]/code]
If you don't add this your entities model will be steve. In this case, your mob will come out as a cow. Now you should be getting an error telling you that you don't have a RenderTutorialMob.class. Go ahead an create that, and then add this to your code.
[code]package blfngl.tutorial.entity;
@SideOnly(Side.CLIENT)
public class RenderTutorialMob extends RenderLiving
{
public RenderTutorialMob(ModelCow par1ModelBase, float par2)
{
super(par1ModelBase, par2);
}
public void renderTutorialMob(EntityTutorialMob par1EntityTutorialMob, double par2, double par4, double par6, float par8, float par9)
{
super.doRenderLiving(par1EntityTutorialMob, par2, par4, par6, par8, par9);
}
public void doRenderLiving(EntityLiving par1EntityLiving, double par2, double par4, double par6, float par8, float par9)
{
this.renderTutorialMob((EntityTutorialMob)par1EntityLiving, par2, par4, par6, par8, par9);
}
public void doRender(Entity par1Entity, double par2, double par4, double par6, float par8, float par9)
{
this.renderTutorialMob((EntityTutorialMob)par1Entity, par2, par4, par6, par8, par9);
}
}
After this, you should be done! Enjoy your mob.
Step 7 - Tools:
These are very basic. First thing you want to do is declare a new tool Enum in your main mod file under @sidedproxy:
public static EnumToolMaterial TUTONE= EnumHelper.addToolMaterial("TUTONE", 2, 1248, 7.0F, 5, 10);
Enums are usually declared in all caps. TUTONE is the name of your enum. The first number is the harvest level, meaning what kind of blocks you can mine. 3 is diamond, 2 is iron, 1 is stone and 0 is gold and wood. The next number, in this case 1248, is the durability of the tool. 7.0F is the speed at which the tool breaks blocks. Diamond is 8.0, wood is 2.0, gold is 12.0, iron is 6.0 and stone is 4.0.
The next number is damage against entities. Not related to swords, but for shovels and such. The last number is enchantability. Not really sure what this does, but I'm guessing the higher the number is the better enchantments it'll get?
One change has been added since the 1.5 update. You must make your own tool classes now, so they get texture support.
Now it's time to declare the items in your @sidedproxy:
public static final Item TutPick = (new ItemTutPickaxe(19000, TutorialMain.TUTONE)).setCreativeTab(CreativeTabs.tabTools).setUnlocalizedName("TutPick");
public static final Item TutAxe= (new ItemTutAxe(19001, TutorialMain.TUTONE)).setCreativeTab(CreativeTabs.tabTools).setUnlocalizedName("TutAxe");
public static final Item TutShovel= (new ItemTutSpade(19002, TutorialMain.TUTONE)).setCreativeTab(CreativeTabs.tabTools).setUnlocalizedName("TutShovel");
public static final Item TutSword= (new ItemTutSword(19003, TutorialMain.TUTONE)).setCreativeTab(CreativeTabs.tabTools).setUnlocalizedName("TutSword");
(new ItemPickaxe(19000, TutorialMain.TUTONE)) declares what the item is extending, in this case a pickaxe. 19000 is the id of the tool. TutorialMain.TUTONE is the Enum of the tool that you just created.
The custom TutToolHere class is very simple as well:
public class TutAxe extends ItemAxe
{
public TutAxe(int par1, EnumToolMaterial par2EnumToolMaterial)
{
super(par1, par2EnumToolMaterial);
}
}
If you want the tool to be a different one, change the extends to a different tool, like ItemSpade.
One of the easiest tutorials ever. (new ItemStack(this.TutItem, 2) tell Minecraft what should the outcome be. In this case, it will be TutItem and two of them.
new Object [] actually defines the recipe. The first set of quotations is the top layer of a crafting bench, the middle the middle, and the last is the bottom. Spaces represent blanks. Put symbols in for where you want your items to be. 'X', TutorialMain.TutIngot is telling Minecraft that the 'X' should be the item TutIngot.
To make a shapeless recipe is even easier:
GameRegistry.addShapelessRecipe(new ItemStack(this.TutIngot, 2), new Object [] {Item.ingotIron, Item.ingotGold});
Just like before, new ItemStack defines what comes out. The difference is in the recipe. All you need to do now is tell Minecraft what items are needed and it handles the rest for you.
Smelting is decently easy also:
GameRegistry.addSmelting(TutorialMain.TutOre.blockID, new ItemStack(this.TutIngot), 15);
Here, TutOre is going to be smelted to produce TutIngot. The thing being smelted doesn't need to be a block though. The number after new ItemStack determines how much experience you'll get from smelting the item/block.
Now you can add recipes!
Step 9 - Armor:
WORKING ON RIGHT NOW
To create armor, just like tools, we need to make a new Enum inside our @sidedproxy:
public static EnumArmorMaterial TUTARMOR= EnumHelper.addArmorMaterial("TUTARMOR", 33, new int[]{5, 10, 7, 3}, 10);
Step 10 - Plants:
Plants are a two step process. First, declare your new plant as so:
public final static BlockFlower TutFlower= (BlockFlower) new BlockTutFlower(174, 3).setBlockName("TutFlower");
Just like before, TutFlower is the code name of your new plant. new BlockTutFlower is the class that will be called. (174, 3) is the id and then the icon index, respectively.
Now on to the BlockTutFlower class:
package tutorial.package;
import java.util.Random;
import net.minecraft.block.BlockFlower;
public class BlockBrocFlower extends BlockFlower
{
public BlockBrocFlower(int id, int iconindex)
{
super(id, iconindex);
}
public int idDropped(int i, Random random, int j)
{
return TutorialMain.bTutFlower.itemID;
}
public String getTextureFile()
{
return "/tutorial/textures/blocks.png";
}
}
Now you might be wondering what bTutFlower is. Flowers can't be placed like blocks. They must be placed through items, kinda like redstone. Anyway, declare a new item in your main file, but instead of calling it as Item, declare it as the new class you will make. Mine is called bTutFlower and it's code is:
package tutorial.package;
import net.minecraft.block.Block;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public class ItembTutFlower extends Item
{
public ItembTutFlower(int par1, int par2, float par3, boolean par4){
super(par1);
this.setCreativeTab(CreativeTabs.tabDecorations);
}
@Override
public String getTextureFile(){
return "/tutorial/textures/items.png";
}
public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10)
{
if (par3World.getBlockId(par4, par5, par6) != Block.snow.blockID)
{
if (par7 == 0)
{
--par5;
}
if (par7 == 1)
{
++par5;
}
if (par7 == 2)
{
--par6;
}
if (par7 == 3)
{
++par6;
}
if (par7 == 4)
{
--par4;
}
if (par7 == 5)
{
++par4;
}
if (!par3World.isAirBlock(par4, par5, par6))
{
return false;
}
}
if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack))
{
return false;
}
else
{
if (TutorialMain.TutFlower.canPlaceBlockAt(par3World, par4, par5, par6))
{
--par1ItemStack.stackSize;
par3World.setBlockWithNotify(par4, par5, par6, TutorialMain.TutFlower.blockID);
}
return true;
}
}
}
That should do it for a flower tutorial
Step 11 - Ore Generation:
A simple tutorial. First, declare this in your init section of your main file:
To make the WorldGenTutOre class, copy this inside it:
package tutorial.package;
import java.util.Random;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.feature.WorldGenMinable;
import cpw.mods.fml.common.IWorldGenerator;
public class WorldGenTungstenOre implements IWorldGenerator {
@Override
public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider)
{
switch(world.provider.dimensionId)
{
case 0:
generateSurface(world, random, chunkX*16, chunkZ*16);
break;
}
}
public void generateSurface(World world, Random rand, int chunkX, int chunkZ)
{
for (int i = 0; i < 16; i++)
{
int randPosX = chunkX + rand.nextInt(16);
int randPosY = rand.nextInt(48);
int randPosZ = chunkZ + rand.nextInt(16);
(new WorldGenMinable(TutorialMain.TutOre.blockID, 10)).generate(world, rand, randPosX, randPosY, randPosZ);
}
}
}
Let's skip right to the generateSurface method. for (int = 0; i<16; i++) determines the frequency of your ore. The larger the number, the more likely it will be to find.
Under that, randPosX = chunkX + rand.nexInt(16) and int randPosZ = chunkZ + rand.newInt(16) should stay this way. This keeps the blocks inside the chunk. The one that you should mess with is the randPosY. 48 is the level that this ore will be and everything below it. For example, diamond is 18, while coal is 256.
To define the item, you must declare it as a public static final
public static final Item TungstenIngot = (new ItemTungstenIngot(902)).setIconIndex(2).setItemName("TungstenIngot").setCreativeTab(CreativeTabs.tabMisc);
The word item in front of TungstenIngot is telling minecraft what type of object this is. TungstenIngot is naming the variable. This is what your mod will refer to when it needs to call it. ItemTungstenIngot(902) is a class that you'll have to make, in this case ItemTungstenIngot. 902 is the ID that your item will receive.
only I want update discontinued mods, in the case I have a source code, where I must put it and how I can update the mod to the last minecraft version?
Nope. Mods are protected under GNU Lesser, which means that the source code is available but you can't edit or redistribute it without special permission. That's what mine's under.
"Since I decided not to continue developing this mod, I have released its source code."
I just want to know how to update mods, then if I put it in a forum, obviously I will ask permission. but the issue is that I want to know how to update mods .. to keep the latest version of the mods I used to have in previous versions and now they aren't here because the creator has abandoned
You're still modifying it, which is against the rules.
Oh god.. Are you a cop?! I want my old mods back.. The rules say I can use the mod, modify if the creator allow that, but I can't distribute without permission.. I DON'T WANNA DISTRIBUTE THE MOD, ONLY I WANT USE THIS IN MY COMPUTER ONLY
Back on topic, I am getting a "static access of nonstatic" error - "cannot make a static reference to the nonstatic method registerRenderers from the type CommonProxy":
Back on topic, I am getting a "static access of nonstatic" error - "cannot make a static reference to the nonstatic method registerRenderers from the type CommonProxy":
NO LONGER BEING MAINTAINED. Slowly transferring everything to here. However, feel free to post error messages here, I'd be happy to answer them.
Old post:
For a long time I had wanted to learn how to mod Minecraft and thanks to the great tutorials out there I've been able to. But now it's my turn to give back and help the users that come to this page on how Minecraft is modded. Let's begin!
Note: After you're done with your code, highlight all of your code and type ctrl and I. This will correct indentations. Now, highlight everything and type ctrl + shift + O. This will import all of the correct packages.
Moar note: I will continue adding tutorials, so this is still a WIP.
Step 1- Setting up:
Next is MinecraftForge; download the src or source package.
Furthermore, you need JDK, or Java Development Kit. This allows you to edit Java classes and jars.
Lastly, Eclipse. This is what allows you to code classes for java. I prefer Java IDE but whatever you find attractive or already use is completely up to you.
After downloading, install JDK. After insalling, you need to set a path to the folder you installed it in. Click on your start menu button and then right click on Computer and select properties. When that window opens up, click on Advanced System Settings and go to the advanced tab. At the very bottom there should be a button labeled Environment Variables. Click on that, and under system variables there should be a label called Path. Double click on it, and scroll to the end of the text. Then paste this at the end of the line, DO NOT REPLACE THE ENTIRE LINE.
After, unzip the MCP folder (if using winrar, don't click unzip here, just normally unzip it.) and name it whatever you want your mod to be called. I will be naming mine Tutorial, for the sake of this thread.
Next, unzip the MinecraftForge src folder (this time you can click unzip here) and drag the folder called forge inside your unzipped MCP folder.
Your mod folder should now look like this.
Once you're done, go back to the forge folder, and enter the folder called fml (forge modloader) and inside should be a folder called eclipse. Copy that file and return to your mod name folder, in my case tutorial. Paste the eclipse folder and override the current one, accepting all of the "do you want to replace" stuff.
Now you are ready to set up eclipse. Open it up, and the first thing it should ask you to is to select a workspace. Find your mod folder and enter it. Choose the folder "eclipse" as your workspace, for it is already set up with the decompiled Minecraft. Eclipse should then open up and you can start modding!
Step 2 - Main Mod File, Proxy And CommonProxy:
Your first step is to left click on src and select new and then package. Package names tend to be a website or email address. An example of a package name is com.blfngl.common, com for the extension of my site (that doesn't exit ), blfngl for the domain name, and common because it's the main section of my mod. For a website use one that you own, if you own one, don't do com.google.common.
After you create your package, the next thing you want to do is create your main mod file. Left click on your package and create a new class. The class can be named many things. Most users like their main file to be mod_ModNameHere or ModNameHereMain. You can name it whatever you want, but try to keep your code organized. Mine will be called TutorialMain.
Inside your main file, you should paste this code:
The first section:
name is the mod's display name. Now you can name it Alabaster Mod.
version is pretty obvious.
Inside NetworkMod clientSideRequired means that the client must have it to join a server that has your mod. Keep this as true.
serverSideRequired means that if you have this mod and you join a vanilla server, it will still be compatible with your client. Keep this on false.
The next section:
public static TutorialMain instance; should be the name of your mod's main class, this one is TutorialMain.
SidedProxy determines where your proxies are. These are what let you connect to servers. The first proxy you make should be TutorialCommonProxy, which should go in the same package your main file is in. The next proxy should be called TutorialClientProxy. This goes in a new package, in this case com.tutorial.client. Make both classes but don't edit them yet.
Under SidedProxy is also where some of your coding will go.
PreInit loads sounds and other things.
Init is where most registries occur, like names and recipes.
PostInit isn't used in this tutorial.
Now we want to go and make the two proxy classes. Make a new class in your mod.common package named TutorialCommonProxy. This is mainly for preloading textures.
As you can see here, the blocks and items that we will be adding need their textures rendered before hand. To add texture files will be covered later. Now we move onto the client proxy. Make a new class called tutorialClientProxy in your tutorial.client package. This is where the textures are notified for the server and mob registering takes place.
This needs to extend you common proxy to get the texture files for the server. Now we can move on to our first item.
Step 3 - Items:
To define the item, you must declare it as a public static final
.setUnlocalizedName is the new method Forge uses to get a name, in 1.4.7 it was .setItemName.
The word item in front of TungstenIngot is telling minecraft what type of object this is. TungstenIngot is naming the variable. This is what your mod will refer to when it needs to call it. 902 is the ID that your item will receive.
.setCreativeTab is fairly obvious.
Now, if you want your item to be unique, you must make an ItemTungstenIngot class. To call the unique item, instead of writing Item(id) fill in the item with the name of the unique item's class file. If you're making a large mod, I recommend making a new package in the src folder name tutorial.item or something similar.
An item's code is written like this, this is mainly used for custom items that have effects:
After you're done with this, go back to your main mod file. You now need to add it's in game name and a recipe if you want. This next section of code goes under your public void init method.
This tells minecraft that the item known as TungstenIngot should have an in game name of Tungsten Ingot. I will explain recipes and smelting later on.
And that's all there is to a basic item.
Step 4 - Blocks:
To declare a block, simply put this section of code under your sided proxy:
public static final BlockOre TutorialBlock defines the block's code name and type. new BlockTutorialBlock is the class you will need to make in order for the block to exist in the game. After that, the number 170 is it's ID, number 0 is it's texture indices in your blocks.png folder (textures tutorial coming soon...) and Material.rock defines what type of tool is required to mine it.
This next section of code is the content of your BlockTutorialBlock class:
First things first. In your super, setHardness determines what kind of tool your block requires to be mined. 4.0F is at least iron. 5.0 is diamond, 3.0 is gold, 2.0 is stone and 1.0 is wood. If you want your block to be unbreakeable, set it to -1.0F. setBlockName is the code name, so what you defined it with public static final. setStepSound is what sound your block makes when you walk on it. setCreativeTab is pretty obvious.
The @Override with the texture file is what texture your block will load. idDropped is what item your block will drop.
And that's all there is to a basic block.
Step 5 - Block and Item Textures:
With minecraftforge, textures are implemented via texture maps. A texture map is a large png file with many textures on it instead of multiple small files. A base version of this can be found here. Each box is a 16x16 section in which you will put your texture. The box on the top left is zero, the one to it's right one and so on an so forth.Now, textures are in there own file. Minecraft will stitch together the large file automatically now, so if you're coming from ModLoader you should be thankful. For everyone updating to 1.5 from 1.4 forge, they need to cut up their old items.png and blocks.png to make the separate files.
Note: This looks very strange. But it's correct.
To declare a texture in a block, add this to your BlockTutorialBlock class:
To declare a texture for an item, add this to your ItemTutorialItem class:
Now it gets trippy. Inside the quotes, the first string, in this case "yourfolderhere" is a reference to a folder that you must make inside a new folder called mods. Meaning, the file structure inside your .zip for your mod would be \mod\yourfolderhere. Inside yourfolderhere you must make two new folders, one called items and one called blocks. Those are where the separate textures go. Here's an example:
Note: You can't add more than one colon. If you do, the file won't be found. It must be in this weird format.
The string after the colon is the image's name. If my image was butterBar.png, I would put butterBar behind the colon. Make sure your images are in .png format!
If you still need some clarification feel free to leave a comment or pm me.
That's the texture tutorial for ya.
Step 6 - New Mobs and Entities:
The first thing you want to do is go into your TutorialMain.class and add this to your code under your init section:
EntityRegistry.registerGlobalEntityID(EntityTutorialMob.class is the class file that you will create that defines your mob. "TutorialMob" is the name that minecraft uses to recognize your mob.
ModLoader.getUniqueEntityId() will find a unique number for minecraft to recognize your mob. You can replace this with a number, but then if another mod has the same number with one of it's mobs. they'll conflict.
The numbers after that define the spawn eggs colors. 230, 0 creates a bluish background with black dots. Not really sure what color scale this one uses
LanguageRegistry.instance().addStringLocalization("entity.TutorialMob.name" is calling the name that you called your mob. en_US sets the language and Tutorial Mob is the ingame name of it. Now to create the TutorialMob.class. Instead of writing about the code after this section, I'm going to put the comments inside the code.
Now on to the mobs rendering. Inside your ClientProxy add this under your registerRenderers method:
After this, you should be done! Enjoy your mob.
Step 7 - Tools:
Enums are usually declared in all caps. TUTONE is the name of your enum. The first number is the harvest level, meaning what kind of blocks you can mine. 3 is diamond, 2 is iron, 1 is stone and 0 is gold and wood. The next number, in this case 1248, is the durability of the tool. 7.0F is the speed at which the tool breaks blocks. Diamond is 8.0, wood is 2.0, gold is 12.0, iron is 6.0 and stone is 4.0.
The next number is damage against entities. Not related to swords, but for shovels and such. The last number is enchantability. Not really sure what this does, but I'm guessing the higher the number is the better enchantments it'll get?
One change has been added since the 1.5 update. You must make your own tool classes now, so they get texture support.
Now it's time to declare the items in your @sidedproxy:
(new ItemPickaxe(19000, TutorialMain.TUTONE)) declares what the item is extending, in this case a pickaxe. 19000 is the id of the tool. TutorialMain.TUTONE is the Enum of the tool that you just created.
The custom TutToolHere class is very simple as well:
setUnlocalizedNamewill set your tools code name.
Now we can declare the tool in your init section:
This is the exact same as naming items and blocks. Same with the recipe section.
Your tools are now done!
Step 8 - Recipes and Smelting:
One of the easiest tutorials ever. (new ItemStack(this.TutItem, 2) tell Minecraft what should the outcome be. In this case, it will be TutItem and two of them.
new Object [] actually defines the recipe. The first set of quotations is the top layer of a crafting bench, the middle the middle, and the last is the bottom. Spaces represent blanks. Put symbols in for where you want your items to be. 'X', TutorialMain.TutIngot is telling Minecraft that the 'X' should be the item TutIngot.
To make a shapeless recipe is even easier:
Just like before, new ItemStack defines what comes out. The difference is in the recipe. All you need to do now is tell Minecraft what items are needed and it handles the rest for you.
Smelting is decently easy also:
Here, TutOre is going to be smelted to produce TutIngot. The thing being smelted doesn't need to be a block though. The number after new ItemStack determines how much experience you'll get from smelting the item/block.
Now you can add recipes!
Step 9 - Armor:
To create armor, just like tools, we need to make a new Enum inside our @sidedproxy:
Step 10 - Plants:
Just like before, TutFlower is the code name of your new plant. new BlockTutFlower is the class that will be called. (174, 3) is the id and then the icon index, respectively.
Now on to the BlockTutFlower class:
That should do it for a flower tutorial
Step 11 - Ore Generation:
To make the WorldGenTutOre class, copy this inside it:
Under that, randPosX = chunkX + rand.nexInt(16) and int randPosZ = chunkZ + rand.newInt(16) should stay this way. This keeps the blocks inside the chunk. The one that you should mess with is the randPosY. 48 is the level that this ore will be and everything below it. For example, diamond is 18, while coal is 256.
That's it for an ore gen tutorial.
To define the item, you must declare it as a public static final
public static final Item TungstenIngot = (new ItemTungstenIngot(902)).setIconIndex(2).setItemName("TungstenIngot").setCreativeTab(CreativeTabs.tabMisc);
The word item in front of TungstenIngot is telling minecraft what type of object this is. TungstenIngot is naming the variable. This is what your mod will refer to when it needs to call it. ItemTungstenIngot(902) is a class that you'll have to make, in this case ItemTungstenIngot. 902 is the ID that your item will receive.
I suppose the creator allow everyone to update his mod if he released the source code o_O
I just want to know how to update mods, then if I put it in a forum, obviously I will ask permission. but the issue is that I want to know how to update mods .. to keep the latest version of the mods I used to have in previous versions and now they aren't here because the creator has abandoned
I don't want repost this mod, I only want update to my only use!
Oh god.. Are you a cop?! I want my old mods back.. The rules say I can use the mod, modify if the creator allow that, but I can't distribute without permission.. I DON'T WANNA DISTRIBUTE THE MOD, ONLY I WANT USE THIS IN MY COMPUTER ONLY
ok, He say me I have permission to update the mod, but I don't have permission to put it in a forum thread.. so I am the only one can use the mod.
Can you say me how update the mod?
In my mod_ file:
And my client proxy is as you do:
Where exactly is your error? Most of the time in the error message it will tell you what line is creating a problem.