Skip to content
This repository was archived by the owner on Feb 16, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/main/resources/forge-1.20.1/biome.definition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ templates:
- template: biome/biome.json.ftl # loaded from datapack generator
writer: json
name: "@MODDATAROOT/worldgen/biome/@registryname.json"
- template: biome/configured_tree.json.ftl
- template: biome/configured_tree.json.ftl # loaded from datapack generator
writer: json
condition: hasTrees()
name: "@MODDATAROOT/worldgen/configured_feature/@registryname_tree.json"
- template: biome/placed_tree.json.ftl
- template: biome/placed_tree.json.ftl # loaded from datapack generator
writer: json
condition: hasTrees()
name: "@MODDATAROOT/worldgen/placed_feature/@registryname_tree.json"
Expand All @@ -25,6 +25,10 @@ global_templates:
writer: java
condition: "${w.getGElementsOfType('biome')?filter(e -> e.spawnBiome || e.spawnInCaves || e.spawnBiomeNether)?size != 0}"
name: "@SRCROOT/@BASEPACKAGEPATH/init/@JavaModNameBiomes.java"
- template: biome/mixin_noisegeneratorsettings.java.ftl
writer: java
condition: "${w.getGElementsOfType('biome')?filter(e -> e.spawnBiome || e.spawnInCaves || e.spawnBiomeNether)?size != 0}"
name: "@SRCROOT/@BASEPACKAGEPATH/mixin/NoiseGeneratorSettingsMixin.java"

tags:
- tag: BIOMES:minecraft:has_structure/mineshaft
Expand Down
15 changes: 13 additions & 2 deletions src/main/resources/forge-1.20.1/generator.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Minecraft Forge for @minecraft (@buildfileversion)
status: legacy
buildfileversion: 47.4.0
subversion: 1.3 # force setup re-run to update build script to use MDG
subversion: 1.4 # force setup re-run to update build script to downlaod Mixin Extras

import:
- datapack-1.20.1
Expand All @@ -25,8 +25,14 @@ import_formatter:
Nullable: javax.annotation
Codec: com.mojang.serialization
SoundEvent: net.minecraft.sounds
Blocks: net.minecraft.world.level.block
Items: net.minecraft.world.item
Multimap: com.google.common.collect
ImmutableSet: com.google.common.collect
Iterables: com.google.common.collect
Attributes: net.minecraft.world.entity.ai.attributes
Keyframe: net.minecraft.client.animation
Dynamic: com.mojang.serialization

# base generator roots
source_root: "@WORKSPACEROOT/src/main/java"
Expand Down Expand Up @@ -79,11 +85,16 @@ base_templates:
writer: file
name: "@RESROOT/META-INF/accesstransformer.cfg"
condition_any:
- ${w.hasElementsOfType('feature')}
- "${w.getGElementsOfType('biome')?filter(e -> e.spawnBiome || e.spawnInCaves || e.spawnBiomeNether)?size != 0}"
- "${w.hasElementsOfType('feature')}"
- template: elementinits/javamodels.java.ftl
name: "@SRCROOT/@BASEPACKAGEPATH/init/@JavaModNameModels.java"
condition: hasJavaModels()
- template: modbase/mixin.json.ftl
writer: json
condition_any:
- "${w.getGElementsOfType('biome')?filter(e -> e.spawnBiome || e.spawnInCaves || e.spawnBiomeNether)?size != 0}"
name: "@RESROOT/@modid.mixins.json"

sources_setup_tasks:
- task: copy_models
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<#--
# MCreator (https://mcreator.net/)
# Copyright (C) 2012-2020, Pylo
# Copyright (C) 2020-2023, Pylo, opensource contributors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# Additional permission for code generator templates (*.ftl files)
#
# As a special exception, you may create a larger work that contains part or
# all of the MCreator code generator templates (*.ftl files) and distribute
# that work under terms of your choice, so long as that work isn't itself a
# template for code generation. Alternatively, if you modify or redistribute
# the template itself, you may (at your option) remove this special exception,
# which will cause the template and the resulting code generator output files
# to be licensed under the GNU General Public License without this special
# exception.
-->

<#-- @formatter:off -->

package ${package}.mixin;

import org.spongepowered.asm.mixin.Unique;

@Mixin(NoiseGeneratorSettings.class) public class NoiseGeneratorSettingsMixin implements ${JavaModName}Biomes.${JavaModName}NoiseGeneratorSettings {

@Unique private Holder<DimensionType> ${modid}_dimensionTypeReference;

@WrapMethod(method = "surfaceRule")
public SurfaceRules.RuleSource surfaceRule(Operation<SurfaceRules.RuleSource> original) {
SurfaceRules.RuleSource retval = original.call();
if (this.${modid}_dimensionTypeReference != null) {
retval = ${JavaModName}Biomes.adaptSurfaceRule(retval, this.${modid}_dimensionTypeReference);
}
return retval;
}

@Override public void set${modid}DimensionTypeReference(Holder<DimensionType> dimensionType) {
this.${modid}_dimensionTypeReference = dimensionType;
}

}
177 changes: 87 additions & 90 deletions src/main/resources/forge-1.20.1/templates/elementinits/biomes.java.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
package ${package}.init;

