54
First of all, this tutorial is for forge. Sorry Rigusami users.
This tutorial will only explain how to add custom structures to village generation, so I'm going to assume you have your mod class set up and such.
Add this code to your base class, in the init/load function:
Ok,
There are several things you need to know about the above code, the areas of importance are highlighted.
And that is it for the first bit of code!
Now, the next part does not need to be explained, just copy and paste into a class with a sensible name. Once done, replace that VillageCreationHandler in the above code with this new class name that you chose.
Ok, now the last bit!
The component class.
Below is straight out of my incense mod code. (The candleshop will be in a future update, not now.)
There will be a LOT of errors here, due to references to blocks only added in the mod.
And... ALL DONE, this code above is pretty self explanatory.
Now you can build your building in minecraft and use MCEdit to convert it into a schematic and turn it into code to be used.. or... you can do it manually.
And that's it.
If you have any issues, just say in the comments below.
This tutorial will only explain how to add custom structures to village generation, so I'm going to assume you have your mod class set up and such.
Add this code to your base class, in the init/load function:
ModTutorial
addVillagePiece(VillageComponentBakery.class, "ViBk");
addVillageCreationHandler(new VillageHandlerBakery());
addVillageCreationHandler(new VillageHandlerBakery());
Ok,
There are several things you need to know about the above code, the areas of importance are highlighted.
- ComponentBakery.class is the class containing your actual structure code, it tells minecraft where to create the blocks to form your component. You will get an error there because we have not made our component yet.
- That "ViBk" really means nothing, you can put whatever you want in there. HOWEVER, for convenience, so that you may know which building it is, I suggest you call it smething like this instead of something silly like "dhnkbjdhb". In the minecraft code, they have names like "ViBH" which can be understood as (Vi)llage (B)ig (H)ouse. So yeah.
- Next we have the VillageCreationHandler. You will make this class, so for now do not worry about the error.
- Also, eclipse will be screaming at us because no such methods "addVillagePiece", etc exist, yet.
Spoiler - click to reveal
public static void addVillagePiece(Class c, String s)
{
try
{
MapGenStructureIO.func_143031_a(c, s);
}
catch (Exception localException) {}
}
public static void addVillageCreationHandler(VillagerRegistry.IVillageCreationHandler v)
{
VillagerRegistry.instance().registerVillageCreationHandler(v);
}
{
try
{
MapGenStructureIO.func_143031_a(c, s);
}
catch (Exception localException) {}
}
public static void addVillageCreationHandler(VillagerRegistry.IVillageCreationHandler v)
{
VillagerRegistry.instance().registerVillageCreationHandler(v);
}
And that is it for the first bit of code!
Now, the next part does not need to be explained, just copy and paste into a class with a sensible name. Once done, replace that VillageCreationHandler in the above code with this new class name that you chose.
VillageCreationHandler
package com.my.mod.village;
import cpw.mods.fml.common.registry.VillagerRegistry.IVillageCreationHandler;
import java.util.List;
import java.util.Random;
import net.minecraft.world.gen.structure.StructureVillagePieces.PieceWeight;
import net.minecraft.world.gen.structure.StructureVillagePieces.Start;
public class VillageHandlerBakery
implements IVillageCreationHandler
{
public StructureVillagePieces.PieceWeight getVillagePieceWeight(Random random, int i)
{
return new StructureVillagePieces.PieceWeight(VillageComponentBakery.class, 15, i + random.nextInt(3)); //Play around with these numbers!
}
public Class<?> getComponentClass()
{
return VillageComponentBakery.class;
}
public Object buildComponent(StructureVillagePieces.PieceWeight villagePiece, StructureVillagePieces.Start startPiece, List pieces, Random random, int p1, int p2, int p3, int p4, int p5)
{
return VillageComponentBakery.buildComponent(startPiece, pieces, random, p1, p2, p3, p4, p5);
}
}
import cpw.mods.fml.common.registry.VillagerRegistry.IVillageCreationHandler;
import java.util.List;
import java.util.Random;
import net.minecraft.world.gen.structure.StructureVillagePieces.PieceWeight;
import net.minecraft.world.gen.structure.StructureVillagePieces.Start;
public class VillageHandlerBakery
implements IVillageCreationHandler
{
public StructureVillagePieces.PieceWeight getVillagePieceWeight(Random random, int i)
{
return new StructureVillagePieces.PieceWeight(VillageComponentBakery.class, 15, i + random.nextInt(3)); //Play around with these numbers!
}
public Class<?> getComponentClass()
{
return VillageComponentBakery.class;
}
public Object buildComponent(StructureVillagePieces.PieceWeight villagePiece, StructureVillagePieces.Start startPiece, List pieces, Random random, int p1, int p2, int p3, int p4, int p5)
{
return VillageComponentBakery.buildComponent(startPiece, pieces, random, p1, p2, p3, p4, p5);
}
}
Ok, now the last bit!
The component class.
Below is straight out of my incense mod code. (The candleshop will be in a future update, not now.)
There will be a LOT of errors here, due to references to blocks only added in the mod.
ComponentVillageCandleshop
package com.mcis.all;
import java.util.List;
import java.util.Random;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.WeightedRandomChestContent;
import net.minecraft.world.World;
import net.minecraft.world.gen.structure.StructureBoundingBox;
import net.minecraft.world.gen.structure.StructureComponent;
import net.minecraft.world.gen.structure.StructureVillagePieces.Start;
import net.minecraft.world.gen.structure.StructureVillagePieces.Village;
public class VillageComponentCandleshop
extends StructureVillagePieces.Village
{
private int averageGroundLevel = -1;
public VillageComponentCandleshop(StructureVillagePieces.Start villagePiece, int par2, Random par3Random, StructureBoundingBox par4StructureBoundingBox, int par5)
{
this.coordBaseMode = par5;
this.boundingBox = par4StructureBoundingBox;
}
public static final WeightedRandomChestContent[] candleshopChest = {
new WeightedRandomChestContent(IncenseCore.cinnamon, 0, 1, 3, 85),
new WeightedRandomChestContent(IncenseCore.incenseHolder, 0, 1, 1, 25),
new WeightedRandomChestContent(IncenseCore.incense, 0, 1, 2, 5),
new WeightedRandomChestContent(IncenseCore.incense, 1, 1, 2, 5),
new WeightedRandomChestContent(IncenseCore.incense, 2, 1, 2, 5),
new WeightedRandomChestContent(IncenseCore.incense, 3, 1, 2, 5),
new WeightedRandomChestContent(IncenseCore.incense, 4, 1, 2, 5),
new WeightedRandomChestContent(IncenseCore.incense, 5, 1, 2, 5),
new WeightedRandomChestContent(Items.sugar, 0, 1, 4, 85),
new WeightedRandomChestContent(Items.book, 0, 1, 2, 35),
new WeightedRandomChestContent(Items.flint_and_steel, 0, 1, 1, 2) };
private boolean hasMadeChest;
protected void func_143012_a(NBTTagCompound par1NBTTagCompound)
{
super.func_143012_a(par1NBTTagCompound);
par1NBTTagCompound.setBoolean("MCIS_createdChest", this.hasMadeChest);
}
protected void func_143011_b(NBTTagCompound par1NBTTagCompound)
{
super.func_143011_b(par1NBTTagCompound);
this.hasMadeChest = par1NBTTagCompound.getBoolean("MCIS_createdChest");
}
public static VillageComponentCandleshop buildComponent(StructureVillagePieces.Start villagePiece, List pieces, Random random, int p1, int p2, int p3, int p4, int p5)
{
StructureBoundingBox structureboundingbox = StructureBoundingBox.getComponentToAddBoundingBox(p1, p2, p3, 0, 0, 0, widX, heiY, lenZ, p4);
return (canVillageGoDeeper(structureboundingbox)) && (StructureComponent.findIntersecting(pieces, structureboundingbox) == null) ? new VillageComponentCandleshop(villagePiece, p5, random, structureboundingbox, p4) : null;
}
private static int widX = 9;
private static int heiY = 7;
private static int lenZ = 11;
public boolean addComponentParts(World world, Random random, StructureBoundingBox sbb)
{
if (this.averageGroundLevel < 0)
{
this.averageGroundLevel = getAverageGroundLevel(world, sbb);
if (this.averageGroundLevel < 0) {
return true;
}
this.boundingBox.offset(0, this.averageGroundLevel - this.boundingBox.maxY + 4, 0);
}
fillWithBlocks(world, sbb, 0, 2, 0, 6, 3, 6, Blocks.cobblestone, Blocks.cobblestone, false);
fillWithBlocks(world, sbb, 0, 4, 0, 6, 7, 6, Blocks.planks, Blocks.planks, false);
fillWithBlocks(world, sbb, 1, 2, 1, 5, 2, 5, Blocks.planks, Blocks.planks, false);
fillWithAir(world, sbb, 1, 3, 1, 5, 5, 5);
placeBlockAtCurrentPosition(world, Blocks.stone_stairs, getMetadataWithOffset(Blocks.stone_stairs, 3), 4, 2, -1, sbb);
placeDoorAtCurrentPosition(world, sbb, random, 4, 3, 0, getMetadataWithOffset(Blocks.wooden_door, 3));
for (int i = 0; i < 4; i++)
{
placeBlockAtCurrentPosition(world, Blocks.log, 0, 0, i + 2, 0, sbb);
placeBlockAtCurrentPosition(world, Blocks.log, 0, 6, i + 2, 0, sbb);
placeBlockAtCurrentPosition(world, Blocks.log, 0, 0, i + 2, 6, sbb);
placeBlockAtCurrentPosition(world, Blocks.log, 0, 6, i + 2, 6, sbb);
if ((i >= 1) && (i <= 4)) {
placeBlockAtCurrentPosition(world, Blocks.log, 0, 3, i + 2, 1, sbb);
}
}
for (int i = 0; i < 7; i++)
{
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, getMetadataWithOffset(Blocks.oak_stairs, 3), i, 6, -1, sbb);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, getMetadataWithOffset(Blocks.oak_stairs, 3), i, 7, 0, sbb);
}
for (int i = 0; i < 7; i++)
{
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, getMetadataWithOffset(Blocks.oak_stairs, 2), i, 6, 7, sbb);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, getMetadataWithOffset(Blocks.oak_stairs, 2), i, 7, 6, sbb);
}
fillWithBlocks(world, sbb, 1, 4, 0, 2, 5, 0, Blocks.glass_pane, Blocks.glass_pane, false);
placeBlockAtCurrentPosition(world, Blocks.wool, 14, 1, 3, 1, sbb);
placeBlockAtCurrentPosition(world, Blocks.wool, 14, 2, 3, 1, sbb);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, getMetadataWithOffset(Blocks.oak_stairs, 2) + 4, 3, 5, 2, sbb);
for (int i1 = 0; i1 < 2; i1++)
{
placeBlockAtCurrentPosition(world, Blocks.log, 0, i1 * 6, 4, 2, sbb);
placeBlockAtCurrentPosition(world, Blocks.glass_pane, 0, i1 * 6, 4, 3, sbb);
placeBlockAtCurrentPosition(world, Blocks.log, 0, i1 * 6, 4, 4, sbb);
}
placeBlockAtCurrentPosition(world, Blocks.planks, 1, 1, 3, 4, sbb);
placeBlockAtCurrentPosition(world, Blocks.planks, 1, 2, 3, 4, sbb);
placeBlockAtCurrentPosition(world, Blocks.planks, 1, 3, 3, 4, sbb);
placeBlockAtCurrentPosition(world, Blocks.planks, 1, 3, 3, 5, sbb);
for (int i2 = 1; i2 < 4; i2++) {
placeBlockAtCurrentPosition(world, Blocks.wooden_slab, 1, i2, 5, 5, sbb);
}
placeBlockAtCurrentPosition(world, Blocks.torch, 0, 4, 5, 1, sbb);
if (!this.hasMadeChest)
{
int i = getYWithOffset(1);
int j = getXWithOffset(5, 5);
int k = getZWithOffset(5, 5);
if (sbb.isVecInside(j, i, k))
{
this.hasMadeChest = true;
generateStructureChestContents(world, sbb, random, 5, 3, 5, candleshopChest, 1 + random.nextInt(3));
}
}
spawnVillagers(world, sbb, 2, 3, 5, 1);
return true;
}
public int getVillagerType(int i)
{
return 99;
}
}
import java.util.List;
import java.util.Random;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.WeightedRandomChestContent;
import net.minecraft.world.World;
import net.minecraft.world.gen.structure.StructureBoundingBox;
import net.minecraft.world.gen.structure.StructureComponent;
import net.minecraft.world.gen.structure.StructureVillagePieces.Start;
import net.minecraft.world.gen.structure.StructureVillagePieces.Village;
public class VillageComponentCandleshop
extends StructureVillagePieces.Village
{
private int averageGroundLevel = -1;
public VillageComponentCandleshop(StructureVillagePieces.Start villagePiece, int par2, Random par3Random, StructureBoundingBox par4StructureBoundingBox, int par5)
{
this.coordBaseMode = par5;
this.boundingBox = par4StructureBoundingBox;
}
public static final WeightedRandomChestContent[] candleshopChest = {
new WeightedRandomChestContent(IncenseCore.cinnamon, 0, 1, 3, 85),
new WeightedRandomChestContent(IncenseCore.incenseHolder, 0, 1, 1, 25),
new WeightedRandomChestContent(IncenseCore.incense, 0, 1, 2, 5),
new WeightedRandomChestContent(IncenseCore.incense, 1, 1, 2, 5),
new WeightedRandomChestContent(IncenseCore.incense, 2, 1, 2, 5),
new WeightedRandomChestContent(IncenseCore.incense, 3, 1, 2, 5),
new WeightedRandomChestContent(IncenseCore.incense, 4, 1, 2, 5),
new WeightedRandomChestContent(IncenseCore.incense, 5, 1, 2, 5),
new WeightedRandomChestContent(Items.sugar, 0, 1, 4, 85),
new WeightedRandomChestContent(Items.book, 0, 1, 2, 35),
new WeightedRandomChestContent(Items.flint_and_steel, 0, 1, 1, 2) };
private boolean hasMadeChest;
protected void func_143012_a(NBTTagCompound par1NBTTagCompound)
{
super.func_143012_a(par1NBTTagCompound);
par1NBTTagCompound.setBoolean("MCIS_createdChest", this.hasMadeChest);
}
protected void func_143011_b(NBTTagCompound par1NBTTagCompound)
{
super.func_143011_b(par1NBTTagCompound);
this.hasMadeChest = par1NBTTagCompound.getBoolean("MCIS_createdChest");
}
public static VillageComponentCandleshop buildComponent(StructureVillagePieces.Start villagePiece, List pieces, Random random, int p1, int p2, int p3, int p4, int p5)
{
StructureBoundingBox structureboundingbox = StructureBoundingBox.getComponentToAddBoundingBox(p1, p2, p3, 0, 0, 0, widX, heiY, lenZ, p4);
return (canVillageGoDeeper(structureboundingbox)) && (StructureComponent.findIntersecting(pieces, structureboundingbox) == null) ? new VillageComponentCandleshop(villagePiece, p5, random, structureboundingbox, p4) : null;
}
private static int widX = 9;
private static int heiY = 7;
private static int lenZ = 11;
public boolean addComponentParts(World world, Random random, StructureBoundingBox sbb)
{
if (this.averageGroundLevel < 0)
{
this.averageGroundLevel = getAverageGroundLevel(world, sbb);
if (this.averageGroundLevel < 0) {
return true;
}
this.boundingBox.offset(0, this.averageGroundLevel - this.boundingBox.maxY + 4, 0);
}
fillWithBlocks(world, sbb, 0, 2, 0, 6, 3, 6, Blocks.cobblestone, Blocks.cobblestone, false);
fillWithBlocks(world, sbb, 0, 4, 0, 6, 7, 6, Blocks.planks, Blocks.planks, false);
fillWithBlocks(world, sbb, 1, 2, 1, 5, 2, 5, Blocks.planks, Blocks.planks, false);
fillWithAir(world, sbb, 1, 3, 1, 5, 5, 5);
placeBlockAtCurrentPosition(world, Blocks.stone_stairs, getMetadataWithOffset(Blocks.stone_stairs, 3), 4, 2, -1, sbb);
placeDoorAtCurrentPosition(world, sbb, random, 4, 3, 0, getMetadataWithOffset(Blocks.wooden_door, 3));
for (int i = 0; i < 4; i++)
{
placeBlockAtCurrentPosition(world, Blocks.log, 0, 0, i + 2, 0, sbb);
placeBlockAtCurrentPosition(world, Blocks.log, 0, 6, i + 2, 0, sbb);
placeBlockAtCurrentPosition(world, Blocks.log, 0, 0, i + 2, 6, sbb);
placeBlockAtCurrentPosition(world, Blocks.log, 0, 6, i + 2, 6, sbb);
if ((i >= 1) && (i <= 4)) {
placeBlockAtCurrentPosition(world, Blocks.log, 0, 3, i + 2, 1, sbb);
}
}
for (int i = 0; i < 7; i++)
{
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, getMetadataWithOffset(Blocks.oak_stairs, 3), i, 6, -1, sbb);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, getMetadataWithOffset(Blocks.oak_stairs, 3), i, 7, 0, sbb);
}
for (int i = 0; i < 7; i++)
{
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, getMetadataWithOffset(Blocks.oak_stairs, 2), i, 6, 7, sbb);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, getMetadataWithOffset(Blocks.oak_stairs, 2), i, 7, 6, sbb);
}
fillWithBlocks(world, sbb, 1, 4, 0, 2, 5, 0, Blocks.glass_pane, Blocks.glass_pane, false);
placeBlockAtCurrentPosition(world, Blocks.wool, 14, 1, 3, 1, sbb);
placeBlockAtCurrentPosition(world, Blocks.wool, 14, 2, 3, 1, sbb);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, getMetadataWithOffset(Blocks.oak_stairs, 2) + 4, 3, 5, 2, sbb);
for (int i1 = 0; i1 < 2; i1++)
{
placeBlockAtCurrentPosition(world, Blocks.log, 0, i1 * 6, 4, 2, sbb);
placeBlockAtCurrentPosition(world, Blocks.glass_pane, 0, i1 * 6, 4, 3, sbb);
placeBlockAtCurrentPosition(world, Blocks.log, 0, i1 * 6, 4, 4, sbb);
}
placeBlockAtCurrentPosition(world, Blocks.planks, 1, 1, 3, 4, sbb);
placeBlockAtCurrentPosition(world, Blocks.planks, 1, 2, 3, 4, sbb);
placeBlockAtCurrentPosition(world, Blocks.planks, 1, 3, 3, 4, sbb);
placeBlockAtCurrentPosition(world, Blocks.planks, 1, 3, 3, 5, sbb);
for (int i2 = 1; i2 < 4; i2++) {
placeBlockAtCurrentPosition(world, Blocks.wooden_slab, 1, i2, 5, 5, sbb);
}
placeBlockAtCurrentPosition(world, Blocks.torch, 0, 4, 5, 1, sbb);
if (!this.hasMadeChest)
{
int i = getYWithOffset(1);
int j = getXWithOffset(5, 5);
int k = getZWithOffset(5, 5);
if (sbb.isVecInside(j, i, k))
{
this.hasMadeChest = true;
generateStructureChestContents(world, sbb, random, 5, 3, 5, candleshopChest, 1 + random.nextInt(3));
}
}
spawnVillagers(world, sbb, 2, 3, 5, 1);
return true;
}
public int getVillagerType(int i)
{
return 99;
}
}
And... ALL DONE, this code above is pretty self explanatory.
Now you can build your building in minecraft and use MCEdit to convert it into a schematic and turn it into code to be used.. or... you can do it manually.
And that's it.
If you have any issues, just say in the comments below.
Tags |
tools/tracking
2671296
6
modding-trouble---adding-village-components-forge-164
Create an account or sign in to comment.
I have an error while creating new world.
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 BetterWorld.village.VillageCreationHandler.buildComponent(VillageCreationHandler.java:44)
at cpw.mods.fml.common.registry.VillagerRegistry.getVillageComponent(VillagerRegistry.java:220)
net.minecraft.world.gen.structure.StructureVillagePieces.func_75083_a(StructureVillagePieces.java:136)
net.minecraft.world.gen.structure.StructureVillagePieces.getNextVillageComponent(StructureVillagePieces.java:175)
net.minecraft.world.gen.structure.StructureVillagePieces.getNextVillageStructureComponent(StructureVillagePieces.java:217)
net.minecraft.world.gen.structure.StructureVillagePieces.access$100(StructureVillagePieces.java:26)
net.minecraft.world.gen.structure.StructureVillagePieces$Village.getNextComponentPP(StructureVillagePieces.java:1639)
net.minecraft.world.gen.structure.StructureVillagePieces$Path.buildComponent(StructureVillagePieces.java:1362)
at net.minecraft.world.gen.structure.MapGenVillage$Start.<init>(MapGenVillage.java:129)
at net.minecraft.world.gen.structure.MapGenVillage.getStructureStart(MapGenVillage.java:93)
Error is in that line:
obj = meth.invoke(null, new Object[] { startPiece, pieces, random, Integer.valueOf(p1), Integer.valueOf(p2), Integer.valueOf(p3), Integer.valueOf(p4), Integer.valueOf(p5) });
I have no idea how to get my head around 1.7.2 atm, it is just so tiring.
I might be able to work on it very soon thoug.