package tutorial;
import net.minecraft.block.Block;
import
net.minecraft.block.material.Material;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.Init;
import
cpw.mods.fml.common.event.FMLInitializationEvent;
import
cpw.mods.fml.common.network.NetworkMod;
import
cpw.mods.fml.common.registry.GameRegistry;
import
cpw.mods.fml.common.registry.LanguageRegistry;
@Mod(modid = Tutorial.modid, name = "Mod Name", version = "1.0")
@NetworkMod(clientSideRequired = true, serverSideRequired
= false)
public class Tutorial
{
public static final String modid = "YourName_ModName";
public static Block tutorialBlock;
public static Item tutorialItem;
@Init
public void load(FMLInitializationEvent
event)
{
tutorialBlock = new BlockTutorialBlock(500, Material.rock).setUnlocalizedName("tutorialBlock");
GameRegistry.registerBlock(tutorialBlock, ItemTutorialBlock.class, modid + (tutorialBlock.getUnlocalizedName().substring(5)));
LanguageRegistry.addName(new ItemStack(tutorialBlock, 1, 0), "Tutorial Block");
LanguageRegistry.addName(new ItemStack(tutorialBlock, 1, 1), "Nether Tutorial
Block");
tutorialItem = new ItemTutorial(5000).setUnlocalizedName("tutorialItem");
LanguageRegistry.addName(tutorialItem, "Tutorial Item");
TutorialCrafting.addRecipes();
}
}
There are a couple of ways to add your ore to generation. In this tutorial I'm going to show the way I prefer it, but there are always other ways you can do it.
In my opinion the best way to do it is with an EventManager. A lot of things in Forge are done with events. If you want to see different kinds of events you should take a look at net.minecraftforge.event. In later tutorials I will show you how to use these events. Another way certain events are done is through interfaces. Those also contain methods that get run when the event happens. One of those events are for ore generation. However, most forge mods will contain more than just a single type of Event. That is why we won't be creating a different file for every single Event, but for all of them in one.
To do this you should create a file that will handle all the events. For the tutorial I'm going to call it EventManager. Then make an object of it in the mod file. You should register that object as a World Generator using this code.
GameRegistry.registerWorldGenerator(eventmanager);
And now the whole mod file should look like this.
package tutorial;
import net.minecraft.block.Block;
import
net.minecraft.block.material.Material;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.Init;
import
cpw.mods.fml.common.event.FMLInitializationEvent;
import
cpw.mods.fml.common.network.NetworkMod;
import
cpw.mods.fml.common.registry.GameRegistry;
import
cpw.mods.fml.common.registry.LanguageRegistry;
@Mod(modid = Tutorial.modid, name = "Mod Name", version = "1.0")
@NetworkMod(clientSideRequired = true, serverSideRequired
= false)
public class Tutorial
{
public static final String modid = "YourName_ModName";
public static Block tutorialBlock;
public static Item tutorialItem;
EventManager eventmanager = new EventManager();
@Init
public void load(FMLInitializationEvent
event)
{
tutorialBlock = new BlockTutorialBlock(500, Material.rock).setUnlocalizedName("tutorialBlock");
GameRegistry.registerBlock(tutorialBlock, ItemTutorialBlock.class, modid + (tutorialBlock.getUnlocalizedName().substring(5)));
LanguageRegistry.addName(new ItemStack(tutorialBlock, 1, 0), "Tutorial Block");
LanguageRegistry.addName(new ItemStack(tutorialBlock, 1, 1), "Nether Tutorial Block");
tutorialItem = new ItemTutorial(5000).setUnlocalizedName("tutorialItem");
LanguageRegistry.addName(tutorialItem, "Tutorial Item");
GameRegistry.registerWorldGenerator(eventmanager);
TutorialCrafting.addRecipes();
}
}
If you haven't created the EventManager file just yet you will get an error under registerWorldManager. If you did you will also get an error under there. To fix the error you will have to make the EventManager implement IWorldGenerator. Make sure you implement and not extend or it will give you errors. When you do that you need to import the file. After that you will get an error under EventManager which you can fix by adding the unimplemented methods. Then the file should look like this.
package tutorial;
import java.util.Random;
import net.minecraft.world.World;
import
net.minecraft.world.chunk.IChunkProvider;
import
cpw.mods.fml.common.IWorldGenerator;
public class EventManager implements IWorldGenerator
{
public void generate(Random random, int chunkX, int chunkZ, World world,
IChunkProvider chunkGenerator, IChunkProvider chunkProvider)
{
}
}
Almost every mod will have multiple ores to generate. There are quite a few lines of code you need to write so that is why we will make a method that will write all the code for you. The only thing you need to do is paste it in the file and call it with the block and locations you want it to generate. This is the method you can use for that.
/**
* Adds an Ore Spawn to Minecraft.
Simply register all Ores to spawn with this method in your Generation method in
your IWorldGeneration extending Class
*
* @param The Block to spawn
* @param The World to spawn in
* @param A Random object for retrieving
random positions within the world to spawn the Block
* @param An int for passing the X-Coordinate for the
Generation method
* @param An int for passing the Z-Coordinate for the
Generation method
* @param An int for setting the maximum
X-Coordinate values for spawning on the X-Axis on a Per-Chunk basis
* @param An int for setting the maximum
Z-Coordinate values for spawning on the Z-Axis on a Per-Chunk basis
* @param An int for setting the maximum
size of a vein
* @param An int for the Number of
chances available for the Block to spawn per-chunk
* @param An int for the minimum Y-Coordinate height
at which this block may spawn
* @param An int for the maximum Y-Coordinate height
at which this block may spawn
**/
public void addOreSpawn(Block block, World
world, Random random, int blockXPos, int blockZPos, int maxX, int maxZ, int maxVeinSize, int chancesToSpawn, int minY, int maxY)
{
int maxPossY = minY + (maxY - 1);
assert maxY > minY: "The maximum Y must be greater than the Minimum
Y";
assert maxX > 0 && maxX
<= 16: "addOreSpawn: The Maximum X must be
greater than 0 and less than 16";
assert minY > 0: "addOreSpawn: The Minimum Y must be greater than
0";
assert maxY < 256 && maxY
> 0: "addOreSpawn: The Maximum Y must be
less than 256 but greater than 0";
assert maxZ > 0 && maxZ
<= 16: "addOreSpawn: The Maximum Z must be
greater than 0 and less than 16";
int diffBtwnMinMaxY = maxY - minY;
for(int x = 0; x < chancesToSpawn; x++)
{
int posX = blockXPos +
random.nextInt(maxX);
int posY = minY +
random.nextInt(diffBtwnMinMaxY);
int posZ = blockZPos +
random.nextInt(maxZ);
(new
WorldGenMinable(block.blockID, maxVeinSize)).generate(world, random, posX, posY, posZ);
}
}
This method takes a lot of parameters and they are all explained in the comment above it. This method will use the vanilla WorldGenMinable and then use all of the variables you put in to generate the ore.
Now that we have a way to generate the ores there is one more thing we have to do before we can actually use it. When you are generating ores you usually only want it to generate in a single dimension. To make sure it only goes in one dimension you will have to add a switch and 3 methods to the file. One for each dimension. Once that is done the file should look like this.
package tutorial;
import java.util.Random;
import net.minecraft.block.Block;
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 EventManager implements IWorldGenerator
{
public void generate(Random random, int chunkX, int chunkZ, World world,
IChunkProvider chunkGenerator, IChunkProvider chunkProvider)
{
switch(world.provider.dimensionId)
{
case -1:
generateNether(world, random, chunkX * 16, chunkZ * 16);
case 0:
generateSurface(world, random, chunkX * 16, chunkZ * 16);
case 1:
generateEnd(world, random, chunkX * 16, chunkZ * 16);
}
}
private void generateEnd(World world, Random
random, int x, int z)
{
}
private void generateSurface(World world,
Random random, int x, int z)
{
}
private void generateNether(World world,
Random random, int x, int z)
{
}
/**
* Adds an Ore Spawn to Minecraft. Simply
register all Ores to spawn with this method in your Generation method in your
IWorldGeneration extending Class
*
* @param The Block to spawn
* @param The World to spawn in
* @param A Random object for retrieving random positions
within the world to spawn the Block
* @param An int for passing the X-Coordinate for the Generation method
* @param An int for passing the Z-Coordinate for the Generation method
* @param An int for setting the maximum X-Coordinate values
for spawning on the X-Axis on a Per-Chunk basis
* @param An int for setting the maximum Z-Coordinate values
for spawning on the Z-Axis on a Per-Chunk basis
* @param An int for setting the maximum size of a vein
* @param An int for the Number of chances available for the
Block to spawn per-chunk
* @param An int for the minimum Y-Coordinate height at which this block
may spawn
* @param An int for the maximum Y-Coordinate height at which this block
may spawn
**/
public void addOreSpawn(Block block, World
world, Random random, int blockXPos, int blockZPos, int maxX, int maxZ, int maxVeinSize, int chancesToSpawn, int minY, int maxY)
{
int maxPossY = minY +
(maxY - 1);
assert maxY >
minY: "The maximum Y must be greater than
the Minimum Y";
assert maxX > 0
&& maxX <= 16: "addOreSpawn:
The Maximum X must be greater than 0 and less than 16";
assert minY > 0: "addOreSpawn: The Minimum Y must be greater than
0";
assert maxY < 256
&& maxY > 0: "addOreSpawn:
The Maximum Y must be less than 256 but greater than 0";
assert maxZ > 0
&& maxZ <= 16: "addOreSpawn:
The Maximum Z must be greater than 0 and less than 16";
int diffBtwnMinMaxY =
maxY - minY;
for(int x = 0; x <
chancesToSpawn; x++)
{
int posX = blockXPos +
random.nextInt(maxX);
int posY = minY +
random.nextInt(diffBtwnMinMaxY);
int posZ = blockZPos +
random.nextInt(maxZ);
(new
WorldGenMinable(block.blockID, maxVeinSize)).generate(world, random, posX, posY, posZ);
}
}
}
So we now have a method to generate the ores and a separate method for each dimension to make sure it generate the ores in the right dimension. Of course if you don't want to generate ores in a certain dimension you can simply remove that part of the switch and remove the method.
Now we will have to call addOreSpawn in generateSurface which has to be done like this.
private void generateSurface(World world, Random random, int x, int z)
{
this.addOreSpawn(Tutorial.tutorialBlock, world, random, x, z, 16, 16, 4 + random.nextInt(3), 5, 15, 50);
}
A big part of the parameters in here have to be exactly the same. world, random, x and z can't be changed.
The first parameter is the block that will be generated.
The 2 16's make sure that the blocks can spawn in the whole chunk. If you want blocks to only generate in the first 5 blocks of a chunk for some reason you can change one of those variables.
The 8th variable is the size of the vein and the one after that is how many of the veins will be made in a single chunk. The last 2 variables are the lowest and the highest height those veins will appear.
The whole file should now look something like this.
package tutorial;
import java.util.Random;
import net.minecraft.block.Block;
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 EventManager implements IWorldGenerator
{
public void generate(Random random, int chunkX, int chunkZ, World world,
IChunkProvider chunkGenerator, IChunkProvider chunkProvider)
{
switch(world.provider.dimensionId)
{
case -1:
generateNether(world, random, chunkX * 16, chunkZ * 16);
case 0:
generateSurface(world, random, chunkX * 16, chunkZ * 16);
case 1:
generateEnd(world, random, chunkX * 16, chunkZ * 16);
}
}
private void generateEnd(World world, Random
random, int x, int z)
{
}
private void generateSurface(World world,
Random random, int x, int z)
{
this.addOreSpawn(Tutorial.tutorialBlock, world, random, x, z, 16, 16, 4 + random.nextInt(3), 5, 15, 50);
}
private void generateNether(World world,
Random random, int x, int z)
{
}
/**
* Adds an Ore Spawn to Minecraft. Simply
register all Ores to spawn with this method in your Generation method in your
IWorldGeneration extending Class
*
* @param The Block to spawn
* @param The World to spawn in
* @param A Random object for retrieving random positions
within the world to spawn the Block
* @param An int for passing the X-Coordinate for the Generation method
* @param An int for passing the Z-Coordinate for the Generation method
* @param An int for setting the maximum X-Coordinate values
for spawning on the X-Axis on a Per-Chunk basis
* @param An int for setting the maximum Z-Coordinate values
for spawning on the Z-Axis on a Per-Chunk basis
* @param An int for setting the maximum size of a vein
* @param An int for the Number of chances available for the
Block to spawn per-chunk
* @param An int for the minimum Y-Coordinate height at which this block
may spawn
* @param An int for the maximum Y-Coordinate height at which this block
may spawn
**/
public void addOreSpawn(Block block, World
world, Random random, int blockXPos, int blockZPos, int maxX, int maxZ, int maxVeinSize, int chancesToSpawn, int minY, int maxY)
{
int maxPossY = minY +
(maxY - 1);
assert maxY >
minY: "The maximum Y must be greater than
the Minimum Y";
assert maxX > 0
&& maxX <= 16: "addOreSpawn:
The Maximum X must be greater than 0 and less than 16";
assert minY > 0: "addOreSpawn: The Minimum Y must be greater than
0";
assert maxY < 256
&& maxY > 0: "addOreSpawn:
The Maximum Y must be less than 256 but greater than 0";
assert maxZ > 0
&& maxZ <= 16: "addOreSpawn:
The Maximum Z must be greater than 0 and less than 16";
int diffBtwnMinMaxY =
maxY - minY;
for(int x = 0; x <
chancesToSpawn; x++)
{
int posX = blockXPos +
random.nextInt(maxX);
int posY = minY +
random.nextInt(diffBtwnMinMaxY);
int posZ = blockZPos +
random.nextInt(maxZ);
(new
WorldGenMinable(block.blockID, maxVeinSize)).generate(world, random, posX, posY, posZ);
}
}
}
In the next tutorial I will show you how to add Ore generation to the nether.
You can look at the source code over here.
When you are done you should go back to the tutorials list here.
Deze reactie is verwijderd door de auteur.
BeantwoordenVerwijderen