[Change] WorldPresets are configured through BiomeSources

This commit is contained in:
Frank 2022-06-23 23:48:36 +02:00
parent 2a03b46a98
commit 877691011f
39 changed files with 1092 additions and 723 deletions

View file

@ -6,6 +6,9 @@ import org.betterx.bclib.api.v2.generator.BCLibEndBiomeSource;
import org.betterx.bclib.api.v2.generator.BCLibNetherBiomeSource;
import org.betterx.bclib.api.v2.generator.GeneratorOptions;
import org.betterx.bclib.api.v2.levelgen.LevelGenEvents;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeBuilder;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.bclib.api.v2.levelgen.features.blockpredicates.Types;
import org.betterx.bclib.api.v2.levelgen.features.placement.PlacementModifiers;
import org.betterx.bclib.api.v2.levelgen.structures.TemplatePiece;
@ -22,6 +25,8 @@ import org.betterx.worlds.together.tag.v3.TagManager;
import org.betterx.worlds.together.world.WorldConfig;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Blocks;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.ModInitializer;
@ -65,25 +70,78 @@ public class BCLib implements ModInitializer {
PlacementModifiers.ensureStaticInitialization();
Configs.save();
/*if (isDevEnvironment()) {
Biome.BiomeBuilder builder = new Biome.BiomeBuilder()
if (isDevEnvironment()) {
BCLBiome theYellow = BCLBiomeBuilder
.start(makeID("the_yellow"))
.precipitation(Biome.Precipitation.NONE)
.temperature(1.0f)
.downfall(1.0f)
.mobSpawnSettings(new MobSpawnSettings.Builder().build())
.specialEffects(new BiomeSpecialEffects.Builder().fogColor(0xff00ff)
.waterColor(0xff00ff)
.waterFogColor(0xff00ff)
.skyColor(0xff00ff)
.build())
.generationSettings(new BiomeGenerationSettings.Builder().build());
.wetness(1.0f)
.fogColor(0xFFFF00)
.waterColor(0x777700)
.waterFogColor(0xFFFF00)
.skyColor(0xAAAA00)
.addNetherClimateParamater(-1, 1)
.surface(Blocks.YELLOW_CONCRETE)
.build();
BiomeAPI.registerEndLandBiome(theYellow);
Biome biome = builder.build();
ResourceLocation loc = makeID("testbiome");
biome = Registry.register(BuiltinRegistries.BIOME, loc, biome);
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(biome).orElseThrow();
NetherBiomeData.addNetherBiome(key, Climate.parameters(-1, 1, 0, 0, 0, 0, 0));
}*/
BCLBiome theBlue = BCLBiomeBuilder
.start(makeID("the_blue"))
.precipitation(Biome.Precipitation.NONE)
.temperature(1.0f)
.wetness(1.0f)
.fogColor(0x0000FF)
.waterColor(0x000077)
.waterFogColor(0x0000FF)
.skyColor(0x0000AA)
.addNetherClimateParamater(-1, 1)
.surface(Blocks.LIGHT_BLUE_CONCRETE)
.build();
BiomeAPI.registerEndLandBiome(theBlue);
BCLBiome theGray = BCLBiomeBuilder
.start(makeID("the_gray"))
.precipitation(Biome.Precipitation.NONE)
.temperature(1.0f)
.wetness(1.0f)
.fogColor(0xFFFFFF)
.waterColor(0x777777)
.waterFogColor(0xFFFFFF)
.skyColor(0xAAAAAA)
.addNetherClimateParamater(-1, 1)
.surface(Blocks.GRAY_CONCRETE)
.build();
BiomeAPI.registerEndVoidBiome(theGray);
BCLBiome theOrange = BCLBiomeBuilder
.start(makeID("the_orange"))
.precipitation(Biome.Precipitation.NONE)
.temperature(1.0f)
.wetness(1.0f)
.fogColor(0xFF7700)
.waterColor(0x773300)
.waterFogColor(0xFF7700)
.skyColor(0xAA7700)
.addNetherClimateParamater(-1, 1.1f)
.surface(Blocks.ORANGE_CONCRETE)
.build();
BiomeAPI.registerNetherBiome(theOrange);
BCLBiome thePurple = BCLBiomeBuilder
.start(makeID("the_purple"))
.precipitation(Biome.Precipitation.NONE)
.temperature(1.0f)
.wetness(1.0f)
.fogColor(0xFF00FF)
.waterColor(0x770077)
.waterFogColor(0xFF00FF)
.skyColor(0xAA00AA)
.addNetherClimateParamater(-1.1f, 1)
.surface(Blocks.PURPLE_CONCRETE)
.build();
BiomeAPI.registerNetherBiome(thePurple);
}
}
public static boolean isDevEnvironment() {

View file

@ -6,21 +6,14 @@ import org.betterx.bclib.api.v2.datafixer.MigrationProfile;
import org.betterx.bclib.api.v2.generator.GeneratorOptions;
import org.betterx.bclib.api.v2.levelgen.LevelGenUtil;
import org.betterx.bclib.config.Configs;
import org.betterx.bclib.util.MHelper;
import com.mojang.serialization.Dynamic;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import java.util.Optional;
public final class BCLibPatch {
public static void register() {
@ -94,60 +87,60 @@ final class BiomeSourcePatch extends ForcedLevelPatch {
RegistryOps<Tag> registryOps,
ResourceKey<LevelStem> dimensionKey
) {
final long seed = worldGenSettings.contains("seed")
? worldGenSettings.getLong("seed")
: MHelper.RANDOM.nextLong();
final boolean genStructures = !worldGenSettings.contains("generate_features") || worldGenSettings.getBoolean(
"generate_features");
final boolean genBonusChest = worldGenSettings.contains("bonus_chest") && worldGenSettings.getBoolean(
"bonus_chest");
boolean result = false;
CompoundTag dimensionTag = dimensions.getCompound(dimensionKey.location().toString());
Optional<WorldGenSettings> oWorldGen = WorldGenSettings.CODEC
.parse(new Dynamic<>(registryOps, worldGenSettings))
.result();
Optional<LevelStem> oLevelStem = LevelStem.CODEC
.parse(new Dynamic<>(registryOps, dimensionTag))
.resultOrPartial(BCLib.LOGGER::error);
Optional<ChunkGenerator> netherGenerator = oLevelStem.map(l -> l.generator());
int biomeSourceVersion = LevelGenUtil.getBiomeVersionForGenerator(netherGenerator.orElse(null));
int targetVersion = LevelGenUtil.getBiomeVersionForCurrentWorld(dimensionKey);
if (biomeSourceVersion != targetVersion) {
Optional<Holder<LevelStem>> refLevelStem = LevelGenUtil.referenceStemForVersion(
dimensionKey,
targetVersion,
registryAccess,
oWorldGen.map(g -> g.seed()).orElse(seed),
oWorldGen.map(g -> g.generateStructures()).orElse(genStructures),
oWorldGen.map(g -> g.generateBonusChest()).orElse(genBonusChest)
);
BCLib.LOGGER.warning("The world uses the BiomeSource Version " + biomeSourceVersion + " but should have " + targetVersion + ".");
BCLib.LOGGER.warning("Dimension: " + dimensionKey);
BCLib.LOGGER.warning("Found: " + netherGenerator);
BCLib.LOGGER.warning("Should: " + refLevelStem.map(l -> l.value().generator()));
if (refLevelStem.isPresent()) {
var levelStem = refLevelStem.get();
BCLib.LOGGER.warning("Repairing level.dat in order to ensure world continuity.");
var codec = LevelStem.CODEC.orElse(levelStem.value());
var encodeResult = codec.encodeStart(registryOps, levelStem.value());
if (encodeResult.result().isPresent()) {
dimensions.put(dimensionKey.location().toString(), encodeResult.result().get());
result = true;
} else {
BCLib.LOGGER.error("Unable to encode '" + dimensionKey + "' generator for level.dat.");
}
} else {
BCLib.LOGGER.error("Unable to update '" + dimensionKey + "' generator in level.dat.");
}
}
// final long seed = worldGenSettings.contains("seed")
// ? worldGenSettings.getLong("seed")
// : MHelper.RANDOM.nextLong();
//
// final boolean genStructures = !worldGenSettings.contains("generate_features") || worldGenSettings.getBoolean(
// "generate_features");
//
// final boolean genBonusChest = worldGenSettings.contains("bonus_chest") && worldGenSettings.getBoolean(
// "bonus_chest");
//
//
// CompoundTag dimensionTag = dimensions.getCompound(dimensionKey.location().toString());
// Optional<WorldGenSettings> oWorldGen = WorldGenSettings.CODEC
// .parse(new Dynamic<>(registryOps, worldGenSettings))
// .result();
//
// Optional<LevelStem> oLevelStem = LevelStem.CODEC
// .parse(new Dynamic<>(registryOps, dimensionTag))
// .resultOrPartial(BCLib.LOGGER::error);
//
// Optional<ChunkGenerator> netherGenerator = oLevelStem.map(l -> l.generator());
// int biomeSourceVersion = LevelGenUtil.getBiomeVersionForGenerator(netherGenerator.orElse(null));
// int targetVersion = LevelGenUtil.getBiomeVersionForCurrentWorld(dimensionKey);
// if (biomeSourceVersion != targetVersion) {
// Optional<Holder<LevelStem>> refLevelStem = LevelGenUtil.referenceStemForVersion(
// dimensionKey,
// targetVersion,
// registryAccess,
// oWorldGen.map(g -> g.seed()).orElse(seed),
// oWorldGen.map(g -> g.generateStructures()).orElse(genStructures),
// oWorldGen.map(g -> g.generateBonusChest()).orElse(genBonusChest)
// );
//
// BCLib.LOGGER.warning("The world uses the BiomeSource Version " + biomeSourceVersion + " but should have " + targetVersion + ".");
// BCLib.LOGGER.warning("Dimension: " + dimensionKey);
// BCLib.LOGGER.warning("Found: " + netherGenerator);
// BCLib.LOGGER.warning("Should: " + refLevelStem.map(l -> l.value().generator()));
//
// if (refLevelStem.isPresent()) {
// var levelStem = refLevelStem.get();
// BCLib.LOGGER.warning("Repairing level.dat in order to ensure world continuity.");
// var codec = LevelStem.CODEC.orElse(levelStem.value());
// var encodeResult = codec.encodeStart(registryOps, levelStem.value());
// if (encodeResult.result().isPresent()) {
// dimensions.put(dimensionKey.location().toString(), encodeResult.result().get());
// result = true;
// } else {
// BCLib.LOGGER.error("Unable to encode '" + dimensionKey + "' generator for level.dat.");
// }
// } else {
// BCLib.LOGGER.error("Unable to update '" + dimensionKey + "' generator in level.dat.");
// }
// }
return result;
}

View file

@ -1,6 +1,7 @@
package org.betterx.bclib.api.v2.generator;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.worlds.together.biomesource.MergeableBiomeSource;
import org.betterx.worlds.together.world.BiomeSourceWithSeed;
import net.minecraft.core.Holder;
@ -13,11 +14,9 @@ import com.google.common.collect.Sets;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
public abstract class BCLBiomeSource extends BiomeSource implements BiomeSourceWithSeed {
public static int BIOME_SOURCE_VERSION_NONE = -1;
public abstract class BCLBiomeSource extends BiomeSource implements BiomeSourceWithSeed, MergeableBiomeSource<BCLBiomeSource> {
public static int BIOME_SOURCE_VERSION_VANILLA = 0;
public static int BIOME_SOURCE_VERSION_SQUARE = 17;
public static int BIOME_SOURCE_VERSION_HEX = 18;
@ -26,8 +25,6 @@ public abstract class BCLBiomeSource extends BiomeSource implements BiomeSourceW
protected long currentSeed;
protected int maxHeight;
public final int biomeSourceVersion;
private static List<Holder<Biome>> preInit(Registry<Biome> biomeRegistry, List<Holder<Biome>> biomes) {
biomes = biomes.stream().sorted(Comparator.comparing(holder -> holder.unwrapKey()
.get()
@ -41,19 +38,12 @@ public abstract class BCLBiomeSource extends BiomeSource implements BiomeSourceW
protected BCLBiomeSource(
Registry<Biome> biomeRegistry,
List<Holder<Biome>> list,
long seed,
Optional<Integer> biomeSourceVersion
long seed
) {
super(preInit(biomeRegistry, list));
this.biomeRegistry = biomeRegistry;
this.biomeSourceVersion = biomeSourceVersion.orElse(DEFAULT_BIOME_SOURCE_VERSION);
this.currentSeed = seed;
System.out.println(this + " with Registry: " + biomeRegistry.getClass().getName() + "@" + Integer.toHexString(
biomeRegistry.hashCode()));
//BiomeAPI.initRegistry(biomeRegistry);
}
final public void setSeed(long seed) {
@ -85,16 +75,6 @@ public abstract class BCLBiomeSource extends BiomeSource implements BiomeSourceW
protected abstract void onInitMap(long newSeed);
protected abstract void onHeightChange(int newHeight);
public static int getVersionBiomeSource(BiomeSource biomeSource) {
if (biomeSource == null) return BCLBiomeSource.BIOME_SOURCE_VERSION_NONE;
if (biomeSource instanceof BCLBiomeSource bcl) {
return bcl.biomeSourceVersion;
} else {
return BCLBiomeSource.BIOME_SOURCE_VERSION_VANILLA;
}
}
public BCLBiomeSource createCopyForDatapack(Set<Holder<Biome>> datapackBiomes) {
Set<Holder<Biome>> mutableSet = Sets.newHashSet();
mutableSet.addAll(datapackBiomes);
@ -128,4 +108,10 @@ public abstract class BCLBiomeSource extends BiomeSource implements BiomeSourceW
})
.toList();
}
@Override
public BCLBiomeSource mergeWithBiomeSource(BiomeSource inputBiomeSource) {
final Set<Holder<Biome>> datapackBiomes = inputBiomeSource.possibleBiomes();
return this.createCopyForDatapack(datapackBiomes);
}
}

View file

@ -1,15 +1,22 @@
package org.betterx.bclib.api.v2.generator;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.levelgen.LevelGenUtil;
import org.betterx.bclib.api.v2.levelgen.biomes.InternalBiomeAPI;
import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider;
import org.betterx.bclib.mixin.common.ChunkGeneratorAccessor;
import org.betterx.worlds.together.WorldsTogether;
import org.betterx.worlds.together.world.WorldGenUtil;
import org.betterx.worlds.together.biomesource.MergeableBiomeSource;
import org.betterx.worlds.together.chunkgenerator.EnforceableChunkGenerator;
import org.betterx.worlds.together.chunkgenerator.InjectableSurfaceRules;
import org.betterx.worlds.together.chunkgenerator.RestorableBiomeSource;
import org.betterx.worlds.together.levelgen.WorldGenUtil;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel;
@ -18,6 +25,7 @@ import net.minecraft.world.level.biome.BiomeGenerationSettings;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.FeatureSorter;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
@ -31,7 +39,7 @@ import com.google.common.base.Suppliers;
import java.util.List;
import java.util.function.Function;
public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
public class BCLChunkGenerator extends NoiseBasedChunkGenerator implements RestorableBiomeSource<BCLChunkGenerator>, InjectableSurfaceRules<BCLChunkGenerator>, EnforceableChunkGenerator<BCLChunkGenerator> {
public static final Codec<BCLChunkGenerator> CODEC = RecordCodecBuilder
.create((RecordCodecBuilder.Instance<BCLChunkGenerator> builderInstance) -> {
@ -92,7 +100,13 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
}
}
public void restoreInitialBiomeSource() {
/**
* Other Mods like TerraBlender might inject new BiomeSources. We und that change after the world setup did run.
*
* @param dimensionKey The Dimension where this ChunkGenerator is used from
*/
@Override
public void restoreInitialBiomeSource(ResourceKey<LevelStem> dimensionKey) {
if (initialBiomeSource != getBiomeSource()) {
if (this instanceof ChunkGeneratorAccessor acc) {
BiomeSource bs = WorldGenUtil.getWorldSettings()
@ -122,7 +136,9 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
return "BCLib - Chunk Generator (" + Integer.toHexString(hashCode()) + ")";
}
//Make sure terrablender does not rewrite the feature-set
// This method is injected by Terrablender.
// We make sure terrablender does not rewrite the feature-set for our ChunkGenerator by overwriting the
// Mixin-Method with an empty implementation
public void appendFeaturesPerStep() {
}
@ -138,15 +154,75 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
}
}
public static void restoreInitialBiomeSources(WorldGenSettings settings) {
restoreInitialBiomeSource(settings, LevelStem.NETHER);
restoreInitialBiomeSource(settings, LevelStem.END);
@Override
public WorldGenSettings enforceGeneratorInWorldGenSettings(
RegistryAccess access,
ResourceKey<LevelStem> dimensionKey,
ResourceKey<DimensionType> dimensionTypeKey,
ChunkGenerator loadedChunkGenerator,
WorldGenSettings settings
) {
BCLib.LOGGER.info("Enforcing Correct Generator for " + dimensionKey.location().toString() + ".");
ChunkGenerator referenceGenerator = this;
if (loadedChunkGenerator instanceof org.betterx.bclib.interfaces.ChunkGeneratorAccessor generator) {
if (loadedChunkGenerator instanceof NoiseGeneratorSettingsProvider noiseProvider) {
if (referenceGenerator instanceof NoiseGeneratorSettingsProvider referenceProvider) {
final BiomeSource bs;
if (referenceGenerator.getBiomeSource() instanceof MergeableBiomeSource mbs) {
bs = mbs.mergeWithBiomeSource(loadedChunkGenerator.getBiomeSource());
} else {
bs = referenceGenerator.getBiomeSource();
}
InternalBiomeAPI.applyModifications(bs, dimensionKey);
referenceGenerator = new BCLChunkGenerator(
generator.bclib_getStructureSetsRegistry(),
noiseProvider.bclib_getNoises(),
bs,
buildGeneratorSettings(
referenceProvider.bclib_getNoiseGeneratorSettingHolders(),
noiseProvider.bclib_getNoiseGeneratorSettingHolders(),
bs
)
);
}
}
}
return LevelGenUtil.replaceGenerator(
dimensionKey,
dimensionTypeKey,
access,
settings,
referenceGenerator
);
}
public static void restoreInitialBiomeSource(WorldGenSettings settings, ResourceKey<LevelStem> dimension) {
LevelStem loadedStem = settings.dimensions().getOrThrow(dimension);
if (loadedStem.generator() instanceof BCLChunkGenerator cg) {
cg.restoreInitialBiomeSource();
}
private static Holder<NoiseGeneratorSettings> buildGeneratorSettings(
Holder<NoiseGeneratorSettings> reference,
Holder<NoiseGeneratorSettings> settings,
BiomeSource biomeSource
) {
return settings;
// NoiseGeneratorSettings old = settings.value();
// NoiseGeneratorSettings noise = new NoiseGeneratorSettings(
// old.noiseSettings(),
// old.defaultBlock(),
// old.defaultFluid(),
// old.noiseRouter(),
// SurfaceRuleRegistry.mergeSurfaceRulesFromBiomes(old.surfaceRule(), biomeSource),
// //SurfaceRuleUtil.addRulesForBiomeSource(old.surfaceRule(), biomeSource),
// old.spawnTarget(),
// old.seaLevel(),
// old.disableMobGeneration(),
// old.aquifersEnabled(),
// old.oreVeinsEnabled(),
// old.useLegacyRandomSource()
// );
//
//
// return Holder.direct(noise);
}
}

View file

@ -1,17 +1,16 @@
package org.betterx.bclib.api.v2.generator;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.generator.map.hex.HexBiomeMap;
import org.betterx.bclib.api.v2.generator.map.square.SquareBiomeMap;
import org.betterx.bclib.api.v2.generator.config.BCLEndBiomeSourceConfig;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.bclib.config.ConfigKeeper.StringArrayEntry;
import org.betterx.bclib.config.Configs;
import org.betterx.bclib.interfaces.BiomeMap;
import org.betterx.bclib.interfaces.TheEndBiomeDataAccessor;
import org.betterx.bclib.noise.OpenSimplexNoise;
import org.betterx.bclib.presets.worldgen.BCLWorldPresetSettings;
import org.betterx.worlds.together.world.WorldGenUtil;
import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig;
import org.betterx.worlds.together.levelgen.WorldGenUtil;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
@ -22,27 +21,22 @@ import net.minecraft.core.SectionPos;
import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BiomeTags;
import net.minecraft.util.Mth;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.levelgen.DensityFunction;
import net.minecraft.world.level.levelgen.LegacyRandomSource;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.levelgen.synth.SimplexNoise;
import net.fabricmc.fabric.impl.biome.TheEndBiomeData;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
import org.jetbrains.annotations.NotNull;
public class BCLibEndBiomeSource extends BCLBiomeSource {
private static final OpenSimplexNoise SMALL_NOISE = new OpenSimplexNoise(8324);
public class BCLibEndBiomeSource extends BCLBiomeSource implements BiomeSourceWithConfig<BCLibEndBiomeSource, BCLEndBiomeSourceConfig> {
public static Codec<BCLibEndBiomeSource> CODEC
= RecordCodecBuilder.create((instance) -> instance.group(
RegistryOps
@ -53,11 +47,11 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
.fieldOf("seed")
.stable()
.forGetter(source -> source.currentSeed),
Codec
.INT
.optionalFieldOf("version")
.stable()
.forGetter(source -> Optional.of(source.biomeSourceVersion))
BCLEndBiomeSourceConfig
.CODEC
.fieldOf("config")
.orElse(BCLEndBiomeSourceConfig.DEFAULT)
.forGetter(o -> o.config)
)
.apply(
instance,
@ -68,40 +62,40 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
private final Holder<Biome> barrens;
private final Point pos;
private final BiFunction<Point, Integer, Boolean> endLandFunction;
private SimplexNoise noise;
private BiomeMap mapLand;
private BiomeMap mapVoid;
private final BiomePicker endLandBiomePicker;
private final BiomePicker endVoidBiomePicker;
private boolean generateEndVoids;
private BCLEndBiomeSourceConfig config;
public BCLibEndBiomeSource(Registry<Biome> biomeRegistry, long seed, Optional<Integer> version) {
this(biomeRegistry, seed, version, true);
public BCLibEndBiomeSource(Registry<Biome> biomeRegistry, long seed, BCLEndBiomeSourceConfig config) {
this(biomeRegistry, seed, config, true);
}
public BCLibEndBiomeSource(Registry<Biome> biomeRegistry, Optional<Integer> version) {
this(biomeRegistry, 0, version, false);
public BCLibEndBiomeSource(Registry<Biome> biomeRegistry, BCLEndBiomeSourceConfig config) {
this(biomeRegistry, 0, config, false);
}
private BCLibEndBiomeSource(Registry<Biome> biomeRegistry, long seed, Optional<Integer> version, boolean initMaps) {
this(biomeRegistry, getBiomes(biomeRegistry), seed, version, initMaps);
private BCLibEndBiomeSource(
Registry<Biome> biomeRegistry,
long seed,
BCLEndBiomeSourceConfig config,
boolean initMaps
) {
this(biomeRegistry, getBiomes(biomeRegistry), seed, config, initMaps);
}
private BCLibEndBiomeSource(
Registry<Biome> biomeRegistry,
List<Holder<Biome>> list,
long seed,
Optional<Integer> version,
BCLEndBiomeSourceConfig config,
boolean initMaps
) {
super(biomeRegistry, list, seed, version);
if (WorldGenUtil.getWorldSettings() instanceof BCLWorldPresetSettings settings) {
generateEndVoids = settings.generateEndVoid;
} else {
generateEndVoids = true;
}
super(biomeRegistry, list, seed);
this.config = config;
endLandBiomePicker = new BiomePicker(biomeRegistry);
endVoidBiomePicker = new BiomePicker(biomeRegistry);
@ -133,7 +127,7 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
BCLBiome bclBiome = BiomeAPI.getBiome(key);
if (bclBiome != BiomeAPI.EMPTY_BIOME) {
if (bclBiome.getParentBiome() == null) {
if (generateEndVoids) {
if (config.withVoidBiomes) {
if (BiomeAPI.wasRegisteredAsEndVoidBiome(key) || includeVoid.contains(key.toString())) {
endVoidBiomePicker.addBiome(bclBiome);
} else if (BiomeAPI.wasRegisteredAsEndLandBiome(key) || includeLand.contains(key.toString())) {
@ -144,7 +138,7 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
endLandBiomePicker.addBiome(bclBiome);
endVoidBiomePicker.addBiome(bclBiome);
}
if (!key.equals(Biomes.SMALL_END_ISLANDS) && !key.equals(Biomes.THE_END)
if (!key.equals(Biomes.SMALL_END_ISLANDS.location()) && !key.equals(Biomes.THE_END.location())
&& (BiomeAPI.wasRegisteredAsEndVoidBiome(key) || includeVoid.contains(key.toString()))
) {
endVoidBiomePicker.addBiome(bclBiome);
@ -183,7 +177,7 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
this.biomeRegistry,
datapackBiomes.stream().toList(),
this.currentSeed,
Optional.of(biomeSourceVersion),
this.config,
true
);
}
@ -258,63 +252,23 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
BiomeAPI.wasRegisteredAs(location, BiomeAPI.BiomeType.BCL_END_VOID);
}
public static float getLegacyHeightValue(SimplexNoise simplexNoise, int i, int j) {
int k = i / 2;
int l = j / 2;
int m = i % 2;
int n = j % 2;
float f = 100.0f - Mth.sqrt(i * i + j * j) * 8.0f;
f = Mth.clamp(f, -100.0f, 80.0f);
for (int o = -12; o <= 12; ++o) {
for (int p = -12; p <= 12; ++p) {
long q = k + o;
long r = l + p;
if (q * q + r * r <= 4096L || !(simplexNoise.getValue(q, r) < (double) -0.9f)) continue;
float g = (Mth.abs(q) * 3439.0f + Mth.abs(r) * 147.0f) % 13.0f + 9.0f;
float h = m - o * 2;
float s = n - p * 2;
float t = 100.0f - Mth.sqrt(h * h + s * s) * g;
t = Mth.clamp(t, -100.0f, 80.0f);
f = Math.max(f, t);
}
}
return f;
}
public static void register() {
Registry.register(Registry.BIOME_SOURCE, BCLib.makeID("end_biome_source"), CODEC);
}
@Override
protected void onInitMap(long seed) {
if ((biomeSourceVersion != BIOME_SOURCE_VERSION_HEX)) {
this.mapLand = new SquareBiomeMap(
seed,
GeneratorOptions.getBiomeSizeEndLand(),
endLandBiomePicker
);
this.mapVoid = new SquareBiomeMap(
seed,
GeneratorOptions.getBiomeSizeEndVoid(),
endVoidBiomePicker
);
} else {
this.mapLand = new HexBiomeMap(
seed,
GeneratorOptions.getBiomeSizeEndLand(),
endLandBiomePicker
);
this.mapVoid = new HexBiomeMap(
seed,
GeneratorOptions.getBiomeSizeEndVoid(),
endVoidBiomePicker
);
}
this.mapLand = config.mapVersion.mapBuilder.apply(
seed,
GeneratorOptions.getBiomeSizeEndLand(),
endLandBiomePicker
);
WorldgenRandom chunkRandom = new WorldgenRandom(new LegacyRandomSource(seed));
chunkRandom.consumeCount(17292);
this.noise = new SimplexNoise(chunkRandom);
this.mapVoid = config.mapVersion.mapBuilder.apply(
seed,
GeneratorOptions.getBiomeSizeEndVoid(),
endVoidBiomePicker
);
}
@Override
@ -323,17 +277,16 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
}
@Override
public Holder<Biome> getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.Sampler sampler) {
public Holder<Biome> getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.@NotNull Sampler sampler) {
if (mapLand == null || mapVoid == null)
return this.possibleBiomes().stream().findFirst().get();
return this.possibleBiomes().stream().findFirst().orElseThrow();
int posX = QuartPos.toBlock(biomeX);
int posY = QuartPos.toBlock(biomeY);
int posZ = QuartPos.toBlock(biomeZ);
long farEndBiomes = GeneratorOptions.getFarEndBiomes();
long dist = Math.abs(posX) + Math.abs(posZ) > farEndBiomes
? (farEndBiomes + 1)
long dist = Math.abs(posX) + Math.abs(posZ) > (long) config.innerVoidRadiusSquared
? ((long) config.innerVoidRadiusSquared + 1)
: (long) posX * (long) posX + (long) posZ * (long) posZ;
if ((biomeX & 63) == 0 && (biomeZ & 63) == 0) {
@ -341,8 +294,8 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
mapVoid.clearCache();
}
if (endLandFunction == null) {
if (dist <= farEndBiomes) {
if (config.generatorVersion == BCLEndBiomeSourceConfig.EndBiomeGeneratorType.VANILLA || endLandFunction == null) {
if (dist <= (long) config.innerVoidRadiusSquared) {
return this.centerBiome;
}
int x = (SectionPos.blockToSectionCoord(posX) * 2 + 1) * 8;
@ -355,14 +308,15 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
} else {
return d < -0.21875
? mapVoid.getBiome(posX, biomeY << 2, posZ).biome
: generateEndVoids ? this.barrens : mapVoid.getBiome(posX, biomeY << 2, posZ).biome;
: config.withVoidBiomes ? this.barrens : mapVoid.getBiome(posX, biomeY << 2, posZ).biome;
}
} else {
pos.setLocation(biomeX, biomeZ);
if (endLandFunction.apply(pos, maxHeight)) {
return dist <= farEndBiomes ? centerBiome : mapLand.getBiome(posX, biomeY << 2, posZ).biome;
return dist <= (long) config.innerVoidRadiusSquared
? centerBiome : mapLand.getBiome(posX, biomeY << 2, posZ).biome;
} else {
return dist <= farEndBiomes
return dist <= (long) config.innerVoidRadiusSquared
? barrens
: mapVoid.getBiome(posX, biomeY << 2, posZ).biome;
}
@ -378,6 +332,17 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
@Override
public String toString() {
return "BCLib - The End BiomeSource (" + Integer.toHexString(hashCode()) + ", version=" + biomeSourceVersion + ", seed=" + currentSeed + ", height=" + maxHeight + ", voids=" + generateEndVoids + ", customLand=" + (endLandFunction != null) + ", biomes=" + possibleBiomes().size() + ")";
return "BCLib - The End BiomeSource (" + Integer.toHexString(hashCode()) + ", config=" + config + ", seed=" + currentSeed + ", height=" + maxHeight + ", customLand=" + (endLandFunction != null) + ", biomes=" + possibleBiomes().size() + ")";
}
@Override
public BCLEndBiomeSourceConfig getTogetherConfig() {
return config;
}
@Override
public void setTogetherConfig(BCLEndBiomeSourceConfig newConfig) {
this.config = newConfig;
this.initMap(currentSeed);
}
}

View file

@ -1,14 +1,15 @@
package org.betterx.bclib.api.v2.generator;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.generator.config.BCLNetherBiomeSourceConfig;
import org.betterx.bclib.api.v2.generator.map.MapStack;
import org.betterx.bclib.api.v2.generator.map.hex.HexBiomeMap;
import org.betterx.bclib.api.v2.generator.map.square.SquareBiomeMap;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.bclib.config.ConfigKeeper.StringArrayEntry;
import org.betterx.bclib.config.Configs;
import org.betterx.bclib.interfaces.BiomeMap;
import org.betterx.bclib.util.TriFunction;
import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
@ -23,13 +24,10 @@ import net.minecraft.world.level.biome.Climate;
import net.fabricmc.fabric.api.biome.v1.NetherBiomes;
import org.apache.commons.lang3.function.TriFunction;
import java.util.List;
import java.util.Optional;
import java.util.Set;
public class BCLibNetherBiomeSource extends BCLBiomeSource {
public class BCLibNetherBiomeSource extends BCLBiomeSource implements BiomeSourceWithConfig<BCLibNetherBiomeSource, BCLNetherBiomeSourceConfig> {
public static final Codec<BCLibNetherBiomeSource> CODEC = RecordCodecBuilder
.create(instance -> instance
.group(
@ -43,43 +41,44 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource {
.forGetter(source -> {
return source.currentSeed;
}),
Codec
.INT
.optionalFieldOf("version")
.stable()
.forGetter(source -> Optional.of(source.biomeSourceVersion))
BCLNetherBiomeSourceConfig
.CODEC
.fieldOf("config")
.orElse(BCLNetherBiomeSourceConfig.DEFAULT)
.forGetter(o -> o.config)
)
.apply(instance, instance.stable(BCLibNetherBiomeSource::new))
);
private BiomeMap biomeMap;
private final BiomePicker biomePicker;
private BCLNetherBiomeSourceConfig config;
public BCLibNetherBiomeSource(Registry<Biome> biomeRegistry, Optional<Integer> version) {
this(biomeRegistry, 0, version, false);
public BCLibNetherBiomeSource(Registry<Biome> biomeRegistry, BCLNetherBiomeSourceConfig config) {
this(biomeRegistry, 0, config, false);
}
public BCLibNetherBiomeSource(Registry<Biome> biomeRegistry, long seed, Optional<Integer> version) {
this(biomeRegistry, seed, version, true);
public BCLibNetherBiomeSource(Registry<Biome> biomeRegistry, long seed, BCLNetherBiomeSourceConfig config) {
this(biomeRegistry, seed, config, true);
}
private BCLibNetherBiomeSource(
Registry<Biome> biomeRegistry,
long seed,
Optional<Integer> version,
BCLNetherBiomeSourceConfig config,
boolean initMaps
) {
this(biomeRegistry, getBiomes(biomeRegistry), seed, version, initMaps);
this(biomeRegistry, getBiomes(biomeRegistry), seed, config, initMaps);
}
private BCLibNetherBiomeSource(
Registry<Biome> biomeRegistry,
List<Holder<Biome>> list,
long seed,
Optional<Integer> version,
BCLNetherBiomeSourceConfig config,
boolean initMaps
) {
super(biomeRegistry, list, seed, version);
super(biomeRegistry, list, seed);
this.config = config;
biomePicker = new BiomePicker(biomeRegistry);
this.possibleBiomes().forEach(biome -> {
@ -111,7 +110,7 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource {
this.biomeRegistry,
datapackBiomes.stream().toList(),
this.currentSeed,
Optional.of(biomeSourceVersion),
config,
true
);
}
@ -181,9 +180,7 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource {
@Override
protected void onInitMap(long seed) {
TriFunction<Long, Integer, BiomePicker, BiomeMap> mapConstructor = (biomeSourceVersion != BIOME_SOURCE_VERSION_HEX)
? SquareBiomeMap::new
: HexBiomeMap::new;
TriFunction<Long, Integer, BiomePicker, BiomeMap> mapConstructor = config.mapVersion.mapBuilder;
if (maxHeight > 128 && GeneratorOptions.useVerticalBiomes()) {
this.biomeMap = new MapStack(
seed,
@ -209,6 +206,17 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource {
@Override
public String toString() {
return "BCLib - Nether BiomeSource (" + Integer.toHexString(hashCode()) + ", version=" + biomeSourceVersion + ", seed=" + currentSeed + ", height=" + maxHeight + ", biomes=" + possibleBiomes().size() + ")";
return "BCLib - Nether BiomeSource (" + Integer.toHexString(hashCode()) + ", config=" + config + ", seed=" + currentSeed + ", height=" + maxHeight + ", biomes=" + possibleBiomes().size() + ")";
}
@Override
public BCLNetherBiomeSourceConfig getTogetherConfig() {
return config;
}
@Override
public void setTogetherConfig(BCLNetherBiomeSourceConfig newConfig) {
this.config = config;
initMap(currentSeed);
}
}

View file

@ -0,0 +1,154 @@
package org.betterx.bclib.api.v2.generator.config;
import org.betterx.bclib.api.v2.generator.BCLibEndBiomeSource;
import org.betterx.bclib.api.v2.generator.BiomePicker;
import org.betterx.bclib.api.v2.generator.map.hex.HexBiomeMap;
import org.betterx.bclib.api.v2.generator.map.square.SquareBiomeMap;
import org.betterx.bclib.interfaces.BiomeMap;
import org.betterx.bclib.util.TriFunction;
import org.betterx.worlds.together.biomesource.config.BiomeSourceConfig;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.util.StringRepresentable;
import java.util.Objects;
import org.jetbrains.annotations.NotNull;
public class BCLEndBiomeSourceConfig implements BiomeSourceConfig<BCLibEndBiomeSource> {
public static final BCLEndBiomeSourceConfig MINECRAFT_17 = new BCLEndBiomeSourceConfig(
EndBiomeMapType.SQUARE,
EndBiomeGeneratorType.PAULEVS,
true,
1000000
);
public static final BCLEndBiomeSourceConfig MINECRAFT_18 = new BCLEndBiomeSourceConfig(
EndBiomeMapType.HEX,
EndBiomeGeneratorType.PAULEVS,
false,
MINECRAFT_17.innerVoidRadiusSquared
);
public static final BCLEndBiomeSourceConfig DEFAULT = MINECRAFT_18;
public static final Codec<BCLEndBiomeSourceConfig> CODEC = RecordCodecBuilder.create(instance -> instance
.group(
EndBiomeMapType.CODEC
.fieldOf("map_type")
.orElse(DEFAULT.mapVersion)
.forGetter(o -> o.mapVersion),
EndBiomeGeneratorType.CODEC
.fieldOf("generator_version")
.orElse(DEFAULT.generatorVersion)
.forGetter(o -> o.generatorVersion),
Codec.BOOL
.fieldOf("with_void_biomes")
.orElse(DEFAULT.withVoidBiomes)
.forGetter(o -> o.withVoidBiomes),
Codec.INT
.fieldOf("inner_void_radius_squared")
.orElse(DEFAULT.innerVoidRadiusSquared)
.forGetter(o -> o.innerVoidRadiusSquared)
)
.apply(instance, BCLEndBiomeSourceConfig::new));
public BCLEndBiomeSourceConfig(
@NotNull EndBiomeMapType mapVersion,
@NotNull EndBiomeGeneratorType generatorVersion,
boolean withVoidBiomes,
int innerVoidRadiusSquared
) {
this.mapVersion = mapVersion;
this.generatorVersion = generatorVersion;
this.withVoidBiomes = withVoidBiomes;
this.innerVoidRadiusSquared = innerVoidRadiusSquared;
}
public enum EndBiomeMapType implements StringRepresentable {
VANILLA("vanilla", (seed, biomeSize, picker) -> new HexBiomeMap(seed, biomeSize, picker)),
SQUARE("square", (seed, biomeSize, picker) -> new SquareBiomeMap(seed, biomeSize, picker)),
HEX("hex", (seed, biomeSize, picker) -> new HexBiomeMap(seed, biomeSize, picker));
public static final Codec<EndBiomeMapType> CODEC = StringRepresentable.fromEnum(EndBiomeMapType::values);
public final String name;
public final @NotNull TriFunction<Long, Integer, BiomePicker, BiomeMap> mapBuilder;
EndBiomeMapType(String name, @NotNull TriFunction<Long, Integer, BiomePicker, BiomeMap> mapBuilder) {
this.name = name;
this.mapBuilder = mapBuilder;
}
@Override
public String getSerializedName() {
return name;
}
@Override
public String toString() {
return name;
}
}
public enum EndBiomeGeneratorType implements StringRepresentable {
VANILLA("vanilla"),
PAULEVS("paulevs");
public static final Codec<EndBiomeGeneratorType> CODEC = StringRepresentable.fromEnum(EndBiomeGeneratorType::values);
public final String name;
EndBiomeGeneratorType(String name) {
this.name = name;
}
@Override
public String getSerializedName() {
return name;
}
@Override
public String toString() {
return name;
}
}
public final @NotNull EndBiomeMapType mapVersion;
public final @NotNull EndBiomeGeneratorType generatorVersion;
public final boolean withVoidBiomes;
public final int innerVoidRadiusSquared;
@Override
public String toString() {
return "BCLibEndBiomeSourceConfig{" +
"mapVersion=" + mapVersion +
", generatorVersion=" + generatorVersion +
", withVoidBiomes=" + withVoidBiomes +
", innerVoidRadiusSquared=" + innerVoidRadiusSquared +
'}';
}
@Override
public boolean couldSetWithoutRepair(BiomeSourceConfig<?> input) {
if (input instanceof BCLEndBiomeSourceConfig cfg) {
return withVoidBiomes == cfg.withVoidBiomes && mapVersion == cfg.mapVersion;
}
return false;
}
@Override
public boolean sameConfig(BiomeSourceConfig<?> input) {
return this.equals(input);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BCLEndBiomeSourceConfig)) return false;
BCLEndBiomeSourceConfig that = (BCLEndBiomeSourceConfig) o;
return withVoidBiomes == that.withVoidBiomes && innerVoidRadiusSquared == that.innerVoidRadiusSquared && mapVersion == that.mapVersion && generatorVersion == that.generatorVersion;
}
@Override
public int hashCode() {
return Objects.hash(mapVersion, generatorVersion, withVoidBiomes, innerVoidRadiusSquared);
}
}

View file

@ -0,0 +1,98 @@
package org.betterx.bclib.api.v2.generator.config;
import org.betterx.bclib.api.v2.generator.BCLibNetherBiomeSource;
import org.betterx.bclib.api.v2.generator.BiomePicker;
import org.betterx.bclib.api.v2.generator.map.hex.HexBiomeMap;
import org.betterx.bclib.api.v2.generator.map.square.SquareBiomeMap;
import org.betterx.bclib.interfaces.BiomeMap;
import org.betterx.bclib.util.TriFunction;
import org.betterx.worlds.together.biomesource.config.BiomeSourceConfig;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.util.StringRepresentable;
import java.util.Objects;
import org.jetbrains.annotations.NotNull;
public class BCLNetherBiomeSourceConfig implements BiomeSourceConfig<BCLibNetherBiomeSource> {
public static final BCLNetherBiomeSourceConfig MINECRAFT_17 = new BCLNetherBiomeSourceConfig(
NetherBiomeMapType.SQUARE
);
public static final BCLNetherBiomeSourceConfig MINECRAFT_18 = new BCLNetherBiomeSourceConfig(
NetherBiomeMapType.HEX
);
public static final BCLNetherBiomeSourceConfig DEFAULT = MINECRAFT_18;
public static final Codec<BCLNetherBiomeSourceConfig> CODEC = RecordCodecBuilder.create(instance -> instance
.group(
BCLNetherBiomeSourceConfig.NetherBiomeMapType.CODEC
.fieldOf("map_type")
.orElse(DEFAULT.mapVersion)
.forGetter(o -> o.mapVersion)
)
.apply(instance, BCLNetherBiomeSourceConfig::new));
public final @NotNull NetherBiomeMapType mapVersion;
public BCLNetherBiomeSourceConfig(@NotNull NetherBiomeMapType mapVersion) {
this.mapVersion = mapVersion;
}
@Override
public String toString() {
return "BCLibNetherBiomeSourceConfig{" +
"mapVersion=" + mapVersion +
'}';
}
@Override
public boolean couldSetWithoutRepair(BiomeSourceConfig<?> input) {
if (input instanceof BCLNetherBiomeSourceConfig cfg) {
return mapVersion == cfg.mapVersion;
}
return false;
}
@Override
public boolean sameConfig(BiomeSourceConfig<?> input) {
return this.equals(input);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BCLNetherBiomeSourceConfig)) return false;
BCLNetherBiomeSourceConfig that = (BCLNetherBiomeSourceConfig) o;
return mapVersion == that.mapVersion;
}
@Override
public int hashCode() {
return Objects.hash(mapVersion);
}
public enum NetherBiomeMapType implements StringRepresentable {
VANILLA("vanilla", (seed, biomeSize, picker) -> new HexBiomeMap(seed, biomeSize, picker)),
SQUARE("square", (seed, biomeSize, picker) -> new SquareBiomeMap(seed, biomeSize, picker)),
HEX("hex", (seed, biomeSize, picker) -> new HexBiomeMap(seed, biomeSize, picker));
public static final Codec<NetherBiomeMapType> CODEC = StringRepresentable.fromEnum(NetherBiomeMapType::values);
public final String name;
public final TriFunction<Long, Integer, BiomePicker, BiomeMap> mapBuilder;
NetherBiomeMapType(String name, TriFunction<Long, Integer, BiomePicker, BiomeMap> mapBuilder) {
this.name = name;
this.mapBuilder = mapBuilder;
}
@Override
public String getSerializedName() {
return name;
}
@Override
public String toString() {
return name;
}
}
}

View file

@ -5,11 +5,10 @@ import org.betterx.bclib.interfaces.BiomeChunk;
import org.betterx.bclib.interfaces.BiomeMap;
import org.betterx.bclib.interfaces.TriConsumer;
import org.betterx.bclib.noise.OpenSimplexNoise;
import org.betterx.bclib.util.TriFunction;
import net.minecraft.util.Mth;
import org.apache.commons.lang3.function.TriFunction;
import java.util.Random;
public class MapStack implements BiomeMap {

View file

@ -5,8 +5,8 @@ import org.betterx.bclib.api.v2.LifeCycleAPI;
import org.betterx.bclib.api.v2.dataexchange.DataExchangeAPI;
import org.betterx.bclib.api.v2.datafixer.DataFixerAPI;
import org.betterx.bclib.api.v2.generator.BCLibEndBiomeSource;
import org.betterx.bclib.api.v2.generator.config.BCLEndBiomeSourceConfig;
import org.betterx.bclib.api.v2.levelgen.biomes.InternalBiomeAPI;
import org.betterx.bclib.presets.worldgen.BCLWorldPresetSettings;
import org.betterx.bclib.registry.PresetsRegistry;
import org.betterx.worlds.together.world.event.WorldEvents;
import org.betterx.worlds.together.worldPreset.TogetherWorldPreset;
@ -59,21 +59,24 @@ public class LevelGenEvents {
if (currentPreset.isPresent()) {
if (currentPreset.get().value() instanceof TogetherWorldPreset worldPreset) {
ResourceKey key = currentPreset.get().unwrapKey().orElse(null);
//user did not configure the Preset!
if (PresetsRegistry.BCL_WORLD.equals(key) || PresetsRegistry.BCL_WORLD_17.equals(key)) {
ResourceKey worldPresetKey = currentPreset.get().unwrapKey().orElse(null);
//user did not configure/change the Preset!
if (PresetsRegistry.BCL_WORLD.equals(worldPresetKey)
|| PresetsRegistry.BCL_WORLD_17.equals(worldPresetKey)) {
BCLib.LOGGER.info("Detected Datapack for END.");
if (worldPreset.settings instanceof BCLWorldPresetSettings settings) {
LevelStem configuredEndStem = worldPreset.getDimension(LevelStem.END);
if (configuredEndStem.generator().getBiomeSource() instanceof BCLibEndBiomeSource endSource) {
BCLib.LOGGER.info("Changing Default WorldPreset Settings for Datapack use.");
worldPreset = worldPreset.withSettings(new BCLWorldPresetSettings(
settings.netherVersion,
settings.endVersion,
BCLEndBiomeSourceConfig inputConfig = endSource.getTogetherConfig();
endSource.setTogetherConfig(new BCLEndBiomeSourceConfig(
inputConfig.mapVersion,
BCLEndBiomeSourceConfig.EndBiomeGeneratorType.VANILLA,
false,
false
inputConfig.innerVoidRadiusSquared
));
currentPreset = Optional.of(Holder.direct(worldPreset));
}
}
}

View file

@ -5,11 +5,13 @@ import org.betterx.bclib.api.v2.generator.BCLBiomeSource;
import org.betterx.bclib.api.v2.generator.BCLChunkGenerator;
import org.betterx.bclib.api.v2.generator.BCLibEndBiomeSource;
import org.betterx.bclib.api.v2.generator.BCLibNetherBiomeSource;
import org.betterx.bclib.api.v2.generator.config.BCLEndBiomeSourceConfig;
import org.betterx.bclib.api.v2.generator.config.BCLNetherBiomeSourceConfig;
import org.betterx.bclib.presets.worldgen.BCLWorldPresetSettings;
import org.betterx.bclib.registry.PresetsRegistry;
import org.betterx.worlds.together.levelgen.WorldGenUtil;
import org.betterx.worlds.together.util.ModUtil;
import org.betterx.worlds.together.world.WorldConfig;
import org.betterx.worlds.together.world.WorldGenUtil;
import org.betterx.worlds.together.worldPreset.TogetherWorldPreset;
import org.betterx.worlds.together.worldPreset.settings.WorldPresetSettings;
@ -20,7 +22,6 @@ import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
@ -35,41 +36,33 @@ public class LevelGenUtil {
private static final String TAG_BN_GEN_VERSION = "generator_version";
@NotNull
public static LevelStem getBCLNetherLevelStem(WorldGenUtil.Context context, Optional<Integer> version) {
BCLibNetherBiomeSource netherSource = new BCLibNetherBiomeSource(context.biomes, version);
return getBCLNetherLevelStem(context, netherSource);
}
public static LevelStem getBCLNetherLevelStem(WorldGenUtil.Context context, BCLNetherBiomeSourceConfig config) {
BCLibNetherBiomeSource netherSource = new BCLibNetherBiomeSource(context.biomes, config);
public static LevelStem getBCLNetherLevelStem(WorldGenUtil.StemContext context, BiomeSource biomeSource) {
return new LevelStem(
context.dimension,
new BCLChunkGenerator(
context.structureSets,
context.noiseParameters,
biomeSource,
netherSource,
context.generatorSettings
)
);
}
@NotNull
public static LevelStem getBCLEndLevelStem(WorldGenUtil.StemContext context, BiomeSource biomeSource) {
public static LevelStem getBCLEndLevelStem(WorldGenUtil.Context context, BCLEndBiomeSourceConfig config) {
BCLibEndBiomeSource endSource = new BCLibEndBiomeSource(context.biomes, config);
return new LevelStem(
context.dimension,
new BCLChunkGenerator(
context.structureSets,
context.noiseParameters,
biomeSource,
endSource,
context.generatorSettings
)
);
}
public static LevelStem getBCLEndLevelStem(WorldGenUtil.Context context, Optional<Integer> version) {
BCLibEndBiomeSource endSource = new BCLibEndBiomeSource(context.biomes, version);
return getBCLEndLevelStem(context, endSource);
}
public static WorldGenSettings replaceGenerator(
ResourceKey<LevelStem> dimensionKey,
@ -178,10 +171,10 @@ public class LevelGenUtil {
return writableRegistry;
}
public static int getBiomeVersionForGenerator(ChunkGenerator generator) {
if (generator == null) return BCLBiomeSource.getVersionBiomeSource(null);
return BCLBiomeSource.getVersionBiomeSource(generator.getBiomeSource());
}
// public static int getBiomeVersionForGenerator(ChunkGenerator generator) {
// if (generator == null) return BCLBiomeSource.getVersionBiomeSource(null);
// return BCLBiomeSource.getVersionBiomeSource(generator.getBiomeSource());
// }
public static Optional<Holder<LevelStem>> referenceStemForVersion(
ResourceKey<LevelStem> dimensionKey,
@ -224,25 +217,25 @@ public class LevelGenUtil {
return settingsNbt.getInt(key.location().toString());
}
private static int getDimensionVersion(
WorldGenSettings settings,
ResourceKey<LevelStem> key
) {
var dimension = settings.dimensions().getHolder(key);
if (dimension.isPresent()) {
return getBiomeVersionForGenerator(dimension.get().value().generator());
} else {
return getBiomeVersionForGenerator(null);
}
}
// private static int getDimensionVersion(
// WorldGenSettings settings,
// ResourceKey<LevelStem> key
// ) {
// var dimension = settings.dimensions().getHolder(key);
// if (dimension.isPresent()) {
// return getBiomeVersionForGenerator(dimension.get().value().generator());
// } else {
// return getBiomeVersionForGenerator(null);
// }
// }
private static void writeDimensionVersion(
WorldGenSettings settings,
CompoundTag generatorSettings,
ResourceKey<LevelStem> key
) {
generatorSettings.putInt(key.location().toString(), getDimensionVersion(settings, key));
}
// private static void writeDimensionVersion(
// WorldGenSettings settings,
// CompoundTag generatorSettings,
// ResourceKey<LevelStem> key
// ) {
// generatorSettings.putInt(key.location().toString(), getDimensionVersion(settings, key));
// }
public static void migrateGeneratorSettings() {
final CompoundTag settingsNbt = WorldGenUtil.getSettingsNbt();

View file

@ -1,7 +1,5 @@
package org.betterx.bclib.api.v2.levelgen.biomes;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.levelgen.surface.SurfaceRuleUtil;
import org.betterx.bclib.util.WeightedList;
import org.betterx.worlds.together.tag.v3.TagManager;
@ -11,8 +9,6 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.levelgen.SurfaceRules;
import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import com.google.common.collect.Lists;
@ -36,7 +32,6 @@ public class BCLBiome extends BCLBiomeSettings {
private final List<Climate.ParameterPoint> parameterPoints = Lists.newArrayList();
private Consumer<ResourceKey<Biome>> surfaceInit;
private BCLBiome biomeParent;
/**
@ -202,10 +197,6 @@ public class BCLBiome extends BCLBiomeSettings {
void afterRegistration() {
ResourceKey<Biome> key = BuiltinRegistries.BIOME.getResourceKey(getBiome()).orElseThrow();
this.biomeTags.forEach(tagKey -> TagManager.BIOMES.add(tagKey, biome));
if (this.surfaceInit != null) {
surfaceInit.accept(key);
}
}
@ -297,21 +288,6 @@ public class BCLBiome extends BCLBiomeSettings {
this.parameterPoints.forEach(consumer);
}
/**
* Sets biome surface rule.
*
* @param surface {@link SurfaceRules.RuleSource} rule.
*/
void setSurface(RuleSource surface) {
this.surfaceInit = (key) -> {
if (key == null) {
BCLib.LOGGER.warning("BCL Biome " + biomeID + " does not have registry key!");
} else {
SurfaceRuleUtil.addSurfaceRule(biomeID, SurfaceRules.ifTrue(SurfaceRules.isBiome(key), surface));
}
};
}
/**
* Returns the group used in the config Files for this biome
* <p>

View file

@ -1,87 +0,0 @@
package org.betterx.bclib.api.v2.levelgen.surface;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.bclib.api.v2.levelgen.biomes.InternalBiomeAPI;
import org.betterx.worlds.together.mixin.common.NoiseGeneratorSettingsMixin;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class SurfaceRuleUtil {
private static final Map<ResourceLocation, RuleSource> SURFACE_RULES = Maps.newHashMap();
private static List<RuleSource> getRuleSourcesForBiomes(Set<Holder<Biome>> biomes) {
Set<ResourceLocation> biomeIDs = biomes
.stream()
.map(biome -> BiomeAPI.getBiomeID(biome))
.collect(Collectors.toSet());
return getRuleSourcesFromIDs(biomeIDs);
}
/**
* Creates a list of SurfaceRules for all Biomes that are managed by the passed {@link BiomeSource}.
* If we have Surface rules for any of the Biomes from the given set of {@link BiomeSource}, they
* will be added to the result
* <p>
* Note: This Method is used in the {@link NoiseGeneratorSettingsMixin} which in turn
* is called from {@link InternalBiomeAPI#applyModificationsDeprecated(ServerLevel)}.
*
* @param sources The Set of {@link BiomeSource} we want to consider
* @return A list of {@link RuleSource}-Objects that are needed to create those Biomes
*/
public static List<RuleSource> getRuleSources(Set<BiomeSource> sources) {
final Set<Holder<Biome>> biomes = new HashSet<>();
for (BiomeSource s : sources) {
biomes.addAll(s.possibleBiomes());
}
return getRuleSourcesForBiomes(biomes);
}
public static List<RuleSource> getRuleSources(BiomeSource biomeSource) {
return getRuleSourcesForBiomes(Sets.newHashSet(biomeSource.possibleBiomes()));
}
private static List<RuleSource> getRuleSourcesFromIDs(Set<ResourceLocation> biomeIDs) {
List<RuleSource> rules = Lists.newArrayList();
SURFACE_RULES.forEach((biomeID, rule) -> {
if (biomeIDs.contains(biomeID)) {
rules.add(rule);
}
});
return rules;
}
/**
* Adds surface rule to specified biome.
*
* @param biomeID biome {@link ResourceLocation}.
* @param source {@link RuleSource}.
*/
public static void addSurfaceRule(ResourceLocation biomeID, RuleSource source) {
SURFACE_RULES.put(biomeID, source);
}
public static RuleSource addRulesForBiomeSource(RuleSource orgiginalSource, BiomeSource biomeSource) {
List<RuleSource> additionalRules = getRuleSources(biomeSource);
return org.betterx.worlds.together.surfaceRules.SurfaceRuleUtil.mergeSurfaceRules(
orgiginalSource,
additionalRules
);
}
}

View file

@ -1,16 +1,12 @@
package org.betterx.bclib.presets.worldgen;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.generator.BCLBiomeSource;
import org.betterx.bclib.api.v2.generator.BCLChunkGenerator;
import org.betterx.bclib.api.v2.generator.BCLibEndBiomeSource;
import org.betterx.bclib.api.v2.generator.config.BCLEndBiomeSourceConfig;
import org.betterx.bclib.api.v2.generator.config.BCLNetherBiomeSourceConfig;
import org.betterx.bclib.api.v2.levelgen.LevelGenUtil;
import org.betterx.bclib.api.v2.levelgen.biomes.InternalBiomeAPI;
import org.betterx.bclib.interfaces.ChunkGeneratorAccessor;
import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider;
import org.betterx.worlds.together.world.WorldGenUtil;
import org.betterx.worlds.together.levelgen.WorldGenUtil;
import org.betterx.worlds.together.worldPreset.TogetherWorldPreset;
import org.betterx.worlds.together.worldPreset.settings.VanillaWorldPresetSettings;
import org.betterx.worlds.together.worldPreset.settings.WorldPresetSettings;
import com.mojang.serialization.Codec;
@ -20,40 +16,37 @@ import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.BuiltinDimensionTypes;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
public class BCLWorldPresetSettings extends WorldPresetSettings {
public final static BCLWorldPresetSettings DEFAULT = new BCLWorldPresetSettings(BCLBiomeSource.DEFAULT_BIOME_SOURCE_VERSION);
public static final Codec<BCLWorldPresetSettings> CODEC = RecordCodecBuilder
.create((RecordCodecBuilder.Instance<BCLWorldPresetSettings> builderInstance) -> {
return builderInstance.group(
Codec.INT
.fieldOf(LevelStem.NETHER.location().toString())
.forGetter(o -> o.netherVersion),
Codec.INT
.fieldOf(LevelStem.END.location().toString())
.forGetter(o -> o.endVersion),
Codec.BOOL
.fieldOf("custom_end_terrain")
.orElse(true)
.forGetter(o -> o.useEndTerrainGenerator),
Codec.BOOL
.fieldOf("generate_end_void")
.orElse(false)
.forGetter(o -> o.generateEndVoid)
)
.apply(builderInstance, builderInstance.stable(BCLWorldPresetSettings::new));
});
.create((RecordCodecBuilder.Instance<BCLWorldPresetSettings> builderInstance) -> builderInstance.group(
Codec.INT
.fieldOf(LevelStem.NETHER.location().toString())
.forGetter(o -> o.netherVersion),
Codec.INT
.fieldOf(LevelStem.END.location().toString())
.forGetter(o -> o.endVersion),
Codec.BOOL
.fieldOf("custom_end_terrain")
.orElse(true)
.forGetter(o -> o.useEndTerrainGenerator),
Codec.BOOL
.fieldOf("generate_end_void")
.orElse(false)
.forGetter(o -> o.generateEndVoid)
)
.apply(
builderInstance,
builderInstance.stable(
BCLWorldPresetSettings::new)
));
public final int netherVersion;
public final int endVersion;
public final boolean useEndTerrainGenerator;
@ -89,6 +82,24 @@ public class BCLWorldPresetSettings extends WorldPresetSettings {
return new TogetherWorldPreset(buildDimensionMap(overworldStem, netherContext, endContext), 1000, this);
}
private static BCLEndBiomeSourceConfig getEndConfigForVersion(int version) {
if (version == BCLBiomeSource.BIOME_SOURCE_VERSION_HEX)
return BCLEndBiomeSourceConfig.MINECRAFT_18;
if (version == BCLBiomeSource.BIOME_SOURCE_VERSION_SQUARE)
return BCLEndBiomeSourceConfig.MINECRAFT_17;
return BCLEndBiomeSourceConfig.DEFAULT;
}
private static BCLNetherBiomeSourceConfig getNetherConfigForVersion(int version) {
if (version == BCLBiomeSource.BIOME_SOURCE_VERSION_HEX)
return BCLNetherBiomeSourceConfig.MINECRAFT_18;
if (version == BCLBiomeSource.BIOME_SOURCE_VERSION_SQUARE)
return BCLNetherBiomeSourceConfig.MINECRAFT_17;
return BCLNetherBiomeSourceConfig.DEFAULT;
}
public Map<ResourceKey<LevelStem>, LevelStem> buildDimensionMap(
LevelStem overworldStem,
WorldGenUtil.Context netherContext,
@ -98,32 +109,19 @@ public class BCLWorldPresetSettings extends WorldPresetSettings {
LevelStem.OVERWORLD,
overworldStem,
LevelStem.NETHER,
createNetherStem(netherContext),
LevelGenUtil.getBCLNetherLevelStem(netherContext, getNetherConfigForVersion(netherVersion)),
LevelStem.END,
createEndStem(endContext)
LevelGenUtil.getBCLEndLevelStem(endContext, getEndConfigForVersion(endVersion))
);
}
public int getVersion(ResourceKey<LevelStem> key) {
if (key == LevelStem.NETHER) return netherVersion;
if (key == LevelStem.END) return endVersion;
// public int getVersion(ResourceKey<LevelStem> key) {
// if (key == LevelStem.NETHER) return netherVersion;
// if (key == LevelStem.END) return endVersion;
//
// return BCLBiomeSource.BIOME_SOURCE_VERSION_VANILLA;
// }
return BCLBiomeSource.BIOME_SOURCE_VERSION_VANILLA;
}
public LevelStem createStem(WorldGenUtil.Context ctx, ResourceKey<LevelStem> key) {
if (key == LevelStem.NETHER) return createNetherStem(ctx);
if (key == LevelStem.END) return createEndStem(ctx);
return null;
}
public LevelStem createNetherStem(WorldGenUtil.Context ctx) {
return LevelGenUtil.getBCLNetherLevelStem(ctx, Optional.of(netherVersion));
}
public LevelStem createEndStem(WorldGenUtil.Context ctx) {
return LevelGenUtil.getBCLEndLevelStem(ctx, Optional.of(endVersion));
}
public BiomeSource addDatapackBiomes(BiomeSource biomeSource, Set<Holder<Biome>> datapackBiomes) {
if (biomeSource instanceof BCLBiomeSource bs) {
@ -132,114 +130,108 @@ public class BCLWorldPresetSettings extends WorldPresetSettings {
return biomeSource;
}
@Override
public void injectSurfaceRules(RegistryAccess registryAccess, WorldGenSettings settings) {
VanillaWorldPresetSettings.DEFAULT.injectSurfaceRules(registryAccess, settings);
}
private static Holder<NoiseGeneratorSettings> buildGeneratorSettings(
Holder<NoiseGeneratorSettings> reference,
Holder<NoiseGeneratorSettings> settings,
BiomeSource biomeSource
) {
//SurfaceRuleUtil.injectSurfaceRules(settings.value(), biomeSource);
return settings;
// NoiseGeneratorSettings old = settings.value();
// NoiseGeneratorSettings noise = new NoiseGeneratorSettings(
// old.noiseSettings(),
// old.defaultBlock(),
// old.defaultFluid(),
// old.noiseRouter(),
// SurfaceRuleRegistry.mergeSurfaceRulesFromBiomes(old.surfaceRule(), biomeSource),
// //SurfaceRuleUtil.addRulesForBiomeSource(old.surfaceRule(), biomeSource),
// old.spawnTarget(),
// old.seaLevel(),
// old.disableMobGeneration(),
// old.aquifersEnabled(),
// old.oreVeinsEnabled(),
// old.useLegacyRandomSource()
// );
// private static Holder<NoiseGeneratorSettings> buildGeneratorSettings(
// Holder<NoiseGeneratorSettings> reference,
// Holder<NoiseGeneratorSettings> settings,
// BiomeSource biomeSource
// ) {
// //SurfaceRuleUtil.injectSurfaceRules(settings.value(), biomeSource);
// return settings;
//// NoiseGeneratorSettings old = settings.value();
//// NoiseGeneratorSettings noise = new NoiseGeneratorSettings(
//// old.noiseSettings(),
//// old.defaultBlock(),
//// old.defaultFluid(),
//// old.noiseRouter(),
//// SurfaceRuleRegistry.mergeSurfaceRulesFromBiomes(old.surfaceRule(), biomeSource),
//// //SurfaceRuleUtil.addRulesForBiomeSource(old.surfaceRule(), biomeSource),
//// old.spawnTarget(),
//// old.seaLevel(),
//// old.disableMobGeneration(),
//// old.aquifersEnabled(),
//// old.oreVeinsEnabled(),
//// old.useLegacyRandomSource()
//// );
////
////
//// return Holder.direct(noise);
// }
// /**
// * Datapacks can change the world's generator. This Method will ensure, that the Generators contain
// * the correct BiomeSources for this world
// *
// * @param dimensionKey
// * @param dimensionTypeKey
// * @param settings
// * @return
// */
// private WorldGenSettings fixSettingsInCurrentWorld(
// RegistryAccess access, ResourceKey<LevelStem> dimensionKey,
// ResourceKey<DimensionType> dimensionTypeKey,
// WorldGenSettings settings
// ) {
// Optional<Holder<LevelStem>> loadedStem = settings.dimensions().getHolder(dimensionKey);
// final ChunkGenerator loadedChunkGenerator = loadedStem.map(h -> h.value().generator()).orElse(null);
// final int loaderVersion = LevelGenUtil.getBiomeVersionForGenerator(loadedStem
// .map(h -> h.value().generator())
// .orElse(null));
//
// final int targetVersion = getVersion(dimensionKey);
// if (loaderVersion != targetVersion) {
// BCLib.LOGGER.info("Enforcing Correct Generator for " + dimensionKey.location().toString() + ".");
//
// return Holder.direct(noise);
}
/**
* Datapacks can change the world's generator. This Method will ensure, that the Generators contain
* the correct BiomeSources for this world
*
* @param dimensionKey
* @param dimensionTypeKey
* @param settings
* @return
*/
private WorldGenSettings fixSettingsInCurrentWorld(
RegistryAccess access, ResourceKey<LevelStem> dimensionKey,
ResourceKey<DimensionType> dimensionTypeKey,
WorldGenSettings settings
) {
Optional<Holder<LevelStem>> loadedStem = settings.dimensions().getHolder(dimensionKey);
final ChunkGenerator loadedChunkGenerator = loadedStem.map(h -> h.value().generator()).orElse(null);
final int loaderVersion = LevelGenUtil.getBiomeVersionForGenerator(loadedStem
.map(h -> h.value().generator())
.orElse(null));
final int targetVersion = getVersion(dimensionKey);
if (loaderVersion != targetVersion) {
BCLib.LOGGER.info("Enforcing Correct Generator for " + dimensionKey.location().toString() + ".");
Optional<Holder<LevelStem>> refLevelStem = LevelGenUtil.referenceStemForVersion(
dimensionKey,
targetVersion,
access,
settings.seed(),
settings.generateStructures(),
settings.generateBonusChest()
);
ChunkGenerator referenceGenerator = refLevelStem.map(h -> h.value().generator()).orElse(null);
if (referenceGenerator == null) {
BCLib.LOGGER.error("Failed to create Generator for " + dimensionKey.location().toString());
return settings;
}
if (loadedChunkGenerator instanceof ChunkGeneratorAccessor generator) {
if (loadedChunkGenerator instanceof NoiseGeneratorSettingsProvider noiseProvider) {
if (referenceGenerator instanceof NoiseGeneratorSettingsProvider referenceProvider) {
final Set<Holder<Biome>> biomes = loadedChunkGenerator.getBiomeSource().possibleBiomes();
final BiomeSource bs = addDatapackBiomes(referenceGenerator.getBiomeSource(), biomes);
InternalBiomeAPI.applyModifications(bs, dimensionKey);
referenceGenerator = new BCLChunkGenerator(
generator.bclib_getStructureSetsRegistry(),
noiseProvider.bclib_getNoises(),
bs,
buildGeneratorSettings(
referenceProvider.bclib_getNoiseGeneratorSettingHolders(),
noiseProvider.bclib_getNoiseGeneratorSettingHolders(),
bs
)
);
}
}
}
return LevelGenUtil.replaceGenerator(
dimensionKey,
dimensionTypeKey,
access,
settings,
referenceGenerator
);
}/* else {
SurfaceRuleUtil.injectSurfaceRules(dimensionKey, loadedChunkGenerator);
}*/
return settings;
}
// Optional<Holder<LevelStem>> refLevelStem = LevelGenUtil.referenceStemForVersion(
// dimensionKey,
// targetVersion,
// access,
// settings.seed(),
// settings.generateStructures(),
// settings.generateBonusChest()
// );
//
// ChunkGenerator referenceGenerator = refLevelStem.map(h -> h.value().generator()).orElse(null);
// if (referenceGenerator == null) {
// BCLib.LOGGER.error("Failed to create Generator for " + dimensionKey.location().toString());
// return settings;
// }
//
// if (loadedChunkGenerator instanceof ChunkGeneratorAccessor generator) {
// if (loadedChunkGenerator instanceof NoiseGeneratorSettingsProvider noiseProvider) {
// if (referenceGenerator instanceof NoiseGeneratorSettingsProvider referenceProvider) {
// final Set<Holder<Biome>> biomes = loadedChunkGenerator.getBiomeSource().possibleBiomes();
// final BiomeSource bs = addDatapackBiomes(referenceGenerator.getBiomeSource(), biomes);
// InternalBiomeAPI.applyModifications(bs, dimensionKey);
// referenceGenerator = new BCLChunkGenerator(
// generator.bclib_getStructureSetsRegistry(),
// noiseProvider.bclib_getNoises(),
// bs,
// buildGeneratorSettings(
// referenceProvider.bclib_getNoiseGeneratorSettingHolders(),
// noiseProvider.bclib_getNoiseGeneratorSettingHolders(),
// bs
// )
// );
// }
// }
// }
//
// return LevelGenUtil.replaceGenerator(
// dimensionKey,
// dimensionTypeKey,
// access,
// settings,
// referenceGenerator
// );
// }
// return settings;
// }
public WorldGenSettings repairSettingsOnLoad(RegistryAccess registryAccess, WorldGenSettings settings) {
settings = fixSettingsInCurrentWorld(registryAccess, LevelStem.NETHER, BuiltinDimensionTypes.NETHER, settings);
settings = fixSettingsInCurrentWorld(registryAccess, LevelStem.END, BuiltinDimensionTypes.END, settings);
// settings = fixSettingsInCurrentWorld(registryAccess, LevelStem.NETHER, BuiltinDimensionTypes.NETHER, settings);
// settings = fixSettingsInCurrentWorld(registryAccess, LevelStem.END, BuiltinDimensionTypes.END, settings);
return settings;
}

View file

@ -18,9 +18,9 @@ public class PresetsRegistry {
public static void onLoad() {
BCL_WORLD =
WorldPresets.register(
BCLib.makeID("normal"),
BCLib.makeID("hex_map"),
(overworldStem, netherContext, endContext) ->
new BCLWorldPresetSettings(BCLBiomeSource.DEFAULT_BIOME_SOURCE_VERSION).buildPreset(
new BCLWorldPresetSettings(BCLBiomeSource.BIOME_SOURCE_VERSION_HEX).buildPreset(
overworldStem,
netherContext,
endContext

View file

@ -0,0 +1,10 @@
package org.betterx.worlds.together.biomesource;
import org.betterx.worlds.together.biomesource.config.BiomeSourceConfig;
import net.minecraft.world.level.biome.BiomeSource;
public interface BiomeSourceWithConfig<B extends BiomeSource, C extends BiomeSourceConfig<B>> {
C getTogetherConfig();
void setTogetherConfig(C newConfig);
}

View file

@ -0,0 +1,17 @@
package org.betterx.worlds.together.biomesource;
import net.minecraft.world.level.biome.BiomeSource;
public interface MergeableBiomeSource<B extends BiomeSource> {
/**
* Returns a BiomeSource that merges the settings of this one with the Biomes (and possibly settings) from the
* {@code inputBiomeSource}.
*
* @param inputBiomeSource The {@link BiomeSource} you want to copy
* @return The merged or new BiomeSource
*/
B mergeWithBiomeSource(BiomeSource inputBiomeSource);
}

View file

@ -0,0 +1,7 @@
package org.betterx.worlds.together.biomesource;
import org.jetbrains.annotations.ApiStatus;
@ApiStatus.Internal
public interface MultiNoiseBiomeSourceAccessor {
}

View file

@ -0,0 +1,8 @@
package org.betterx.worlds.together.biomesource.config;
import net.minecraft.world.level.biome.BiomeSource;
public interface BiomeSourceConfig<B extends BiomeSource> {
boolean couldSetWithoutRepair(BiomeSourceConfig<?> input);
boolean sameConfig(BiomeSourceConfig<?> input);
}

View file

@ -0,0 +1,20 @@
package org.betterx.worlds.together.chunkgenerator;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.WorldGenSettings;
public class ChunkGeneratorUtils {
public static void restoreOriginalBiomeSourceInAllDimension(WorldGenSettings settings) {
for (var entry : settings.dimensions().entrySet()) {
ResourceKey<LevelStem> key = entry.getKey();
LevelStem stem = entry.getValue();
if (stem.generator() instanceof RestorableBiomeSource<?> generator) {
generator.restoreInitialBiomeSource(key);
}
}
}
}

View file

@ -0,0 +1,35 @@
package org.betterx.worlds.together.chunkgenerator;
import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.WorldGenSettings;
public interface EnforceableChunkGenerator<G extends ChunkGenerator> {
WorldGenSettings enforceGeneratorInWorldGenSettings(
RegistryAccess access,
ResourceKey<LevelStem> dimensionKey,
ResourceKey<DimensionType> dimensionTypeKey,
ChunkGenerator loadedChunkGenerator,
WorldGenSettings settings
);
default boolean needsChunkGeneratorRepair(ChunkGenerator chunkGenerator) {
ChunkGenerator self = (ChunkGenerator) this;
if (this == chunkGenerator || chunkGenerator == null) return false;
BiomeSource one = self.getBiomeSource();
BiomeSource two = chunkGenerator.getBiomeSource();
if (one == two) return false;
if (one instanceof BiomeSourceWithConfig<?, ?> ba && two instanceof BiomeSourceWithConfig<?, ?> bb) {
return !ba.getTogetherConfig().couldSetWithoutRepair(bb.getTogetherConfig());
}
return !one.getClass().isAssignableFrom(two.getClass()) && !two.getClass().isAssignableFrom(one.getClass());
}
}

View file

@ -0,0 +1,21 @@
package org.betterx.worlds.together.chunkgenerator;
import org.betterx.worlds.together.surfaceRules.SurfaceRuleUtil;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
public interface InjectableSurfaceRules<G extends ChunkGenerator> {
/**
* Called when the Surface Rules for this BiomeSource need to be
*
* @param dimensionKey The Dimension for which this injection is performed
*/
default void injectSurfaceRules(ResourceKey<LevelStem> dimensionKey) {
if (this instanceof NoiseBasedChunkGenerator nbc) {
SurfaceRuleUtil.injectSurfaceRules(nbc.generatorSettings().value(), nbc.getBiomeSource());
}
}
}

View file

@ -0,0 +1,9 @@
package org.betterx.worlds.together.chunkgenerator;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.LevelStem;
public interface RestorableBiomeSource<G extends ChunkGenerator> {
void restoreInitialBiomeSource(ResourceKey<LevelStem> dimensionKey);
}

View file

@ -1,6 +1,11 @@
package org.betterx.worlds.together.world;
package org.betterx.worlds.together.levelgen;
import org.betterx.worlds.together.WorldsTogether;
import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig;
import org.betterx.worlds.together.chunkgenerator.EnforceableChunkGenerator;
import org.betterx.worlds.together.world.BiomeSourceWithSeed;
import org.betterx.worlds.together.world.WorldConfig;
import org.betterx.worlds.together.worldPreset.TogetherWorldPreset;
import org.betterx.worlds.together.worldPreset.WorldPresets;
import org.betterx.worlds.together.worldPreset.settings.WorldPresetSettings;
@ -17,6 +22,7 @@ import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
@ -85,7 +91,6 @@ public class WorldGenUtil {
}
public static WorldPresetSettings getWorldSettings() {
if (BuiltinRegistries.ACCESS == null) return null;
final RegistryAccess registryAccess = BuiltinRegistries.ACCESS;
final RegistryOps<Tag> registryOps = RegistryOps.create(NbtOps.INSTANCE, registryAccess);
@ -128,4 +133,39 @@ public class WorldGenUtil {
this.generatorSettings = generatorSettings;
}
}
@SuppressWarnings("unchecked")
public static WorldGenSettings repairBiomeSourceInAllDimensions(
RegistryAccess registryAccess,
WorldGenSettings settings
) {
var dimensions = TogetherWorldPreset.getWorldDimensions();
for (var entry : settings.dimensions().entrySet()) {
ResourceKey<LevelStem> key = entry.getKey();
LevelStem loadedStem = entry.getValue();
ChunkGenerator referenceGenerator = dimensions.get(key);
if (referenceGenerator instanceof EnforceableChunkGenerator enforcer) {
final ChunkGenerator loadedChunkGenerator = loadedStem.generator();
if (enforcer.needsChunkGeneratorRepair(loadedChunkGenerator)) {
settings = enforcer.enforceGeneratorInWorldGenSettings(
registryAccess,
key,
loadedStem.typeHolder().unwrapKey().orElseThrow(),
loadedChunkGenerator,
settings
);
} else if (loadedChunkGenerator.getBiomeSource() instanceof BiomeSourceWithConfig bs) {
if (referenceGenerator.getBiomeSource() instanceof BiomeSourceWithConfig refbs) {
if (!refbs.getTogetherConfig().sameConfig(bs.getTogetherConfig())) {
bs.setTogetherConfig(refbs.getTogetherConfig());
}
}
}
}
}
return settings;
}
}

View file

@ -1,6 +1,6 @@
package org.betterx.worlds.together.mixin.client;
import org.betterx.worlds.together.world.WorldGenUtil;
import org.betterx.worlds.together.levelgen.WorldGenUtil;
import org.betterx.worlds.together.world.event.WorldBootstrap;
import org.betterx.worlds.together.worldPreset.WorldPresets;

View file

@ -1,6 +1,6 @@
package org.betterx.worlds.together.mixin.common;
import org.betterx.worlds.together.world.WorldGenUtil;
import org.betterx.worlds.together.surfaceRules.SurfaceRuleUtil;
import net.minecraft.core.RegistryAccess;
import net.minecraft.server.MinecraftServer;
@ -29,6 +29,6 @@ public class MinecraftServerMixin {
@Inject(method = "createLevels", at = @At(value = "HEAD"))
private void together_addSurfaceRules(ChunkProgressListener worldGenerationProgressListener, CallbackInfo ci) {
WorldGenUtil.getWorldSettings().injectSurfaceRules(registryHolder, this.worldData.worldGenSettings());
SurfaceRuleUtil.injectSurfaceRulesToAllDimensions(this.worldData.worldGenSettings());
}
}

View file

@ -1,6 +1,6 @@
package org.betterx.bclib.mixin.common;
package org.betterx.worlds.together.mixin.common;
import org.betterx.bclib.api.v2.generator.BCLChunkGenerator;
import org.betterx.worlds.together.chunkgenerator.ChunkGeneratorUtils;
import com.mojang.datafixers.DataFixer;
import net.minecraft.server.MinecraftServer;
@ -31,6 +31,6 @@ public class MinecraftServerMixinLate {
ChunkProgressListenerFactory chunkProgressListenerFactory,
CallbackInfo ci
) {
BCLChunkGenerator.restoreInitialBiomeSources(worldStem.worldData().worldGenSettings());
ChunkGeneratorUtils.restoreOriginalBiomeSourceInAllDimension(worldStem.worldData().worldGenSettings());
}
}

View file

@ -0,0 +1,11 @@
package org.betterx.worlds.together.mixin.common;
import org.betterx.worlds.together.chunkgenerator.InjectableSurfaceRules;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(NoiseBasedChunkGenerator.class)
public class NoiseBasedChunkGeneratorMixin implements InjectableSurfaceRules {
}

View file

@ -1,22 +1,16 @@
package org.betterx.worlds.together.mixin.common;
import org.betterx.bclib.api.v2.levelgen.surface.SurfaceRuleUtil;
import org.betterx.worlds.together.WorldsTogether;
import org.betterx.worlds.together.surfaceRules.SurfaceRuleProvider;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.SurfaceRules;
import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Mixin(NoiseGeneratorSettings.class)
public class NoiseGeneratorSettingsMixin implements SurfaceRuleProvider {
@Mutable
@ -24,80 +18,15 @@ public class NoiseGeneratorSettingsMixin implements SurfaceRuleProvider {
@Shadow
private SurfaceRules.RuleSource surfaceRule;
private SurfaceRules.RuleSource bclib_originalSurfaceRule;
private final Set<BiomeSource> bclib_biomeSources = new HashSet<>();
private void bclib_updateCustomRules() {
bclib_setCustomRules(SurfaceRuleUtil.getRuleSources(bclib_biomeSources));
}
@Override
public void bclib_addBiomeSource(BiomeSource source) {
// bclib_biomeSources.add(source);
// bclib_updateCustomRules();
}
@Override
public void bclib_clearBiomeSources() {
// bclib_biomeSources.clear();
// bclib_clearCustomRules();
}
private void bclib_clearCustomRules() {
// if (bclib_originalSurfaceRule != null) {
// this.surfaceRule = bclib_originalSurfaceRule;
// bclib_originalSurfaceRule = null;
// }
}
private void bclib_setCustomRules(List<RuleSource> rules) {
// if (rules.size() == 0) {
// bclib_clearCustomRules();
// return;
// }
//
// RuleSource org = bclib_getOriginalSurfaceRule();
// if (org instanceof SurfaceRules.SequenceRuleSource sequenceRule) {
// List<RuleSource> currentSequence = sequenceRule.sequence();
// rules = rules.stream().filter(r -> currentSequence.indexOf(r) < 0).collect(Collectors.toList());
// rules.addAll(sequenceRule.sequence());
// } else {
// rules.add(org);
// }
//
// bclib_setSurfaceRule(SurfaceRules.sequence(rules.toArray(new RuleSource[rules.size()])));
}
public void bclib_overwrite(SurfaceRules.RuleSource surfaceRule) {
if (surfaceRule == this.surfaceRule) return;
if (this.bcl_containsOverride) {
System.out.println("Adding another override");
WorldsTogether.LOGGER.warning("Overwriting an overwritten set of Surface Rules.");
}
this.bcl_containsOverride = true;
this.surfaceRule = surfaceRule;
}
void bclib_setSurfaceRule(SurfaceRules.RuleSource surfaceRule) {
if (bclib_originalSurfaceRule == null) {
bclib_originalSurfaceRule = this.surfaceRule;
}
this.surfaceRule = surfaceRule;
}
private boolean bcl_containsOverride = false;
RuleSource bclib_getOriginalSurfaceRule() {
if (bclib_originalSurfaceRule == null) {
return surfaceRule;
}
return bclib_originalSurfaceRule;
}
// @Inject(method = "surfaceRule", at = @At("HEAD"), cancellable = true)
// private void bclib_surfaceRule(CallbackInfoReturnable<SurfaceRules.RuleSource> info) {
// if (bclib_surfaceRule != null) {
// info.setReturnValue(bclib_surfaceRule);
// }
// }
}

View file

@ -1,6 +1,6 @@
package org.betterx.worlds.together.mixin.common;
import org.betterx.worlds.together.world.WorldGenUtil;
import org.betterx.worlds.together.levelgen.WorldGenUtil;
import org.betterx.worlds.together.worldPreset.WorldPresets;
import org.betterx.worlds.together.worldPreset.settings.WorldPresetSettings;

View file

@ -1,10 +1,7 @@
package org.betterx.worlds.together.surfaceRules;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.levelgen.SurfaceRules;
public interface SurfaceRuleProvider {
void bclib_addBiomeSource(BiomeSource source);
void bclib_clearBiomeSources();
void bclib_overwrite(SurfaceRules.RuleSource surfaceRule);
}

View file

@ -1,29 +1,24 @@
package org.betterx.worlds.together.surfaceRules;
import org.betterx.bclib.api.v2.levelgen.biomes.InternalBiomeAPI;
import org.betterx.worlds.together.WorldsTogether;
import org.betterx.worlds.together.chunkgenerator.InjectableSurfaceRules;
import org.betterx.worlds.together.world.event.WorldBootstrap;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.SurfaceRules;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class SurfaceRuleUtil {
public static List<SurfaceRules.RuleSource> getRulesForBiome(ResourceLocation biomeID) {
private static List<SurfaceRules.RuleSource> getRulesForBiome(ResourceLocation biomeID) {
Registry<AssignedSurfaceRule> registry = SurfaceRuleRegistry.BUILTIN_SURFACE_RULES;
if (WorldBootstrap.getLastRegistryAccess() != null)
registry = WorldBootstrap.getLastRegistryAccess()
@ -36,31 +31,30 @@ public class SurfaceRuleUtil {
}
public static List<SurfaceRules.RuleSource> getRulesForBiomes(List<Biome> biomes) {
private static List<SurfaceRules.RuleSource> getRulesForBiomes(List<Biome> biomes) {
Registry<Biome> biomeRegistry = WorldBootstrap.getLastRegistryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
List<ResourceLocation> biomeIDs = biomes.stream()
.map(b -> biomeRegistry.getKey(b))
.filter(id -> id != null)
.toList();
return biomeIDs.stream().map(biomeID -> getRulesForBiome(biomeID)).flatMap(List::stream).toList();
return biomeIDs.stream()
.map(biomeID -> getRulesForBiome(biomeID))
.flatMap(List::stream)
.collect(Collectors.toCollection(LinkedList::new));
}
public static SurfaceRules.RuleSource mergeSurfaceRulesFromBiomes(
private static SurfaceRules.RuleSource mergeSurfaceRulesFromBiomes(
SurfaceRules.RuleSource org,
BiomeSource source
) {
return mergeSurfaceRules(org, getRulesForBiomes(source.possibleBiomes().stream().map(h -> h.value()).toList()));
return mergeSurfaceRules(
org,
getRulesForBiomes(source.possibleBiomes().stream().map(h -> h.value()).toList())
);
}
public static SurfaceRules.RuleSource mergeSurfaceRulesFromBiomes(
SurfaceRules.RuleSource org,
List<Biome> biomes
) {
return mergeSurfaceRules(org, getRulesForBiomes(biomes));
}
public static SurfaceRules.RuleSource mergeSurfaceRules(
private static SurfaceRules.RuleSource mergeSurfaceRules(
SurfaceRules.RuleSource org,
List<SurfaceRules.RuleSource> additionalRules
) {
@ -82,20 +76,6 @@ public class SurfaceRuleUtil {
return new SurfaceRules.SequenceRuleSource(additionalRules);
}
public static void injectSurfaceRules(
ResourceKey<LevelStem> dimensionKey,
ChunkGenerator loadedChunkGenerator
) {
WorldsTogether.LOGGER.debug("Checking Surface Rules for " + dimensionKey.location().toString());
final BiomeSource loadedBiomeSource = loadedChunkGenerator.getBiomeSource();
InternalBiomeAPI.applyModifications(loadedBiomeSource, dimensionKey);
if (loadedChunkGenerator instanceof NoiseBasedChunkGenerator nbc) {
injectSurfaceRules(nbc.generatorSettings().value(), loadedBiomeSource);
}
}
public static void injectSurfaceRules(NoiseGeneratorSettings noiseSettings, BiomeSource loadedBiomeSource) {
if (((Object) noiseSettings) instanceof SurfaceRuleProvider srp) {
SurfaceRules.RuleSource originalRules = noiseSettings.surfaceRule();
@ -103,19 +83,13 @@ public class SurfaceRuleUtil {
}
}
public static void injectSurfaceRules(WorldGenSettings settings, Predicate<ResourceKey<LevelStem>> filter) {
List<ResourceKey<LevelStem>> otherDimensions = settings
.dimensions()
.entrySet()
.stream()
.map(e -> e.getKey())
.filter(filter)
.toList();
public static void injectSurfaceRulesToAllDimensions(WorldGenSettings settings) {
for (var entry : settings.dimensions().entrySet()) {
ResourceKey<LevelStem> key = entry.getKey();
LevelStem stem = entry.getValue();
for (ResourceKey<LevelStem> key : otherDimensions) {
Optional<Holder<LevelStem>> stem = settings.dimensions().getHolder(key);
if (stem.isPresent()) {
injectSurfaceRules(key, stem.get().value().generator());
if (stem.generator() instanceof InjectableSurfaceRules<?> generator) {
generator.injectSurfaceRules(key);
}
}
}

View file

@ -2,9 +2,10 @@ package org.betterx.worlds.together.world.event;
import org.betterx.bclib.BCLib;
import org.betterx.worlds.together.WorldsTogether;
import org.betterx.worlds.together.levelgen.WorldGenUtil;
import org.betterx.worlds.together.mixin.common.RegistryOpsAccessor;
import org.betterx.worlds.together.mixin.common.WorldPresetAccessor;
import org.betterx.worlds.together.world.WorldConfig;
import org.betterx.worlds.together.world.WorldGenUtil;
import org.betterx.worlds.together.worldPreset.TogetherWorldPreset;
import org.betterx.worlds.together.worldPreset.WorldGenSettingsComponentAccessor;
import org.betterx.worlds.together.worldPreset.WorldPresets;
@ -36,15 +37,15 @@ public class WorldBootstrap {
}
public static class Helpers {
private static void initializeWorldDataAPI(
private static void initializeWorldConfig(
LevelStorageSource.LevelStorageAccess levelStorageAccess,
boolean newWorld
) {
File levelPath = levelStorageAccess.getLevelPath(LevelResource.ROOT).toFile();
initializeWorldDataAPI(levelPath, newWorld);
initializeWorldConfig(levelPath, newWorld);
}
private static void initializeWorldDataAPI(File levelBaseDir, boolean newWorld) {
private static void initializeWorldConfig(File levelBaseDir, boolean newWorld) {
WorldConfig.load(new File(levelBaseDir, "data"));
if (newWorld) {
@ -105,12 +106,12 @@ public class WorldBootstrap {
BCLib.LOGGER.info("Creating a new World, no fixes needed");
final WorldPresetSettings settings = Helpers.defaultServerSettings();
Helpers.initializeWorldDataAPI(levelStorageAccess, true);
Helpers.initializeWorldConfig(levelStorageAccess, true);
WorldEventsImpl.BEFORE_SERVER_WORLD_LOAD.emit(e -> e.prepareWorld(
levelStorageAccess, settings, true
));
} else {
Helpers.initializeWorldDataAPI(levelStorageAccess, false);
Helpers.initializeWorldConfig(levelStorageAccess, false);
WorldEventsImpl.BEFORE_SERVER_WORLD_LOAD.emit(e -> e.prepareWorld(
levelStorageAccess,
WorldGenUtil.getWorldSettings(),
@ -130,6 +131,12 @@ public class WorldBootstrap {
settings = t.settings;
}
TogetherWorldPreset.writeWorldPresetSettings(settings);
if (currentPreset.map(h -> h.value()).orElse(null) instanceof WorldPresetAccessor acc) {
TogetherWorldPreset.writeWorldPresetSettings(acc.bcl_getDimensions());
} else {
WorldsTogether.LOGGER.error("Failed writing together File");
//TogetherWorldPreset.writeWorldPresetSettings(worldGenSettings);
}
WorldEventsImpl.ON_WORLD_LOAD.emit(OnWorldLoad::onLoad);
}
}
@ -173,9 +180,9 @@ public class WorldBootstrap {
static Optional<Holder<WorldPreset>> setupNewWorldCommon(
LevelStorageSource.LevelStorageAccess levelStorageAccess,
Optional<Holder<WorldPreset>> currentPreset,
WorldGenSettings worldgenSettings
WorldGenSettings worldGenSettings
) {
Helpers.initializeWorldDataAPI(levelStorageAccess, true);
Helpers.initializeWorldConfig(levelStorageAccess, true);
final WorldPresetSettings settings;
@ -193,9 +200,15 @@ public class WorldBootstrap {
true
));
currentPreset = WorldEventsImpl.ADAPT_WORLD_PRESET.emit(currentPreset, worldgenSettings);
currentPreset = WorldEventsImpl.ADAPT_WORLD_PRESET.emit(currentPreset, worldGenSettings);
TogetherWorldPreset.writeWorldPresetSettings(currentPreset);
if (currentPreset.map(h -> h.value()).orElse(null) instanceof WorldPresetAccessor acc) {
TogetherWorldPreset.writeWorldPresetSettings(acc.bcl_getDimensions());
} else {
WorldsTogether.LOGGER.error("Failed writing together File");
//TogetherWorldPreset.writeWorldPresetSettings(worldGenSettings);
}
//LifeCycleAPI._runBeforeLevelLoad();
WorldEventsImpl.ON_WORLD_LOAD.emit(OnWorldLoad::onLoad);
@ -212,7 +225,7 @@ public class WorldBootstrap {
) {
try {
var levelStorageAccess = levelSource.createAccess(levelID);
Helpers.initializeWorldDataAPI(levelStorageAccess, false);
Helpers.initializeWorldConfig(levelStorageAccess, false);
//Helpers.setupWorld();
WorldEventsImpl.BEFORE_WORLD_LOAD.emit(e -> e.prepareWorld(
@ -270,10 +283,7 @@ public class WorldBootstrap {
}
public static WorldGenSettings enforceInNewWorld(WorldGenSettings worldGenSettings) {
worldGenSettings = WorldGenUtil
.getWorldSettings()
.repairSettingsOnLoad(LAST_REGISTRY_ACCESS, worldGenSettings);
return worldGenSettings;
return WorldGenUtil.repairBiomeSourceInAllDimensions(LAST_REGISTRY_ACCESS, worldGenSettings);
}
public static WorldGenSettings enforceInLoadedWorld(
@ -281,9 +291,7 @@ public class WorldBootstrap {
WorldGenSettings worldGenSettings
) {
if (registryOps.orElse(null) instanceof RegistryOpsAccessor acc) {
return WorldGenUtil
.getWorldSettings()
.repairSettingsOnLoad(acc.bcl_getRegistryAccess(), worldGenSettings);
return WorldGenUtil.repairBiomeSourceInAllDimensions(acc.bcl_getRegistryAccess(), worldGenSettings);
//.repairSettingsOnLoad(LAST_REGISTRY_ACCESS, worldGenSettings);
} else {
BCLib.LOGGER.error("Unable to obtain registryAccess when enforcing generators.");

View file

@ -1,24 +1,32 @@
package org.betterx.worlds.together.worldPreset;
import org.betterx.worlds.together.WorldsTogether;
import org.betterx.worlds.together.levelgen.WorldGenUtil;
import org.betterx.worlds.together.mixin.common.WorldPresetAccessor;
import org.betterx.worlds.together.world.WorldConfig;
import org.betterx.worlds.together.world.WorldGenUtil;
import org.betterx.worlds.together.world.event.WorldBootstrap;
import org.betterx.worlds.together.worldPreset.settings.VanillaWorldPresetSettings;
import org.betterx.worlds.together.worldPreset.settings.WorldPresetSettings;
import net.minecraft.core.Holder;
import com.mojang.serialization.Codec;
import com.mojang.serialization.Dynamic;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.presets.WorldPreset;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.jetbrains.annotations.NotNull;
public class TogetherWorldPreset extends WorldPreset {
public final WorldPresetSettings settings;
@ -54,20 +62,17 @@ public class TogetherWorldPreset extends WorldPreset {
return ((WorldPresetAccessor) this).bcl_getDimensions();
}
public static WorldPresetSettings writeWorldPresetSettings(Optional<Holder<WorldPreset>> worldPreset) {
if (worldPreset.isPresent() && worldPreset.get().value() instanceof TogetherWorldPreset wp) {
writeWorldPresetSettings(wp.settings);
return wp.settings;
} else {
writeWorldPresetSettings(VanillaWorldPresetSettings.DEFAULT);
return VanillaWorldPresetSettings.DEFAULT;
}
public LevelStem getDimension(ResourceKey<LevelStem> key) {
return getDimensions().get(key);
}
public static void writeWorldPresetSettings(WorldPresetSettings presetSettings) {
final RegistryOps<Tag> registryOps = RegistryOps.create(NbtOps.INSTANCE, BuiltinRegistries.ACCESS);
final var codec = WorldPresetSettings.CODEC.orElse(presetSettings);
final var encodeResult = codec.encodeStart(registryOps, presetSettings);
public static void writeWorldPresetSettings(Map<ResourceKey<LevelStem>, LevelStem> settings) {
final RegistryOps<Tag> registryOps = RegistryOps.create(
NbtOps.INSTANCE,
WorldBootstrap.getLastRegistryAccess()
);
DimensionsWrapper wrapper = new DimensionsWrapper(DimensionsWrapper.build(settings));
final var encodeResult = wrapper.CODEC.encodeStart(registryOps, wrapper);
if (encodeResult.result().isPresent()) {
final CompoundTag settingsNbt = WorldConfig.getRootTag(WorldsTogether.MOD_ID);
@ -78,4 +83,75 @@ public class TogetherWorldPreset extends WorldPreset {
WorldConfig.saveFile(WorldsTogether.MOD_ID);
}
private static DimensionsWrapper DEFAULT_DIMENSIONS_WRAPPER = null;
public static @NotNull Map<ResourceKey<LevelStem>, ChunkGenerator> getWorldDimensions() {
if (BuiltinRegistries.ACCESS == null) return null;
final RegistryAccess registryAccess;
if (WorldBootstrap.getLastRegistryAccess() != null) {
registryAccess = WorldBootstrap.getLastRegistryAccess();
} else {
registryAccess = BuiltinRegistries.ACCESS;
}
final RegistryOps<Tag> registryOps = RegistryOps.create(NbtOps.INSTANCE, registryAccess);
Optional<DimensionsWrapper> oLevelStem = DimensionsWrapper.CODEC
.parse(new Dynamic<>(registryOps, WorldGenUtil.getSettingsNbt()))
.resultOrPartial(WorldsTogether.LOGGER::error);
if (DEFAULT_DIMENSIONS_WRAPPER == null) {
DEFAULT_DIMENSIONS_WRAPPER = new DimensionsWrapper(WorldPresets
.get(
registryAccess,
WorldPresets.DEFAULT.orElseThrow()
)
.value()
.createWorldGenSettings(0, true, true)
.dimensions());
}
return oLevelStem.orElse(DEFAULT_DIMENSIONS_WRAPPER).dimensions;
}
private static class DimensionsWrapper {
public static final Codec<DimensionsWrapper> CODEC = RecordCodecBuilder.create(instance -> instance
.group(Codec.unboundedMap(
ResourceKey.codec(Registry.LEVEL_STEM_REGISTRY),
ChunkGenerator.CODEC
)
.fieldOf("dimensions")
.orElse(new HashMap<>())
.forGetter(o -> o.dimensions))
.apply(instance, DimensionsWrapper::new));
final Map<ResourceKey<LevelStem>, ChunkGenerator> dimensions;
static Map<ResourceKey<LevelStem>, ChunkGenerator> build(Registry<LevelStem> dimensions) {
Map<ResourceKey<LevelStem>, ChunkGenerator> map = new HashMap<>();
for (var entry : dimensions.entrySet()) {
ResourceKey<LevelStem> key = entry.getKey();
LevelStem stem = entry.getValue();
map.put(key, stem.generator());
}
return map;
}
static Map<ResourceKey<LevelStem>, ChunkGenerator> build(Map<ResourceKey<LevelStem>, LevelStem> input) {
Map<ResourceKey<LevelStem>, ChunkGenerator> map = new HashMap<>();
for (var entry : input.entrySet()) {
ResourceKey<LevelStem> key = entry.getKey();
LevelStem stem = entry.getValue();
map.put(key, stem.generator());
}
return map;
}
DimensionsWrapper(Registry<LevelStem> dimensions) {
this(build(dimensions));
}
private DimensionsWrapper(Map<ResourceKey<LevelStem>, ChunkGenerator> dimensions) {
this.dimensions = dimensions;
}
}
}

View file

@ -4,7 +4,7 @@ import org.betterx.bclib.registry.PresetsRegistry;
import org.betterx.worlds.together.WorldsTogether;
import org.betterx.worlds.together.tag.v3.TagManager;
import org.betterx.worlds.together.tag.v3.TagRegistry;
import org.betterx.worlds.together.world.WorldGenUtil;
import org.betterx.worlds.together.levelgen.WorldGenUtil;
import org.betterx.worlds.together.worldPreset.client.WorldPresetsClient;
import org.betterx.worlds.together.worldPreset.settings.VanillaWorldPresetSettings;
import org.betterx.worlds.together.worldPreset.settings.WorldPresetSettings;

View file

@ -1,8 +1,5 @@
package org.betterx.worlds.together.worldPreset.settings;
import org.betterx.worlds.together.surfaceRules.SurfaceRuleRegistry;
import org.betterx.worlds.together.surfaceRules.SurfaceRuleUtil;
import com.mojang.serialization.Codec;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
@ -30,9 +27,4 @@ public class VanillaWorldPresetSettings extends WorldPresetSettings {
public BiomeSource addDatapackBiomes(BiomeSource biomeSource, Set<Holder<Biome>> datapackBiomes) {
return biomeSource;
}
public void injectSurfaceRules(RegistryAccess registryAccess, WorldGenSettings settings) {
SurfaceRuleUtil.injectSurfaceRules(settings, SurfaceRuleRegistry.ALL_DIMENSIONS);
}
}

View file

@ -52,5 +52,5 @@ public abstract class WorldPresetSettings {
public abstract Codec<? extends WorldPresetSettings> codec();
public abstract WorldGenSettings repairSettingsOnLoad(RegistryAccess registryAccess, WorldGenSettings settings);
public abstract BiomeSource addDatapackBiomes(BiomeSource biomeSource, Set<Holder<Biome>> datapackBiomes);
public abstract void injectSurfaceRules(RegistryAccess registryAccess, WorldGenSettings settings);
}

View file

@ -23,7 +23,6 @@
"LayerLightSectionStorageMixin",
"LootPoolMixin",
"MinecraftServerMixin",
"MinecraftServerMixinLate",
"MobSpawnSettingsAccessor",
"NoiseBasedChunkGeneratorMixin",
"PistonBaseBlockMixin",

View file

@ -8,6 +8,8 @@
"DiggerItemAccessor",
"MainMixin",
"MinecraftServerMixin",
"MinecraftServerMixinLate",
"NoiseBasedChunkGeneratorMixin",
"NoiseGeneratorSettingsMixin",
"PrimaryLevelDataMixin",
"RegistryAccessMixin",