Minecraft Blogs / Tutorial

Modding Trouble - Adding Village Components [Forge 1.7.2]

  • 3,167 views, 2 today
  • 5
  • 3
  • 9
Neuroticcheeze1101's Avatar Neuroticcheeze1101
Level 60 : High Grandmaster Button Pusher
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:
ModTutorial
addVillagePiece(VillageComponentBakery.class, "ViBk");
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.
So now we add these methods below:

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);
}



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);
}
}


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;
}
}


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

Create an account or sign in to comment.

1
05/12/2016 9:12 am
Level 33 : Artisan Modder
Nulcheck
Nulcheck's Avatar
Wow, cool. Worked first try no problem, when does that ever happen in programming? lol. Thanks for this!
1
01/14/2016 6:42 pm
Level 1 : New Miner
invincible legend
invincible legend's Avatar
someone plz help
1
01/14/2016 6:41 pm
Level 1 : New Miner
invincible legend
invincible legend's Avatar
well... i had some troble because i don't know if this will work with eclipse?
1
10/05/2014 9:10 am
Level 88 : Elite Engineer
TheLarsinator
TheLarsinator's Avatar
You should update this :D Not many modders know that this is possible
1
10/08/2014 7:11 am
Level 60 : High Grandmaster Button Pusher
Neuroticcheeze1101
Neuroticcheeze1101's Avatar
Updated. :D
1
10/08/2014 7:38 am
Level 88 : Elite Engineer
TheLarsinator
TheLarsinator's Avatar
Haha, awesome! Didn't take very long to figure out myself :D
1
10/08/2014 9:15 pm
Level 60 : High Grandmaster Button Pusher
Neuroticcheeze1101
Neuroticcheeze1101's Avatar
Hah, no worries. It looked like just the creation handler code was completely different.
1
05/03/2014 2:06 pm
Level 1 : New Miner
SSslimer
SSslimer's Avatar
It's not working me for 1.7.2.
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) });
1
05/04/2014 1:59 am
Level 60 : High Grandmaster Button Pusher
Neuroticcheeze1101
Neuroticcheeze1101's Avatar
I'm afraid it's for 1.6.4

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.
Planet Minecraft

Website

© 2010 - 2024
www.planetminecraft.com

Welcome