Correct World Preset handling

This commit is contained in:
Frank 2022-05-22 17:49:46 +02:00
parent 7466048a22
commit 7359c64fff
13 changed files with 451 additions and 129 deletions

View file

@ -37,6 +37,7 @@ public class BCLib implements ModInitializer {
TagAPI.init(); TagAPI.init();
CraftingRecipes.init(); CraftingRecipes.init();
WorldDataAPI.registerModCache(MOD_ID); WorldDataAPI.registerModCache(MOD_ID);
WorldDataAPI.registerModCache(MOD_ID);
DataExchangeAPI.registerMod(MOD_ID); DataExchangeAPI.registerMod(MOD_ID);
WorldPresets.registerPresets(); WorldPresets.registerPresets();
AnvilRecipe.register(); AnvilRecipe.register();

View file

@ -1,13 +1,27 @@
package org.betterx.bclib; package org.betterx.bclib;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag; 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 com.mojang.serialization.Dynamic;
import org.betterx.bclib.api.datafixer.DataFixerAPI; import org.betterx.bclib.api.datafixer.DataFixerAPI;
import org.betterx.bclib.api.datafixer.ForcedLevelPatch; import org.betterx.bclib.api.datafixer.ForcedLevelPatch;
import org.betterx.bclib.api.datafixer.MigrationProfile; import org.betterx.bclib.api.datafixer.MigrationProfile;
import org.betterx.bclib.config.Configs; import org.betterx.bclib.config.Configs;
import org.betterx.bclib.presets.worldgen.BCLChunkGenerator;
import org.betterx.bclib.util.MHelper;
import org.betterx.bclib.world.generator.GeneratorOptions; import org.betterx.bclib.world.generator.GeneratorOptions;
import java.util.Optional;
public final class BCLibPatch { public final class BCLibPatch {
public static void register() { public static void register() {
// TODO separate values in config on client side (config screen) // TODO separate values in config on client side (config screen)
@ -27,30 +41,110 @@ final class BiomeSourcePatch extends ForcedLevelPatch {
super(BCLib.MOD_ID, "1.2.1"); super(BCLib.MOD_ID, "1.2.1");
} }
@Override @Override
protected Boolean runLevelDatPatch(CompoundTag root, MigrationProfile profile) { protected Boolean runLevelDatPatch(CompoundTag root, MigrationProfile profile) {
CompoundTag worldGenSettings = root.getCompound("Data").getCompound("WorldGenSettings"); //make sure we have a working generators file before attempting to patch
CompoundTag dimensions = worldGenSettings.getCompound("dimensions"); BCLChunkGenerator.migrateGeneratorSettings();
long seed = worldGenSettings.getLong("seed");
final CompoundTag worldGenSettings = root.getCompound("Data").getCompound("WorldGenSettings");
final CompoundTag dimensions = worldGenSettings.getCompound("dimensions");
final RegistryAccess registryAccess = RegistryAccess.builtinCopy();
final RegistryOps<Tag> registryOps = RegistryOps.create(NbtOps.INSTANCE, registryAccess);
boolean result = false; boolean result = false;
if (GeneratorOptions.fixNetherBiomeSource()) { result |= checkDimension(worldGenSettings, dimensions, registryAccess, registryOps, LevelStem.NETHER);
if (!dimensions.contains(MC_NETHER) || !isBCLibEntry(dimensions.getCompound(MC_NETHER))) { result |= checkDimension(worldGenSettings, dimensions, registryAccess, registryOps, LevelStem.END);
CompoundTag dimRoot = new CompoundTag();
dimRoot.put("generator", makeNetherGenerator(seed));
dimRoot.putString("type", MC_NETHER);
dimensions.put(MC_NETHER, dimRoot);
result = true;
}
}
if (GeneratorOptions.fixEndBiomeSource()) { System.out.println("Dimensions:" + dimensions);
if (!dimensions.contains(MC_END) || !isBCLibEntry(dimensions.getCompound(MC_END))) { return result;
CompoundTag dimRoot = new CompoundTag(); // if (root != null) return false;
dimRoot.put("generator", makeEndGenerator(seed)); //
dimRoot.putString("type", MC_END); // boolean result = false;
dimensions.put(MC_END, dimRoot); //
result = true; // if (GeneratorOptions.fixNetherBiomeSource()) {
// if (!dimensions.contains(MC_NETHER) || !isBCLibEntry(dimensions.getCompound(MC_NETHER))) {
// CompoundTag dimRoot = new CompoundTag();
// dimRoot.put("generator", makeNetherGenerator(seed));
// dimRoot.putString("type", MC_NETHER);
// dimensions.put(MC_NETHER, dimRoot);
// result = true;
// }
// }
//
// if (GeneratorOptions.fixEndBiomeSource()) {
// if (!dimensions.contains(MC_END) || !isBCLibEntry(dimensions.getCompound(MC_END))) {
// CompoundTag dimRoot = new CompoundTag();
// dimRoot.put("generator", makeEndGenerator(seed));
// dimRoot.putString("type", MC_END);
// dimensions.put(MC_END, dimRoot);
// result = true;
// }
// }
//
// return result;
}
private boolean checkDimension(CompoundTag worldGenSettings,
CompoundTag dimensions,
RegistryAccess registryAccess,
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") : true;
final boolean genBonusChest = worldGenSettings.contains("bonus_chest") ? worldGenSettings.getBoolean(
"bonus_chest") : false;
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 = BCLChunkGenerator.getBiomeVersionForGenerator(netherGenerator.orElse(null));
int targetVersion = BCLChunkGenerator.getBiomeVersionForCurrentWorld(dimensionKey);
if (biomeSourceVersion != targetVersion) {
Optional<Holder<LevelStem>> refLevelStem = BCLChunkGenerator.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.");
} }
} }

View file

@ -30,6 +30,9 @@ import java.util.function.Consumer;
public class WorldDataAPI { public class WorldDataAPI {
private static final Map<String, CompoundTag> TAGS = Maps.newHashMap(); private static final Map<String, CompoundTag> TAGS = Maps.newHashMap();
private static final List<String> MODS = Lists.newArrayList(); private static final List<String> MODS = Lists.newArrayList();
private static final String TAG_CREATED = "create_version";
private static final String TAG_MODIFIED = "modify_version";
private static File dataDir; private static File dataDir;
public static void load(File dataDir) { public static void load(File dataDir) {
@ -84,11 +87,16 @@ public class WorldDataAPI {
CompoundTag root = TAGS.get(modID); CompoundTag root = TAGS.get(modID);
if (root == null) { if (root == null) {
root = new CompoundTag(); root = new CompoundTag();
root.putString(TAG_CREATED, ModUtil.getModVersion(modID));
TAGS.put(modID, root); TAGS.put(modID, root);
} }
return root; return root;
} }
public static boolean hasMod(String modID) {
return MODS.contains(modID);
}
/** /**
* Get {@link CompoundTag} with specified path from mod cache in world data folder. * Get {@link CompoundTag} with specified path from mod cache in world data folder.
* *
@ -120,7 +128,9 @@ public class WorldDataAPI {
if (!dataDir.exists()) { if (!dataDir.exists()) {
dataDir.mkdirs(); dataDir.mkdirs();
} }
NbtIo.writeCompressed(getRootTag(modID), new File(dataDir, modID + ".nbt")); CompoundTag tag = getRootTag(modID);
tag.putString(TAG_MODIFIED, ModUtil.getModVersion(modID));
NbtIo.writeCompressed(tag, new File(dataDir, modID + ".nbt"));
} catch (IOException e) { } catch (IOException e) {
BCLib.LOGGER.error("World data saving failed", e); BCLib.LOGGER.error("World data saving failed", e);
} }

View file

@ -3,12 +3,12 @@ package org.betterx.bclib.api.datafixer;
import net.minecraft.Util; import net.minecraft.Util;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.toasts.SystemToast; import net.minecraft.client.gui.components.toasts.SystemToast;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.worldselection.EditWorldScreen; import net.minecraft.client.gui.screens.worldselection.EditWorldScreen;
import net.minecraft.nbt.*; import net.minecraft.nbt.*;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.storage.RegionFile; import net.minecraft.world.level.chunk.storage.RegionFile;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.storage.LevelResource; import net.minecraft.world.level.storage.LevelResource;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess; import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess;
@ -24,6 +24,7 @@ import org.betterx.bclib.gui.screens.ConfirmFixScreen;
import org.betterx.bclib.gui.screens.LevelFixErrorScreen; import org.betterx.bclib.gui.screens.LevelFixErrorScreen;
import org.betterx.bclib.gui.screens.LevelFixErrorScreen.Listener; import org.betterx.bclib.gui.screens.LevelFixErrorScreen.Listener;
import org.betterx.bclib.gui.screens.ProgressScreen; import org.betterx.bclib.gui.screens.ProgressScreen;
import org.betterx.bclib.presets.worldgen.BCLChunkGenerator;
import org.betterx.bclib.util.Logger; import org.betterx.bclib.util.Logger;
import java.io.*; import java.io.*;
@ -160,6 +161,13 @@ public class DataFixerAPI {
}); });
} }
public static void createWorldData(LevelStorageSource levelSource, String levelID, WorldGenSettings settings) {
wrapCall(levelSource, levelID, (levelStorageAccess) -> {
createWorldData(levelStorageAccess, settings);
return true;
});
}
/** /**
* Initializes the DataStorage for this world. If the world is new, the patch registry is initialized to the * Initializes the DataStorage for this world. If the world is new, the patch registry is initialized to the
* current versions of the plugins. * current versions of the plugins.
@ -171,6 +179,12 @@ public class DataFixerAPI {
initializeWorldData(access.getLevelPath(LevelResource.ROOT).toFile(), newWorld); initializeWorldData(access.getLevelPath(LevelResource.ROOT).toFile(), newWorld);
} }
public static void createWorldData(LevelStorageAccess access, WorldGenSettings settings) {
initializeWorldData(access, true);
BCLChunkGenerator.initializeWorldData(settings);
WorldDataAPI.saveFile(BCLib.MOD_ID);
}
/** /**
* Initializes the DataStorage for this world. If the world is new, the patch registry is initialized to the * Initializes the DataStorage for this world. If the world is new, the patch registry is initialized to the
* current versions of the plugins. * current versions of the plugins.
@ -190,8 +204,8 @@ public class DataFixerAPI {
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
private static AtomicProgressListener showProgressScreen() { private static AtomicProgressListener showProgressScreen() {
ProgressScreen ps = new ProgressScreen(Minecraft.getInstance().screen, ProgressScreen ps = new ProgressScreen(Minecraft.getInstance().screen,
Component.translatable("title.bclib.datafixer.progress"), Component.translatable("title.bclib.datafixer.progress"),
Component.translatable("message.bclib.datafixer.progress")); Component.translatable("message.bclib.datafixer.progress"));
Minecraft.getInstance().setScreen(ps); Minecraft.getInstance().setScreen(ps);
return ps; return ps;
} }
@ -298,8 +312,8 @@ public class DataFixerAPI {
private static void showLevelFixErrorScreen(State state, Listener onContinue) { private static void showLevelFixErrorScreen(State state, Listener onContinue) {
Minecraft.getInstance() Minecraft.getInstance()
.setScreen(new LevelFixErrorScreen(Minecraft.getInstance().screen, .setScreen(new LevelFixErrorScreen(Minecraft.getInstance().screen,
state.getErrorMessages(), state.getErrorMessages(),
onContinue)); onContinue));
} }
private static MigrationProfile loadProfileIfNeeded(File levelBaseDir) { private static MigrationProfile loadProfileIfNeeded(File levelBaseDir) {
@ -511,8 +525,8 @@ public class DataFixerAPI {
try { try {
changed[0] |= data.patchBlockState(palette, changed[0] |= data.patchBlockState(palette,
((CompoundTag) tag).getList("BlockStates", ((CompoundTag) tag).getList("BlockStates",
Tag.TAG_LONG)); Tag.TAG_LONG));
} catch (PatchDidiFailException e) { } catch (PatchDidiFailException e) {
BCLib.LOGGER.error("Failed fixing BlockState in " + pos); BCLib.LOGGER.error("Failed fixing BlockState in " + pos);
state.addError("Failed fixing BlockState in " + pos + " (" + e.getMessage() + ")"); state.addError("Failed fixing BlockState in " + pos + " (" + e.getMessage() + ")");

View file

@ -3,16 +3,8 @@ package org.betterx.bclib.config;
import org.betterx.bclib.BCLib; import org.betterx.bclib.BCLib;
public class GeneratorConfig extends NamedPathConfig { public class GeneratorConfig extends NamedPathConfig {
public static final ConfigToken<Boolean> USE_OLD_GENERATOR = ConfigToken.Boolean(false,
"useOldBiomeGenerator",
"options");
public GeneratorConfig() { public GeneratorConfig() {
super(BCLib.MOD_ID, "generator", false); super(BCLib.MOD_ID, "generator", false);
} }
public boolean useOldGenerator() {
return get(USE_OLD_GENERATOR);
}
} }

View file

@ -61,7 +61,7 @@ public abstract class WorldOpenFlowsMixin {
DataExchangeAPI.prepareServerside(); DataExchangeAPI.prepareServerside();
BiomeAPI.prepareNewLevel(); BiomeAPI.prepareNewLevel();
DataFixerAPI.initializeWorldData(this.levelSource, levelID, true); DataFixerAPI.createWorldData(this.levelSource, levelID, worldGenSettings);
LifeCycleAPI._runBeforeLevelLoad(); LifeCycleAPI._runBeforeLevelLoad();
} }
@ -74,7 +74,7 @@ public abstract class WorldOpenFlowsMixin {
DataExchangeAPI.prepareServerside(); DataExchangeAPI.prepareServerside();
BiomeAPI.prepareNewLevel(); BiomeAPI.prepareNewLevel();
DataFixerAPI.initializeWorldData(levelStorageAccess, true); DataFixerAPI.createWorldData(levelStorageAccess, worldData.worldGenSettings());
LifeCycleAPI._runBeforeLevelLoad(); LifeCycleAPI._runBeforeLevelLoad();
} }
} }

View file

@ -12,6 +12,7 @@ import net.minecraft.world.level.levelgen.presets.WorldPresets;
import net.minecraft.world.level.levelgen.structure.StructureSet; import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.levelgen.synth.NormalNoise; import net.minecraft.world.level.levelgen.synth.NormalNoise;
import org.betterx.bclib.presets.worldgen.BCLChunkGenerator;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@ -19,6 +20,7 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyArg;
import java.util.Map; import java.util.Map;
import java.util.Optional;
@Mixin(WorldPresets.Bootstrap.class) @Mixin(WorldPresets.Bootstrap.class)
public abstract class WorldPresetsBootstrapMixin { public abstract class WorldPresetsBootstrapMixin {
@ -51,7 +53,7 @@ public abstract class WorldPresetsBootstrapMixin {
@ModifyArg(method = "run", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/level/levelgen/presets/WorldPresets$Bootstrap;registerCustomOverworldPreset(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/level/dimension/LevelStem;)Lnet/minecraft/core/Holder;")) @ModifyArg(method = "run", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/level/levelgen/presets/WorldPresets$Bootstrap;registerCustomOverworldPreset(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/level/dimension/LevelStem;)Lnet/minecraft/core/Holder;"))
private LevelStem bcl_getOverworldStem(LevelStem overworldStem) { private LevelStem bcl_getOverworldStem(LevelStem overworldStem) {
WorldPreset preset = new org.betterx.bclib.presets.worldgen.WorldPresets.SortableWorldPreset( WorldPreset preset_18 = new org.betterx.bclib.presets.worldgen.WorldPresets.SortableWorldPreset(
Map.of(LevelStem.OVERWORLD, Map.of(LevelStem.OVERWORLD,
overworldStem, overworldStem,
LevelStem.NETHER, LevelStem.NETHER,
@ -59,17 +61,42 @@ public abstract class WorldPresetsBootstrapMixin {
this.netherDimensionType, this.netherDimensionType,
this.structureSets, this.structureSets,
this.noises, this.noises,
this.netherNoiseSettings), this.netherNoiseSettings,
Optional.empty()),
LevelStem.END, LevelStem.END,
org.betterx.bclib.presets.worldgen.WorldPresets.getBCLEndLevelStem(this.biomes, org.betterx.bclib.presets.worldgen.WorldPresets.getBCLEndLevelStem(this.biomes,
this.endDimensionType, this.endDimensionType,
this.structureSets, this.structureSets,
this.noises, this.noises,
this.endNoiseSettings) this.endNoiseSettings,
Optional.empty())
), 0 ), 0
); );
BuiltinRegistries.register(this.presets, org.betterx.bclib.presets.worldgen.WorldPresets.BCL_WORLD, preset); WorldPreset preset_17 = new org.betterx.bclib.presets.worldgen.WorldPresets.SortableWorldPreset(
Map.of(LevelStem.OVERWORLD,
overworldStem,
LevelStem.NETHER,
org.betterx.bclib.presets.worldgen.WorldPresets.getBCLNetherLevelStem(this.biomes,
this.netherDimensionType,
this.structureSets,
this.noises,
this.netherNoiseSettings,
Optional.of(BCLChunkGenerator.BIOME_SOURCE_VERSION_SQUARE)),
LevelStem.END,
org.betterx.bclib.presets.worldgen.WorldPresets.getBCLEndLevelStem(this.biomes,
this.endDimensionType,
this.structureSets,
this.noises,
this.endNoiseSettings,
Optional.of(BCLChunkGenerator.BIOME_SOURCE_VERSION_SQUARE))
), 0
);
BuiltinRegistries.register(this.presets, org.betterx.bclib.presets.worldgen.WorldPresets.BCL_WORLD, preset_18);
BuiltinRegistries.register(this.presets,
org.betterx.bclib.presets.worldgen.WorldPresets.BCL_WORLD_17,
preset_17);
return overworldStem; return overworldStem;
} }

View file

@ -2,19 +2,40 @@ package org.betterx.bclib.presets.worldgen;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.RegistryOps; import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.chunk.ChunkGenerator; 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.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.structure.StructureSet; import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.levelgen.synth.NormalNoise; import net.minecraft.world.level.levelgen.synth.NormalNoise;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.WorldDataAPI;
import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider; import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider;
import org.betterx.bclib.util.ModUtil;
import org.betterx.bclib.world.generator.BCLBiomeSource;
import java.util.Optional;
public class BCLChunkGenerator extends NoiseBasedChunkGenerator { public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
public static int BIOME_SOURCE_VERSION_NONE = -1;
public static int BIOME_SOURCE_VERSION_VANILLA = 0;
public static int BIOME_SOURCE_VERSION_SQUARE = 17;
public static int BIOME_SOURCE_VERSION_HEX = 18;
public static int DEFAULT_BIOME_SOURCE_VERSION = BIOME_SOURCE_VERSION_HEX;
private static String TAG_GENERATOR = "generator";
private static final String TAG_VERSION = "version";
private static final String TAG_BN_GEN_VERSION = "generator_version";
public static final Codec<BCLChunkGenerator> CODEC = RecordCodecBuilder public static final Codec<BCLChunkGenerator> CODEC = RecordCodecBuilder
.create((RecordCodecBuilder.Instance<BCLChunkGenerator> builderInstance) -> { .create((RecordCodecBuilder.Instance<BCLChunkGenerator> builderInstance) -> {
final RecordCodecBuilder<BCLChunkGenerator, Registry<NormalNoise.NoiseParameters>> noiseGetter = RegistryOps final RecordCodecBuilder<BCLChunkGenerator, Registry<NormalNoise.NoiseParameters>> noiseGetter = RegistryOps
@ -38,12 +59,12 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
.apply(builderInstance, builderInstance.stable(BCLChunkGenerator::new)); .apply(builderInstance, builderInstance.stable(BCLChunkGenerator::new));
}); });
public BCLChunkGenerator(Registry<StructureSet> registry, public BCLChunkGenerator(Registry<StructureSet> registry,
Registry<NormalNoise.NoiseParameters> registry2, Registry<NormalNoise.NoiseParameters> registry2,
BiomeSource biomeSource, BiomeSource biomeSource,
Holder<NoiseGeneratorSettings> holder) { Holder<NoiseGeneratorSettings> holder) {
super(registry, registry2, biomeSource, holder); super(registry, registry2, biomeSource, holder);
System.out.println("Chunk Generator: " + this);
} }
@Override @Override
@ -58,4 +79,115 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
} }
return null; return null;
} }
public static int getBiomeVersionForGenerator(ChunkGenerator generator) {
if (generator == null) return BIOME_SOURCE_VERSION_NONE;
if (generator.getBiomeSource() instanceof BCLBiomeSource bcl) {
return bcl.biomeSourceVersion;
} else {
return BIOME_SOURCE_VERSION_VANILLA;
}
}
public static Optional<Holder<LevelStem>> referenceStemForVersion(
ResourceKey<LevelStem> dimensionKey,
int biomeSourceVersion,
RegistryAccess registryAccess,
long seed,
boolean generateStructures,
boolean generateBonusChest
) {
final WorldGenSettings referenceSettings;
if (biomeSourceVersion == BIOME_SOURCE_VERSION_VANILLA) {
referenceSettings = net.minecraft.world.level.levelgen.presets.WorldPresets.createNormalWorldFromPreset(
registryAccess,
seed,
generateStructures,
generateBonusChest);
} else if (biomeSourceVersion == BIOME_SOURCE_VERSION_SQUARE) {
referenceSettings = WorldPresets.createWorldFromPreset(
WorldPresets.BCL_WORLD_17,
registryAccess,
seed,
generateStructures,
generateBonusChest);
} else {
referenceSettings = WorldPresets.createDefaultWorldFromPreset(
registryAccess,
seed,
generateStructures,
generateBonusChest);
}
return referenceSettings.dimensions().getHolder(dimensionKey);
}
public static int getBiomeVersionForCurrentWorld(ResourceKey<LevelStem> key) {
final CompoundTag settingsNbt = getSettingsNbt();
if (!settingsNbt.contains(key.location().toString())) return DEFAULT_BIOME_SOURCE_VERSION;
return settingsNbt.getInt(key.location().toString());
}
private static void writeDimensionVersion(WorldGenSettings settings,
CompoundTag generatorSettings,
ResourceKey<LevelStem> key) {
var dimension = settings.dimensions().getHolder(key);
if (dimension.isPresent()) {
generatorSettings.putInt(key.location().toString(),
getBiomeVersionForGenerator(dimension.get().value().generator()));
} else {
generatorSettings.putInt(key.location().toString(), getBiomeVersionForGenerator(null));
}
}
public static void initializeWorldData(WorldGenSettings settings) {
final CompoundTag settingsNbt = getSettingsNbt();
writeDimensionVersion(settings, settingsNbt, LevelStem.NETHER);
writeDimensionVersion(settings, settingsNbt, LevelStem.END);
}
private static CompoundTag getSettingsNbt() {
return WorldDataAPI.getCompoundTag(BCLib.MOD_ID, TAG_GENERATOR);
}
public static void migrateGeneratorSettings() {
final CompoundTag settingsNbt = getSettingsNbt();
if (settingsNbt.size() == 0) {
BCLib.LOGGER.info("Found World without generator Settings. Setting up data...");
int biomeSourceVersion = DEFAULT_BIOME_SOURCE_VERSION;
final CompoundTag bclRoot = WorldDataAPI.getRootTag(BCLib.MOD_ID);
String bclVersion = "0.0.0";
if (bclRoot.contains(TAG_VERSION)) {
bclVersion = bclRoot.getString(TAG_VERSION);
}
boolean isPre18 = !ModUtil.isLargerOrEqualVersion(bclVersion, "1.0.0");
if (isPre18) {
BCLib.LOGGER.info("World was create pre 1.18!");
biomeSourceVersion = BIOME_SOURCE_VERSION_SQUARE;
}
if (WorldDataAPI.hasMod("betternether")) {
BCLib.LOGGER.info("Found Data from BetterNether, using for migration.");
final CompoundTag bnRoot = WorldDataAPI.getRootTag("betternether");
biomeSourceVersion = "1.17".equals(bnRoot.getString(TAG_BN_GEN_VERSION))
? BIOME_SOURCE_VERSION_SQUARE
: BIOME_SOURCE_VERSION_HEX;
}
BCLib.LOGGER.info("Set world to BiomeSource Version " + biomeSourceVersion);
settingsNbt.putInt(LevelStem.NETHER.location().toString(), biomeSourceVersion);
settingsNbt.putInt(LevelStem.END.location().toString(), biomeSourceVersion);
WorldDataAPI.saveFile(BCLib.MOD_ID);
}
}
@Override
public String toString() {
return "BCLib - Chunk Generator (" + Integer.toHexString(hashCode()) + ")";
}
} }

View file

@ -21,6 +21,7 @@ import com.mojang.datafixers.util.Pair;
import org.betterx.bclib.BCLib; import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.tag.TagAPI; import org.betterx.bclib.api.tag.TagAPI;
import org.betterx.bclib.api.tag.TagType; import org.betterx.bclib.api.tag.TagType;
import org.betterx.bclib.world.generator.BCLBiomeSource;
import org.betterx.bclib.world.generator.BCLibEndBiomeSource; import org.betterx.bclib.world.generator.BCLibEndBiomeSource;
import org.betterx.bclib.world.generator.BCLibNetherBiomeSource; import org.betterx.bclib.world.generator.BCLibNetherBiomeSource;
@ -34,8 +35,9 @@ public class WorldPresets {
Holder<DimensionType> dimension, Holder<DimensionType> dimension,
Registry<StructureSet> structureSets, Registry<StructureSet> structureSets,
Registry<NormalNoise.NoiseParameters> noiseParameters, Registry<NormalNoise.NoiseParameters> noiseParameters,
Holder<NoiseGeneratorSettings> generatorSettings) { Holder<NoiseGeneratorSettings> generatorSettings,
BCLibNetherBiomeSource netherSource = new BCLibNetherBiomeSource(biomes); Optional<Integer> version) {
BCLibNetherBiomeSource netherSource = new BCLibNetherBiomeSource(biomes, version);
LevelStem bclNether = new LevelStem( LevelStem bclNether = new LevelStem(
dimension, dimension,
new BCLChunkGenerator( new BCLChunkGenerator(
@ -52,8 +54,9 @@ public class WorldPresets {
Holder<DimensionType> dimension, Holder<DimensionType> dimension,
Registry<StructureSet> structureSets, Registry<StructureSet> structureSets,
Registry<NormalNoise.NoiseParameters> noiseParameters, Registry<NormalNoise.NoiseParameters> noiseParameters,
Holder<NoiseGeneratorSettings> generatorSettings) { Holder<NoiseGeneratorSettings> generatorSettings,
BCLibEndBiomeSource netherSource = new BCLibEndBiomeSource(biomes); Optional<Integer> version) {
BCLibEndBiomeSource netherSource = new BCLibEndBiomeSource(biomes, version);
LevelStem bclEnd = new LevelStem( LevelStem bclEnd = new LevelStem(
dimension, dimension,
new BCLChunkGenerator( new BCLChunkGenerator(
@ -78,18 +81,39 @@ public class WorldPresets {
TagAPI.registerType(BuiltinRegistries.WORLD_PRESET, "tags/worldgen/world_preset"); TagAPI.registerType(BuiltinRegistries.WORLD_PRESET, "tags/worldgen/world_preset");
public static final ResourceKey<WorldPreset> BCL_WORLD = register(BCLib.makeID("normal")); public static final ResourceKey<WorldPreset> BCL_WORLD = register(BCLib.makeID("normal"));
public static final ResourceKey<WorldPreset> BCL_WORLD_17 = register(BCLib.makeID("legacy_17"), false);
public static Optional<ResourceKey<WorldPreset>> DEFAULT = Optional.of(BCL_WORLD); public static Optional<ResourceKey<WorldPreset>> DEFAULT = Optional.of(BCL_WORLD);
public static WorldGenSettings createWorldFromPreset(ResourceKey<WorldPreset> preset,
RegistryAccess registryAccess,
long seed,
boolean generateStructures,
boolean generateBonusChest) {
WorldGenSettings settings = registryAccess
.registryOrThrow(Registry.WORLD_PRESET_REGISTRY)
.getHolderOrThrow(preset)
.value()
.createWorldGenSettings(seed, generateStructures, generateBonusChest);
for (LevelStem stem : settings.dimensions()) {
if (stem.generator().getBiomeSource() instanceof BCLBiomeSource bcl) {
bcl.setSeed(seed);
}
}
return settings;
}
public static WorldGenSettings createDefaultWorldFromPreset(RegistryAccess registryAccess, public static WorldGenSettings createDefaultWorldFromPreset(RegistryAccess registryAccess,
long seed, long seed,
boolean generateStructures, boolean generateStructures,
boolean generateBonusChest) { boolean generateBonusChest) {
return registryAccess return createWorldFromPreset(DEFAULT.orElseThrow(),
.registryOrThrow(Registry.WORLD_PRESET_REGISTRY) registryAccess,
.getHolderOrThrow(DEFAULT.orElseThrow()) seed,
.value() generateStructures,
.createWorldGenSettings(seed, generateStructures, generateBonusChest); generateBonusChest);
} }
public static Pair<WorldGenSettings, RegistryAccess.Frozen> defaultWorldDataSupplier(RegistryAccess.Frozen frozen) { public static Pair<WorldGenSettings, RegistryAccess.Frozen> defaultWorldDataSupplier(RegistryAccess.Frozen frozen) {
@ -115,8 +139,14 @@ public class WorldPresets {
* @return The key you may use to reference your new Preset * @return The key you may use to reference your new Preset
*/ */
public static ResourceKey<WorldPreset> register(ResourceLocation loc) { public static ResourceKey<WorldPreset> register(ResourceLocation loc) {
return register(loc, true);
}
private static ResourceKey<WorldPreset> register(ResourceLocation loc, boolean addToNormal) {
ResourceKey<WorldPreset> key = ResourceKey.create(Registry.WORLD_PRESET_REGISTRY, loc); ResourceKey<WorldPreset> key = ResourceKey.create(Registry.WORLD_PRESET_REGISTRY, loc);
WORLD_PRESETS.addUntyped(WorldPresetTags.NORMAL, key.location()); if (addToNormal) {
WORLD_PRESETS.addUntyped(WorldPresetTags.NORMAL, key.location());
}
return key; return key;
} }

View file

@ -6,29 +6,50 @@ import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.BiomeSource;
import org.betterx.bclib.api.biomes.BiomeAPI; import org.betterx.bclib.api.biomes.BiomeAPI;
import org.betterx.bclib.presets.worldgen.BCLChunkGenerator;
import java.util.List; import java.util.List;
import java.util.Optional;
public abstract class BCLBiomeSource extends BiomeSource { public abstract class BCLBiomeSource extends BiomeSource {
protected final Registry<Biome> biomeRegistry; protected final Registry<Biome> biomeRegistry;
protected long currentSeed; protected long currentSeed;
public final int biomeSourceVersion;
private static List<Holder<Biome>> preInit(Registry<Biome> biomeRegistry, List<Holder<Biome>> biomes) { private static List<Holder<Biome>> preInit(Registry<Biome> biomeRegistry, List<Holder<Biome>> biomes) {
biomes.forEach(biome -> BiomeAPI.sortBiomeFeatures(biome)); biomes.forEach(biome -> BiomeAPI.sortBiomeFeatures(biome));
return biomes; return biomes;
} }
protected BCLBiomeSource(Registry<Biome> biomeRegistry, List<Holder<Biome>> list) { protected BCLBiomeSource(Registry<Biome> biomeRegistry,
List<Holder<Biome>> list,
long seed,
Optional<Integer> biomeSourceVersion) {
super(preInit(biomeRegistry, list)); super(preInit(biomeRegistry, list));
this.biomeRegistry = biomeRegistry;
this.biomeSourceVersion = biomeSourceVersion.orElse(BCLChunkGenerator.DEFAULT_BIOME_SOURCE_VERSION);
this.currentSeed = seed;
System.out.println(this + " with Registry: " + biomeRegistry.getClass().getName() + "@" + Integer.toHexString( System.out.println(this + " with Registry: " + biomeRegistry.getClass().getName() + "@" + Integer.toHexString(
biomeRegistry.hashCode())); biomeRegistry.hashCode()));
this.biomeRegistry = biomeRegistry;
BiomeAPI.initRegistry(biomeRegistry); BiomeAPI.initRegistry(biomeRegistry);
} }
public void setSeed(long seed) { final public void setSeed(long seed) {
System.out.println(this + " set Seed: " + seed); if (seed != currentSeed) {
this.currentSeed = seed; System.out.println(this + " set Seed: " + seed);
this.currentSeed = seed;
initMap(seed);
}
} }
protected final void initMap(long seed) {
System.out.println(this + " updates Map");
onInitMap(seed);
}
protected abstract void onInitMap(long newSeed);
} }

View file

@ -22,12 +22,14 @@ import org.betterx.bclib.config.ConfigKeeper.StringArrayEntry;
import org.betterx.bclib.config.Configs; import org.betterx.bclib.config.Configs;
import org.betterx.bclib.interfaces.BiomeMap; import org.betterx.bclib.interfaces.BiomeMap;
import org.betterx.bclib.noise.OpenSimplexNoise; import org.betterx.bclib.noise.OpenSimplexNoise;
import org.betterx.bclib.presets.worldgen.BCLChunkGenerator;
import org.betterx.bclib.world.biomes.BCLBiome; import org.betterx.bclib.world.biomes.BCLBiome;
import org.betterx.bclib.world.generator.map.hex.HexBiomeMap; import org.betterx.bclib.world.generator.map.hex.HexBiomeMap;
import org.betterx.bclib.world.generator.map.square.SquareBiomeMap; import org.betterx.bclib.world.generator.map.square.SquareBiomeMap;
import java.awt.*; import java.awt.*;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
public class BCLibEndBiomeSource extends BCLBiomeSource { public class BCLibEndBiomeSource extends BCLBiomeSource {
@ -41,11 +43,16 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
.LONG .LONG
.fieldOf("seed") .fieldOf("seed")
.stable() .stable()
.forGetter(source -> source.currentSeed)) .forGetter(source -> source.currentSeed),
Codec
.INT
.optionalFieldOf("version")
.stable()
.forGetter(source -> Optional.of(source.biomeSourceVersion)))
.apply(instance, .apply(instance,
instance.stable(BCLibEndBiomeSource::new) instance.stable(BCLibEndBiomeSource::new)
) )
); );
private final Holder<Biome> centerBiome; private final Holder<Biome> centerBiome;
private final Holder<Biome> barrens; private final Holder<Biome> barrens;
private final Point pos; private final Point pos;
@ -57,20 +64,23 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
private final BiomePicker endLandBiomePicker; private final BiomePicker endLandBiomePicker;
private final BiomePicker endVoidBiomePicker; private final BiomePicker endVoidBiomePicker;
public BCLibEndBiomeSource(Registry<Biome> biomeRegistry, long seed) { public BCLibEndBiomeSource(Registry<Biome> biomeRegistry, long seed, Optional<Integer> version) {
this(biomeRegistry); this(biomeRegistry, seed, version, true);
this.setSeed(seed);
} }
public BCLibEndBiomeSource(Registry<Biome> biomeRegistry) { public BCLibEndBiomeSource(Registry<Biome> biomeRegistry, Optional<Integer> version) {
super(biomeRegistry, getBiomes(biomeRegistry)); this(biomeRegistry, 0, version, false);
}
private BCLibEndBiomeSource(Registry<Biome> biomeRegistry, long seed, Optional<Integer> version, boolean initMaps) {
super(biomeRegistry, getBiomes(biomeRegistry), seed, version);
endLandBiomePicker = new BiomePicker(biomeRegistry); endLandBiomePicker = new BiomePicker(biomeRegistry);
endVoidBiomePicker = new BiomePicker(biomeRegistry); endVoidBiomePicker = new BiomePicker(biomeRegistry);
List<String> includeVoid = Configs.BIOMES_CONFIG.getEntry("force_include", List<String> includeVoid = Configs.BIOMES_CONFIG.getEntry("force_include",
"end_void_biomes", "end_void_biomes",
StringArrayEntry.class).getValue(); StringArrayEntry.class).getValue();
this.possibleBiomes().forEach(biome -> { this.possibleBiomes().forEach(biome -> {
ResourceLocation key = biome.unwrapKey().orElseThrow().location(); ResourceLocation key = biome.unwrapKey().orElseThrow().location();
String group = key.getNamespace() + "." + key.getPath(); String group = key.getNamespace() + "." + key.getPath();
@ -107,15 +117,19 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
this.endLandFunction = GeneratorOptions.getEndLandFunction(); this.endLandFunction = GeneratorOptions.getEndLandFunction();
this.pos = new Point(); this.pos = new Point();
if (initMaps) {
initMap(seed);
}
} }
private static List<Holder<Biome>> getBiomes(Registry<Biome> biomeRegistry) { private static List<Holder<Biome>> getBiomes(Registry<Biome> biomeRegistry) {
List<String> includeLand = Configs.BIOMES_CONFIG.getEntry("force_include", List<String> includeLand = Configs.BIOMES_CONFIG.getEntry("force_include",
"end_land_biomes", "end_land_biomes",
StringArrayEntry.class).getValue(); StringArrayEntry.class).getValue();
List<String> includeVoid = Configs.BIOMES_CONFIG.getEntry("force_include", List<String> includeVoid = Configs.BIOMES_CONFIG.getEntry("force_include",
"end_void_biomes", "end_void_biomes",
StringArrayEntry.class).getValue(); StringArrayEntry.class).getValue();
return biomeRegistry.stream() return biomeRegistry.stream()
.filter(biome -> biomeRegistry.getResourceKey(biome).isPresent()) .filter(biome -> biomeRegistry.getResourceKey(biome).isPresent())
@ -171,21 +185,22 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
Registry.register(Registry.BIOME_SOURCE, BCLib.makeID("end_biome_source"), CODEC); Registry.register(Registry.BIOME_SOURCE, BCLib.makeID("end_biome_source"), CODEC);
} }
private void initMap(long seed) { @Override
if (GeneratorOptions.useOldBiomeGenerator()) { protected void onInitMap(long seed) {
if ((biomeSourceVersion != BCLChunkGenerator.BIOME_SOURCE_VERSION_HEX)) {
this.mapLand = new SquareBiomeMap(seed, this.mapLand = new SquareBiomeMap(seed,
GeneratorOptions.getBiomeSizeEndLand(), GeneratorOptions.getBiomeSizeEndLand(),
endLandBiomePicker); endLandBiomePicker);
this.mapVoid = new SquareBiomeMap(seed, this.mapVoid = new SquareBiomeMap(seed,
GeneratorOptions.getBiomeSizeEndVoid(), GeneratorOptions.getBiomeSizeEndVoid(),
endVoidBiomePicker); endVoidBiomePicker);
} else { } else {
this.mapLand = new HexBiomeMap(seed, this.mapLand = new HexBiomeMap(seed,
GeneratorOptions.getBiomeSizeEndLand(), GeneratorOptions.getBiomeSizeEndLand(),
endLandBiomePicker); endLandBiomePicker);
this.mapVoid = new HexBiomeMap(seed, this.mapVoid = new HexBiomeMap(seed,
GeneratorOptions.getBiomeSizeEndVoid(), GeneratorOptions.getBiomeSizeEndVoid(),
endVoidBiomePicker); endVoidBiomePicker);
} }
WorldgenRandom chunkRandom = new WorldgenRandom(new LegacyRandomSource(seed)); WorldgenRandom chunkRandom = new WorldgenRandom(new LegacyRandomSource(seed));
@ -193,13 +208,6 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
this.noise = new SimplexNoise(chunkRandom); this.noise = new SimplexNoise(chunkRandom);
} }
@Override
public void setSeed(long seed) {
if (seed == currentSeed) return;
super.setSeed(seed);
initMap(seed);
}
@Override @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.Sampler sampler) {
@ -221,7 +229,7 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
noise, noise,
(biomeX >> 1) + 1, (biomeX >> 1) + 1,
(biomeZ >> 1) + 1 (biomeZ >> 1) + 1
) + (float) SMALL_NOISE.eval(biomeX, biomeZ) * 5; ) + (float) SMALL_NOISE.eval(biomeX, biomeZ) * 5;
if (height > -20F && height < -5F) { if (height > -20F && height < -5F) {
return barrens; return barrens;
@ -249,6 +257,6 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
@Override @Override
public String toString() { public String toString() {
return "BCLib - The End BiomeSource"; return "BCLib - The End BiomeSource (" + Integer.toHexString(hashCode()) + ", version=" + biomeSourceVersion + ", seed=" + currentSeed + ")";
} }
} }

View file

@ -19,15 +19,16 @@ import org.betterx.bclib.api.biomes.BiomeAPI;
import org.betterx.bclib.config.ConfigKeeper.StringArrayEntry; import org.betterx.bclib.config.ConfigKeeper.StringArrayEntry;
import org.betterx.bclib.config.Configs; import org.betterx.bclib.config.Configs;
import org.betterx.bclib.interfaces.BiomeMap; import org.betterx.bclib.interfaces.BiomeMap;
import org.betterx.bclib.presets.worldgen.BCLChunkGenerator;
import org.betterx.bclib.world.biomes.BCLBiome; import org.betterx.bclib.world.biomes.BCLBiome;
import org.betterx.bclib.world.generator.map.MapStack; import org.betterx.bclib.world.generator.map.MapStack;
import org.betterx.bclib.world.generator.map.hex.HexBiomeMap; import org.betterx.bclib.world.generator.map.hex.HexBiomeMap;
import org.betterx.bclib.world.generator.map.square.SquareBiomeMap; import org.betterx.bclib.world.generator.map.square.SquareBiomeMap;
import java.util.List; import java.util.List;
import java.util.Optional;
public class BCLibNetherBiomeSource extends BCLBiomeSource { public class BCLibNetherBiomeSource extends BCLBiomeSource {
private static boolean forceLegacyGenerator = false;
private static int lastWorldHeight; private static int lastWorldHeight;
private static int worldHeight; private static int worldHeight;
public static final Codec<BCLibNetherBiomeSource> CODEC = RecordCodecBuilder public static final Codec<BCLibNetherBiomeSource> CODEC = RecordCodecBuilder
@ -41,15 +42,32 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource {
.stable() .stable()
.forGetter(source -> { .forGetter(source -> {
return source.currentSeed; return source.currentSeed;
}) }),
Codec
.INT
.optionalFieldOf("version")
.stable()
.forGetter(source -> Optional.of(source.biomeSourceVersion))
) )
.apply(instance, instance.stable(BCLibNetherBiomeSource::new)) .apply(instance, instance.stable(BCLibNetherBiomeSource::new))
); );
private BiomeMap biomeMap; private BiomeMap biomeMap;
private final BiomePicker biomePicker; private final BiomePicker biomePicker;
public BCLibNetherBiomeSource(Registry<Biome> biomeRegistry) { public BCLibNetherBiomeSource(Registry<Biome> biomeRegistry, Optional<Integer> version) {
super(biomeRegistry, getBiomes(biomeRegistry)); this(biomeRegistry, 0, version, false);
}
public BCLibNetherBiomeSource(Registry<Biome> biomeRegistry, long seed, Optional<Integer> version) {
this(biomeRegistry, seed, version, true);
}
private BCLibNetherBiomeSource(Registry<Biome> biomeRegistry,
long seed,
Optional<Integer> version,
boolean initMaps) {
super(biomeRegistry, getBiomes(biomeRegistry), seed, version);
biomePicker = new BiomePicker(biomeRegistry); biomePicker = new BiomePicker(biomeRegistry);
this.possibleBiomes().forEach(biome -> { this.possibleBiomes().forEach(biome -> {
@ -69,23 +87,9 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource {
}); });
biomePicker.rebuild(); biomePicker.rebuild();
} if (initMaps) {
initMap(seed);
public BCLibNetherBiomeSource(Registry<Biome> biomeRegistry, long seed) { }
this(biomeRegistry);
setSeed(seed);
}
/**
* When true, the older square generator is used for the nether.
* <p>
* This override is used (for example) by BetterNether to force the legacy generation for worlds
* that were created before 1.18
*
* @param val wether or not you want to force the old generatore.
*/
public static void setForceLegacyGeneration(boolean val) {
forceLegacyGenerator = val;
} }
/** /**
@ -128,12 +132,6 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource {
Registry.register(Registry.BIOME_SOURCE, BCLib.makeID("nether_biome_source"), CODEC); Registry.register(Registry.BIOME_SOURCE, BCLib.makeID("nether_biome_source"), CODEC);
} }
@Override
public void setSeed(long seed) {
if (seed == currentSeed) return;
super.setSeed(seed);
initMap(seed);
}
@Override @Override
public Holder<Biome> getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.Sampler var4) { public Holder<Biome> getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.Sampler var4) {
@ -156,9 +154,9 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource {
return CODEC; return CODEC;
} }
private void initMap(long seed) { @Override
boolean useLegacy = GeneratorOptions.useOldBiomeGenerator() || forceLegacyGenerator; protected void onInitMap(long seed) {
TriFunction<Long, Integer, BiomePicker, BiomeMap> mapConstructor = useLegacy TriFunction<Long, Integer, BiomePicker, BiomeMap> mapConstructor = (biomeSourceVersion != BCLChunkGenerator.BIOME_SOURCE_VERSION_HEX)
? SquareBiomeMap::new ? SquareBiomeMap::new
: HexBiomeMap::new; : HexBiomeMap::new;
if (worldHeight > 128 && GeneratorOptions.useVerticalBiomes()) { if (worldHeight > 128 && GeneratorOptions.useVerticalBiomes()) {
@ -179,6 +177,6 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource {
@Override @Override
public String toString() { public String toString() {
return "BCLib - Nether BiomeSource (" + Integer.toHexString(hashCode()) + ")"; return "BCLib - Nether BiomeSource (" + Integer.toHexString(hashCode()) + ", version=" + biomeSourceVersion + ", seed=" + currentSeed + ")";
} }
} }

View file

@ -15,7 +15,6 @@ public class GeneratorOptions {
private static Function<Point, Boolean> endLandFunction; private static Function<Point, Boolean> endLandFunction;
private static boolean customNetherBiomeSource = true; private static boolean customNetherBiomeSource = true;
private static boolean customEndBiomeSource = true; private static boolean customEndBiomeSource = true;
private static boolean useOldBiomeGenerator = false;
private static boolean verticalBiomes = true; private static boolean verticalBiomes = true;
private static long farEndBiomesSqr = 1000000; private static long farEndBiomesSqr = 1000000;
private static boolean fixEndBiomeSource = true; private static boolean fixEndBiomeSource = true;
@ -24,13 +23,12 @@ public class GeneratorOptions {
public static void init() { public static void init() {
biomeSizeNether = Configs.GENERATOR_CONFIG.getInt("nether.biomeMap", "biomeSize", 256); biomeSizeNether = Configs.GENERATOR_CONFIG.getInt("nether.biomeMap", "biomeSize", 256);
biomeVSizeNether = Configs.GENERATOR_CONFIG.getInt("nether.biomeMap", biomeVSizeNether = Configs.GENERATOR_CONFIG.getInt("nether.biomeMap",
"biomeVerticalSize(onlyInTallNether)", "biomeVerticalSize(onlyInTallNether)",
86); 86);
biomeSizeEndLand = Configs.GENERATOR_CONFIG.getInt("end.biomeMap", "biomeSizeLand", 256); biomeSizeEndLand = Configs.GENERATOR_CONFIG.getInt("end.biomeMap", "biomeSizeLand", 256);
biomeSizeEndVoid = Configs.GENERATOR_CONFIG.getInt("end.biomeMap", "biomeSizeVoid", 256); biomeSizeEndVoid = Configs.GENERATOR_CONFIG.getInt("end.biomeMap", "biomeSizeVoid", 256);
customNetherBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options", "customNetherBiomeSource", true); customNetherBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options", "customNetherBiomeSource", true);
customEndBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options", "customEndBiomeSource", true); customEndBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options", "customEndBiomeSource", true);
useOldBiomeGenerator = Configs.GENERATOR_CONFIG.useOldGenerator();
verticalBiomes = Configs.GENERATOR_CONFIG.getBoolean("options", "verticalBiomesInTallNether", true); verticalBiomes = Configs.GENERATOR_CONFIG.getBoolean("options", "verticalBiomesInTallNether", true);
fixEndBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options.biomeSource", "fixEndBiomeSource", true); fixEndBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options.biomeSource", "fixEndBiomeSource", true);
fixNetherBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options.biomeSource", "fixNetherBiomeSource", true); fixNetherBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options.biomeSource", "fixNetherBiomeSource", true);
@ -90,9 +88,6 @@ public class GeneratorOptions {
return customEndBiomeSource; return customEndBiomeSource;
} }
public static boolean useOldBiomeGenerator() {
return useOldBiomeGenerator;
}
public static boolean useVerticalBiomes() { public static boolean useVerticalBiomes() {
return verticalBiomes; return verticalBiomes;