Minecraft Modding: Custom Villages

Background


Villages in Minecraft are actually one of the most complicated parts of the game logic. The generation is semi-random but has certain organization and then the villagers have complicated behaviors and "professions" that can change according to the size of the villages.

For more information on villages, see the Official Wiki entry on villages.

It is common for modders to want to either customize villages either in terms of the structures or the villagers themselves.

Replacing Construction Blocks In Vanilla Villages


There is an event called BiomeEvent.GetVillageBlockID which can be used to replace construction blocks (not the crops and stuff, but rather the walls, planks, stairs) in villages.

Important: If you handle the event make sure you return a Result.DENY in order for your replacement to be used.

Getting Villages To Generate In Different Biomes


The MapGenVillage class has a public static list of viable biomes called VILLAGE_SPAWN_BIOMES. You can edit it directly in the init loading phase of your mod using any standard List methods such as add(), remove(), clear() etc.

Adding Custom Village Structure "Pieces" To Vanilla Villages


A vlllage "piece" is a whole building like a church or other element like a field.

You can add new pieces to villages by:
  1. Create custom piece: creating a custom class that extends and implements the abstract class StructureVillagePieces.Village class. Some vanilla examples are Church, Field1, etc. At a minimum you need to implement the addComponentParts() method.
  2. Register piece: Important: Your custom piece needs to be registered in the init phase of loading with the MapGenStructureIO.registerStructureComponent() method.
  3. Create custom creation handler: After creating the village piece class you need to create a class that implements the IVillageCreationHandler interface. In the handler class you need to implement the getVillagePieceWeight(), the getComponentClass() and getBuildComponent() method to return your village piece. 
  4. Register creation handlerImportant: Your IVillageCreationHandler must be registered in your init loading phase using the VillageRegistry.getInstance().registerVillageCreationHandler() method. The registration requires you to set a "weight" for the chance it will be generated. You can understand the weights but looking at the vanilla village piece weights.
See example code.

Creating Full Custom Villages


If you're ambitious you might want to do more drastic customization of villages. To do this, you would:
  1.  Create map gen class: Create your own class that copies most of the code from the MapGenVillage and also changes the things you want to change. See example code.
  2. Associate it with chunk generator: For example, you can replace the villageGenerator field (which is public) in the ChunkGeneratorOverworld, or you can make a custom IChunkGenerator implementation if you're doing even more customization to the world generation. See example code where the villageGenerator field is an instance of my custom map gen.
  3. Register the structure: In the init loading phase of your mod, use the MapGenStructureIO.registerStructure() method to register the structure. See example code.

Custom Villagers


5 comments:

  1. Is there any way to have my custom entities spawn in the custom village?

    ReplyDelete
    Replies
    1. Yes it's possible :
      https://nsm09.casimages.com/img/2018/07/27//18072706141216030915824608.png
      In the screenshot you can see bandits villagers in the village.

      I used this to a component village to put the bandit entity in village :
      this.spawnVillagers(par1World, par3StructureBoundingBox, 2, 1, 3, 1, false);

      the Component is extended to ComponentVillageBandit copied from ComponentVillage that contains the spawnVillagers method. The entity is created here.

      You can also put entities in structures :
      https://nsm09.casimages.com/img/2018/07/27//18072706141116030915824607.png
      In this screenshot 2 ships appears with blue knights and explorers.

      I used this to put the explorer entity :
      EntityExplorer Explorer1 = new EntityExplorer(world);
      Explorer1.setLocationAndAngles((double)i + 4.5D, (double)j + 4.5D, (double)k + 2.5D, 0.0F, 0.0F);
      Explorer1.initCreature();
      world.spawnEntityInWorld(Explorer1);

      Delete
  2. Do you HAVE to your own implementation of IChunkGenerator, or can you just extend ChunkGeneratorOverworld? I want to add my own village to the overworld, but villageGenerator is a private field, and I don't know how to access it without copying and pasting the entire ChunkGeneratorOverworld code. And if I make my own chunk generator, how do I register it? Or rather, how do I get minecraft to use it over the overworld one. I can't find anything about it in your code.

    ReplyDelete
  3. What version of minecraft is this?

    ReplyDelete