import com.mojang.datafixers.util.Pair;
import com.google.common.base.Suppliers;

<#assign spawn_overworld = biomes?filter(biome -> biome.spawnBiome)>
<#assign spawn_overworld_caves = biomes?filter(biome -> biome.spawnInCaves)>
Expand All @@ -47,15 +48,14 @@ import com.mojang.datafixers.util.Pair;

@SubscribeEvent public static void onServerAboutToStart(ServerAboutToStartEvent event) {
MinecraftServer server = event.getServer();
Registry<DimensionType> dimensionTypeRegistry = server.registryAccess().registryOrThrow(Registries.DIMENSION_TYPE);
Registry<LevelStem> levelStemTypeRegistry = server.registryAccess().registryOrThrow(Registries.LEVEL_STEM);
Registry<Biome> biomeRegistry = server.registryAccess().registryOrThrow(Registries.BIOME);

for (LevelStem levelStem : levelStemTypeRegistry.stream().toList()) {
DimensionType dimensionType = levelStem.type().value();
Holder<DimensionType> dimensionType = levelStem.type();

<#if spawn_overworld?has_content || spawn_overworld_caves?has_content>
if(dimensionType == dimensionTypeRegistry.getOrThrow(BuiltinDimensionTypes.OVERWORLD)) {
if (dimensionType.is(BuiltinDimensionTypes.OVERWORLD)) {
ChunkGenerator chunkGenerator = levelStem.generator();

// Inject biomes to biome source
Expand Down Expand Up @@ -110,52 +110,14 @@ import com.mojang.datafixers.util.Pair;
chunkGenerator.generationSettingsGetter.apply(biome).features(), true));
}

// Inject surface rules
if(chunkGenerator instanceof NoiseBasedChunkGenerator noiseGenerator) {
NoiseGeneratorSettings noiseGeneratorSettings = noiseGenerator.settings.value();
SurfaceRules.RuleSource currentRuleSource = noiseGeneratorSettings.surfaceRule();
if (currentRuleSource instanceof SurfaceRules.SequenceRuleSource sequenceRuleSource) {
List<SurfaceRules.RuleSource> surfaceRules = new ArrayList<>(sequenceRuleSource.sequence());

<#list spawn_overworld_caves as biome>
addSurfaceRule(surfaceRules, 1, anySurfaceRule(
ResourceKey.create(Registries.BIOME, ResourceLocation.fromNamespaceAndPath("${modid}", "${biome.getModElement().getRegistryName()}")),
${mappedBlockToBlockStateCode(biome.groundBlock)},
${mappedBlockToBlockStateCode(biome.undergroundBlock)},
${mappedBlockToBlockStateCode(biome.getUnderwaterBlock())}
));
</#list>

<#list spawn_overworld as biome>
addSurfaceRule(surfaceRules, 1, preliminarySurfaceRule(
ResourceKey.create(Registries.BIOME, ResourceLocation.fromNamespaceAndPath("${modid}", "${biome.getModElement().getRegistryName()}")),
${mappedBlockToBlockStateCode(biome.groundBlock)},
${mappedBlockToBlockStateCode(biome.undergroundBlock)},
${mappedBlockToBlockStateCode(biome.getUnderwaterBlock())}
));
</#list>

NoiseGeneratorSettings moddedNoiseGeneratorSettings = new NoiseGeneratorSettings(
noiseGeneratorSettings.noiseSettings(),
noiseGeneratorSettings.defaultBlock(),
noiseGeneratorSettings.defaultFluid(),
noiseGeneratorSettings.noiseRouter(),
SurfaceRules.sequence(surfaceRules.toArray(SurfaceRules.RuleSource[]::new)),
noiseGeneratorSettings.spawnTarget(),
noiseGeneratorSettings.seaLevel(),
noiseGeneratorSettings.disableMobGeneration(),
noiseGeneratorSettings.aquifersEnabled(),
noiseGeneratorSettings.oreVeinsEnabled(),
noiseGeneratorSettings.useLegacyRandomSource()
);
noiseGenerator.settings = new Holder.Direct<>(moddedNoiseGeneratorSettings);
}
((${JavaModName}NoiseGeneratorSettings)(Object)noiseGenerator.settings.value()).set${modid}DimensionTypeReference(dimensionType);
}
}
</#if>

