After covering some topics regarding Block Entities, in this tutorial I will show you how to add ore generation for your blocks into your Architectury mod. The process is similar for other world features as well, I will give some details regarding this where relevant.
Additional Resources
The Tutorial Mod used here can be found on GitHub (state after this tutorial).
A video version can be found below.
Contents
Configured Features
Any type of world generation in Minecraft, including ore generation, requires two types of definitions. The first one we need to create is a configured feature. A configured feature tells the game what structure to generate into the world. It does however not tell the game where to spawn it, for this we require then a placed feature, as show below. For our Ruby Ore we place the following configuration in a file in the resources/data/<mod_id>/worldgen/configured_features folder, which I explain below:
{
"type": "minecraft:ore",
"config": {
"discard_chance_on_air_exposure": 0.5,
"size": 8,
"targets": [
{
"state": {
"Name": "tutorial_mod:ruby_ore"
},
"target": {
"predicate_type": "minecraft:tag_match",
"tag": "minecraft:stone_ore_replaceables"
}
},
{
"state": {
"Name": "tutorial_mod:deepslate_ruby_ore"
},
"target": {
"predicate_type": "minecraft:tag_match",
"tag": "minecraft:deepslate_ore_replaceables"
}
}
]
}
}
The first thing we need to define in a configured feature is it’s type. For a list of all possible types, see the corresponding wiki page. In our case we want to use the minecraft:ore feature. After this we need to define the actual configuration for this feature, in case of an ore feature consisting of three parts: The first thing is the discard_chance_on_air_exposure. This defines the probability that an attempted spawn of this feature is discarded if one of it’s blocks is in contact with an air block. Furthermore we need to define the size of the ore vein generated here. This wiki page gives you the number of blocks corresponding to the possible values here.
Finally we need to give an array of targets. Each target represents a possible block to spawn whilst generating this feature, combined with a condition under which it is selected. In our case we have two targets: One for our regular ore, which can generate if it replaces a block tagged with the minecraft:stone_ore_replaceables tag, and a second one for the deepslate ore, which generates for blocks of the minecraft:deepslate_ore_replaceables tag.
Placed Features
As I explained before, a configured feature just tells the game what to generate. Next we want to define how the game should generate said feature. For this we are going to define a placed feature in the resources/data/<mod_id>/worldgen/placed_features folder. The file we create here contains something like this:
{
"feature": "tutorial_mod:ore_ruby",
"placement": [
{
"type": "minecraft:count",
"count": 3
},
{
"type": "minecraft:in_square"
},
{
"type": "minecraft:height_range",
"height": {
"type": "minecraft:uniform",
"max_inclusive": {
"absolute": 20
},
"min_inclusive": {
"absolute": -64
}
}
},
{
"type": "minecraft:biome"
}
]
}
The first thing we define here is the configured feature this placed feature is related to. The next block defines the modifiers for the placement. You can find a listing of all possible modifiers on the wiki. The first modifier specifies the number of generation attempts per chunk. With the second modifier we specify that the distribution on the x and z axis should be randomized. Next we specify the y range in which our feature should attempt to generate. For this we need to specify both a lower and upper bound as well as the distribution type with which values from the given range are chosen. Finally we specify the biome modifier, which restricts the generation attempts to biomes we will add this feature to next.
Add Ore Generation
Now that we have defined the feature we want to add to the world, we need to tell the game in which biomes to generate it. If we wanted to use the vanilla way for this, we would need to overwrite the biome definitions of the game through our datapack. We would however eliminate compatibility with other mods with this approach, since we would also overwrite their changes to the world generation. Therefore we need to go through the individual modloaders to add our feature during the runtime of the game.
Fabric
For FabricMC, we can do this through the BiomeModifications provided by the FabricAPI. This class allows us to easily add features and mob spawnings to existing biomes. It also allows us to remove or modify vanilla features, but I will cover this in a future part. For now we just want to add our ore generation feature to all overworld biomes. We can achieve this by adding the following line at the end of our Fabric mod’s initialization method:
BiomeModifications.addFeature(
BiomeSelectors.foundInOverworld(),
GenerationStep.Decoration.UNDERGROUND_ORES,
ResourceKey.create(
Registries.PLACED_FEATURE,
ResourceLocation.fromNamespaceAndPath(TutorialMod.MOD_ID, "ore_ruby")
)
);
First we need to provide a Predicate that tells Fabric to which biomes we want to add our feature. The BiomeSelectors class provides methods to select biomes by their keys, using a biome tag or simply select all biomes in a certain dimension. Next we need to provide the GenerationStep during which our feature should be generated. Since we want to add an ore, we use the UNDERGROUND_ORES step here, for vegetation for example you would use the VEGETAL_DECORATION step. Finally we need to provide a ResourceKey for our feature. This tells the game where to find the json file we created earlier.
NeoForge
In contrast to Fabric, NeoForge requires us to define our modifications through json files. Those need to be placed in the resources/data/<mod_id>/neoforge/biome_modifier directory of our NeoForge submodule. The content of such a modification file describes the same things we have as parameters in the fabric method, in our case it looks like this:
{
"type": "neoforge:add_features",
"biomes": "#minecraft:is_overworld",
"features": "tutorial_mod:ore_ruby",
"step": "underground_ores"
}
The type describes what kind of modification this file contains, in our case the addition of a feature. Next we define which biomes we want to modify, in our case all biomes that have the minecraft:is_overworld tag applied to them. Furthermore we specify the feature we want to add and finally the step of generation we want to add our feature to, similar to Fabric.
Minecraft
With that we have added everything we need to add so that our ore generates in the world. An example of our generated ore can be seen in the picture attached below:

Video
Please accept YouTube cookies to play this video. By accepting you will be accessing content from YouTube, a service provided by an external third party.
If you accept this notice, your choice will be saved and the page will refresh.
Related Content
Check out the entire series here.