<#if spawn_nether?has_content>
if(dimensionType == dimensionTypeRegistry.getOrThrow(BuiltinDimensionTypes.NETHER)) {
if (dimensionType.is(BuiltinDimensionTypes.NETHER)) {
ChunkGenerator chunkGenerator = levelStem.generator();

// Inject biomes to biome source
Expand Down Expand Up @@ -195,43 +157,81 @@ import com.mojang.datafixers.util.Pair;
chunkGenerator.generationSettingsGetter.apply(biome).features(), true));
}

// Inject surface rules
if(chunkGenerator instanceof NoiseBasedChunkGenerator noiseGenerator) {
NoiseGeneratorSettings noiseGeneratorSettings = noiseGenerator.settings.value();
SurfaceRules.RuleSource currentRuleSource = noiseGeneratorSettings.surfaceRule();
if (currentRuleSource instanceof SurfaceRules.SequenceRuleSource sequenceRuleSource) {
List<SurfaceRules.RuleSource> surfaceRules = new ArrayList<>(sequenceRuleSource.sequence());

<#list spawn_nether as biome>
addSurfaceRule(surfaceRules, 2, anySurfaceRule(
ResourceKey.create(Registries.BIOME, ResourceLocation.fromNamespaceAndPath("${modid}", "${biome.getModElement().getRegistryName()}")),
${mappedBlockToBlockStateCode(biome.groundBlock)},
${mappedBlockToBlockStateCode(biome.undergroundBlock)},
${mappedBlockToBlockStateCode(biome.getUnderwaterBlock())}
));
</#list>

NoiseGeneratorSettings moddedNoiseGeneratorSettings = new NoiseGeneratorSettings(
noiseGeneratorSettings.noiseSettings(),
noiseGeneratorSettings.defaultBlock(),
noiseGeneratorSettings.defaultFluid(),
noiseGeneratorSettings.noiseRouter(),
SurfaceRules.sequence(surfaceRules.toArray(SurfaceRules.RuleSource[]::new)),
noiseGeneratorSettings.spawnTarget(),
noiseGeneratorSettings.seaLevel(),
noiseGeneratorSettings.disableMobGeneration(),
noiseGeneratorSettings.aquifersEnabled(),
noiseGeneratorSettings.oreVeinsEnabled(),
noiseGeneratorSettings.useLegacyRandomSource()
);
noiseGenerator.settings = new Holder.Direct<>(moddedNoiseGeneratorSettings);
}
((${JavaModName}NoiseGeneratorSettings)(Object)noiseGenerator.settings.value()).set${modid}DimensionTypeReference(dimensionType);
}
}
</#if>
}
}

public static SurfaceRules.RuleSource adaptSurfaceRule(SurfaceRules.RuleSource currentRuleSource, Holder<DimensionType> dimensionType) {
<#if spawn_overworld?has_content || spawn_overworld_caves?has_content>
if (dimensionType.is(BuiltinDimensionTypes.OVERWORLD)) return injectOverworldSurfaceRules(currentRuleSource);
</#if>

<#if spawn_nether?has_content>
if (dimensionType.is(BuiltinDimensionTypes.NETHER)) return injectNetherSurfaceRules(currentRuleSource);
</#if>

return currentRuleSource;
}

<#if spawn_overworld?has_content || spawn_overworld_caves?has_content>
private static SurfaceRules.RuleSource injectOverworldSurfaceRules(SurfaceRules.RuleSource currentRuleSource) {
List<SurfaceRules.RuleSource> customSurfaceRules = new ArrayList<>();

<#list spawn_overworld_caves as biome>
customSurfaceRules.add(anySurfaceRule(
ResourceKey.create(Registries.BIOME, ResourceLocation.fromNamespaceAndPath("${modid}", "${biome.getModElement().getRegistryName()}")),
${mappedBlockToBlockStateCode(biome.groundBlock)},
${mappedBlockToBlockStateCode(biome.undergroundBlock)},
${mappedBlockToBlockStateCode(biome.getUnderwaterBlock())}
));
</#list>

<#list spawn_overworld as biome>
customSurfaceRules.add(preliminarySurfaceRule(
ResourceKey.create(Registries.BIOME, ResourceLocation.fromNamespaceAndPath("${modid}", "${biome.getModElement().getRegistryName()}")),
${mappedBlockToBlockStateCode(biome.groundBlock)},
${mappedBlockToBlockStateCode(biome.undergroundBlock)},
${mappedBlockToBlockStateCode(biome.getUnderwaterBlock())}
));
</#list>

if (currentRuleSource instanceof SurfaceRules.SequenceRuleSource sequenceRuleSource) {
customSurfaceRules.addAll(sequenceRuleSource.sequence());
return SurfaceRules.sequence(customSurfaceRules.toArray(SurfaceRules.RuleSource[]::new));
} else {
customSurfaceRules.add(currentRuleSource);
return SurfaceRules.sequence(customSurfaceRules.toArray(SurfaceRules.RuleSource[]::new));
}
}
</#if>

<#if spawn_nether?has_content>
private static SurfaceRules.RuleSource injectNetherSurfaceRules(SurfaceRules.RuleSource currentRuleSource) {
List<SurfaceRules.RuleSource> customSurfaceRules = new ArrayList<>();

<#list spawn_nether as biome>
customSurfaceRules.add(anySurfaceRule(
ResourceKey.create(Registries.BIOME, ResourceLocation.fromNamespaceAndPath("${modid}", "${biome.getModElement().getRegistryName()}")),
${mappedBlockToBlockStateCode(biome.groundBlock)},
${mappedBlockToBlockStateCode(biome.undergroundBlock)},
${mappedBlockToBlockStateCode(biome.getUnderwaterBlock())}
));
</#list>

if (currentRuleSource instanceof SurfaceRules.SequenceRuleSource sequenceRuleSource) {
customSurfaceRules.addAll(sequenceRuleSource.sequence());
return SurfaceRules.sequence(customSurfaceRules.toArray(SurfaceRules.RuleSource[]::new));
} else {
customSurfaceRules.add(currentRuleSource);
return SurfaceRules.sequence(customSurfaceRules.toArray(SurfaceRules.RuleSource[]::new));
}
}
</#if>

<#if spawn_overworld?has_content>
private static SurfaceRules.RuleSource preliminarySurfaceRule(ResourceKey<Biome> biomeKey, BlockState groundBlock, BlockState undergroundBlock, BlockState underwaterBlock) {
return SurfaceRules.ifTrue(SurfaceRules.isBiome(biomeKey),
Expand All @@ -257,17 +257,21 @@ import com.mojang.datafixers.util.Pair;
<#if spawn_nether?has_content || spawn_overworld_caves?has_content>
private static SurfaceRules.RuleSource anySurfaceRule(ResourceKey<Biome> biomeKey, BlockState groundBlock, BlockState undergroundBlock, BlockState underwaterBlock) {
return SurfaceRules.ifTrue(SurfaceRules.isBiome(biomeKey),
SurfaceRules.sequence(
SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(0, false, 0, CaveSurface.FLOOR),
SurfaceRules.ifTrue(SurfaceRules.yBlockCheck(VerticalAnchor.aboveBottom(5), 0),
SurfaceRules.ifTrue(SurfaceRules.not(SurfaceRules.yBlockCheck(VerticalAnchor.belowTop(5), 0)),
SurfaceRules.sequence(
SurfaceRules.ifTrue(SurfaceRules.waterBlockCheck(-1, 0),
SurfaceRules.state(groundBlock)
SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(0, false, 0, CaveSurface.FLOOR),
SurfaceRules.sequence(
SurfaceRules.ifTrue(SurfaceRules.waterBlockCheck(-1, 0),
SurfaceRules.state(groundBlock)
),
SurfaceRules.state(underwaterBlock)
)
),
SurfaceRules.state(underwaterBlock)
SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(0, true, 0, CaveSurface.FLOOR),
SurfaceRules.state(undergroundBlock)
)
)
),
SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(0, true, 0, CaveSurface.FLOOR),
SurfaceRules.state(undergroundBlock)
)
)
);
Expand All @@ -279,15 +283,8 @@ import com.mojang.datafixers.util.Pair;
parameters.add(point);
}

private static void addSurfaceRule(List<SurfaceRules.RuleSource> surfaceRules, int index, SurfaceRules.RuleSource rule) {
if (!surfaceRules.contains(rule)) {
<#-- Make sure index is within list bounds - improved mod intercompatibility - #5204 -->
if (index >= surfaceRules.size()) {
surfaceRules.add(rule);
} else {
surfaceRules.add(index, rule);
}
}
public interface ${JavaModName}NoiseGeneratorSettings {
void set${modid}DimensionTypeReference(Holder<DimensionType> dimensionType);
}

}
Expand Down
20 changes: 20 additions & 0 deletions src/main/resources/forge-1.20.1/templates/modbase/mixin.json.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<#assign mixins = []>
<#if w.getGElementsOfType('biome')?filter(e -> e.spawnBiome || e.spawnInCaves || e.spawnBiomeNether)?size != 0>
<#assign mixins = mixins + ['NoiseGeneratorSettingsMixin']>
</#if>

{
"required": true,
"package": "${package}.mixin",
"compatibilityLevel": "JAVA_17",
"refmap": "${modid}.refmap.json",
"mixins": [
<#list mixins as mixin>"${mixin}"<#sep>,</#list>
],
"client": [
],
"injectors": {
"defaultRequire": 1
},
"minVersion": "0.8.4"
}
Loading