Datapack Biome Handling with Custom BiomeSource
This commit is contained in:
parent
e10994a1e8
commit
9d0a640173
28 changed files with 1109 additions and 619 deletions
|
@ -2,35 +2,20 @@ package org.betterx.bclib.presets.worldgen;
|
|||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
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.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
||||
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.synth.NormalNoise;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
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.util.ModUtil;
|
||||
import org.betterx.bclib.world.generator.BCLBiomeSource;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
|
||||
|
||||
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
|
||||
.create((RecordCodecBuilder.Instance<BCLChunkGenerator> builderInstance) -> {
|
||||
final RecordCodecBuilder<BCLChunkGenerator, Registry<NormalNoise.NoiseParameters>> noiseGetter = RegistryOps
|
||||
|
@ -75,107 +60,6 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
|
|||
return null;
|
||||
}
|
||||
|
||||
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,
|
||||
int biomeSourceVersion,
|
||||
RegistryAccess registryAccess,
|
||||
long seed,
|
||||
boolean generateStructures,
|
||||
boolean generateBonusChest
|
||||
) {
|
||||
final WorldGenSettings referenceSettings;
|
||||
if (biomeSourceVersion == BCLBiomeSource.BIOME_SOURCE_VERSION_VANILLA) {
|
||||
referenceSettings = net.minecraft.world.level.levelgen.presets.WorldPresets.createNormalWorldFromPreset(
|
||||
registryAccess,
|
||||
seed,
|
||||
generateStructures,
|
||||
generateBonusChest);
|
||||
} else if (biomeSourceVersion == BCLBiomeSource.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 BCLBiomeSource.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 = BCLBiomeSource.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 = BCLBiomeSource.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))
|
||||
? BCLBiomeSource.BIOME_SOURCE_VERSION_SQUARE
|
||||
: BCLBiomeSource.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()) + ")";
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package org.betterx.bclib.presets.worldgen;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.RegistryFileCodec;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.presets.WorldPreset;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.betterx.bclib.mixin.common.WorldPresetAccessor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class BCLWorldPreset extends WorldPreset {
|
||||
public final WorldPresetSettings settings;
|
||||
public final int sortOrder;
|
||||
public static final Codec<BCLWorldPreset> DIRECT_CODEC = RecordCodecBuilder.create(builderInstance -> {
|
||||
RecordCodecBuilder<BCLWorldPreset, Map<ResourceKey<LevelStem>, LevelStem>> dimensionsBuidler = Codec
|
||||
.unboundedMap(ResourceKey.codec(Registry.LEVEL_STEM_REGISTRY), LevelStem.CODEC)
|
||||
.fieldOf("dimensions")
|
||||
.forGetter(worldPreset -> worldPreset.getDimensions());
|
||||
|
||||
RecordCodecBuilder<BCLWorldPreset, Integer> sortBuilder = Codec.INT
|
||||
.fieldOf("sort_order")
|
||||
.forGetter(wp -> wp.sortOrder);
|
||||
|
||||
RecordCodecBuilder<BCLWorldPreset, WorldPresetSettings> settingsBuilder = WorldPresetSettings.CODEC
|
||||
.fieldOf("settings")
|
||||
.forGetter(wp -> wp.settings);
|
||||
|
||||
return builderInstance
|
||||
.group(dimensionsBuidler, sortBuilder, settingsBuilder)
|
||||
.apply(builderInstance, BCLWorldPreset::new);
|
||||
});
|
||||
|
||||
public static final Codec<Holder<WorldPreset>> CODEC = RegistryFileCodec.create(
|
||||
Registry.WORLD_PRESET_REGISTRY,
|
||||
(Codec<WorldPreset>) ((Object) DIRECT_CODEC));
|
||||
|
||||
public BCLWorldPreset(Map<ResourceKey<LevelStem>, LevelStem> map, int sortOrder, WorldPresetSettings settings) {
|
||||
super(map);
|
||||
this.sortOrder = sortOrder;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
private Map<ResourceKey<LevelStem>, LevelStem> getDimensions() {
|
||||
return WorldPresetAccessor.class.cast(this).bcl_getDimensions();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
package org.betterx.bclib.presets.worldgen;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
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.WorldGenSettings;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.interfaces.ChunkGeneratorAccessor;
|
||||
import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider;
|
||||
import org.betterx.bclib.world.generator.BCLBiomeSource;
|
||||
import org.betterx.bclib.world.generator.BCLibNetherBiomeSource;
|
||||
|
||||
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) -> {
|
||||
RecordCodecBuilder<BCLWorldPresetSettings, Integer> netherVersion = Codec.INT
|
||||
.fieldOf(LevelStem.NETHER.location().toString())
|
||||
.forGetter((BCLWorldPresetSettings settings) -> settings.netherVersion);
|
||||
|
||||
RecordCodecBuilder<BCLWorldPresetSettings, Integer> endVersion = Codec.INT
|
||||
.fieldOf(LevelStem.END.location().toString())
|
||||
.forGetter((BCLWorldPresetSettings settings) -> settings.endVersion);
|
||||
|
||||
|
||||
return builderInstance.group(netherVersion, endVersion)
|
||||
.apply(builderInstance, builderInstance.stable(BCLWorldPresetSettings::new));
|
||||
});
|
||||
public final int netherVersion;
|
||||
public final int endVersion;
|
||||
|
||||
public BCLWorldPresetSettings(int version) {
|
||||
this(version, version);
|
||||
}
|
||||
|
||||
public BCLWorldPresetSettings(int netherVersion, int endVersion) {
|
||||
this.netherVersion = netherVersion;
|
||||
this.endVersion = endVersion;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Codec<? extends WorldPresetSettings> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
public BCLWorldPreset buildPreset(LevelStem overworldStem,
|
||||
WorldGenUtilities.Context netherContext,
|
||||
WorldGenUtilities.Context endContext) {
|
||||
return new BCLWorldPreset(buildDimensionMap(overworldStem, netherContext, endContext), 1000, this);
|
||||
}
|
||||
|
||||
public Map<ResourceKey<LevelStem>, LevelStem> buildDimensionMap(LevelStem overworldStem,
|
||||
WorldGenUtilities.Context netherContext,
|
||||
WorldGenUtilities.Context endContext) {
|
||||
return Map.of(LevelStem.OVERWORLD,
|
||||
overworldStem,
|
||||
LevelStem.NETHER,
|
||||
createNetherStem(netherContext),
|
||||
LevelStem.END,
|
||||
createEndStem(endContext)
|
||||
);
|
||||
}
|
||||
|
||||
public int getVersion(ResourceKey<LevelStem> key) {
|
||||
if (key == LevelStem.NETHER) return netherVersion;
|
||||
if (key == LevelStem.END) return endVersion;
|
||||
|
||||
return BCLBiomeSource.BIOME_SOURCE_VERSION_VANILLA;
|
||||
}
|
||||
|
||||
public LevelStem createStem(WorldGenUtilities.Context ctx, ResourceKey<LevelStem> key) {
|
||||
if (key == LevelStem.NETHER) return createNetherStem(ctx);
|
||||
if (key == LevelStem.END) return createEndStem(ctx);
|
||||
return null;
|
||||
}
|
||||
|
||||
public LevelStem createNetherStem(WorldGenUtilities.Context ctx) {
|
||||
return WorldGenUtilities.getBCLNetherLevelStem(ctx, Optional.of(netherVersion));
|
||||
}
|
||||
|
||||
public LevelStem createEndStem(WorldGenUtilities.Context ctx) {
|
||||
return WorldGenUtilities.getBCLEndLevelStem(ctx, Optional.of(endVersion));
|
||||
}
|
||||
|
||||
public BiomeSource fixBiomeSource(BiomeSource biomeSource, Set<Holder<Biome>> datapackBiomes) {
|
||||
if (biomeSource instanceof BCLibNetherBiomeSource bs) {
|
||||
return bs.createCopyForDatapack(datapackBiomes);
|
||||
}
|
||||
return biomeSource;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public WorldGenSettings fixSettingsInCurrentWorld(RegistryAccess access, ResourceKey<LevelStem> dimensionKey,
|
||||
ResourceKey<DimensionType> dimensionTypeKey,
|
||||
WorldGenSettings settings) {
|
||||
var oldNether = settings.dimensions().getHolder(dimensionKey);
|
||||
int loaderVersion = WorldGenUtilities.getBiomeVersionForGenerator(oldNether
|
||||
.map(h -> h.value().generator())
|
||||
.orElse(null));
|
||||
|
||||
int targetVersion = getVersion(dimensionKey);
|
||||
if (loaderVersion != targetVersion) {
|
||||
BCLib.LOGGER.info("Enforcing Correct Generator for " + dimensionKey.location().toString() + ".");
|
||||
var chunkGenerator = oldNether.map(h -> h.value().generator()).orElse(null);
|
||||
Optional<Holder<LevelStem>> refLevelStem = WorldGenUtilities.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 (chunkGenerator instanceof ChunkGeneratorAccessor generator) {
|
||||
if (chunkGenerator instanceof NoiseGeneratorSettingsProvider noiseProvider) {
|
||||
final Set<Holder<Biome>> biomes = chunkGenerator.getBiomeSource().possibleBiomes();
|
||||
|
||||
referenceGenerator = new BCLChunkGenerator(generator.bclib_getStructureSetsRegistry(),
|
||||
noiseProvider.bclib_getNoises(),
|
||||
fixBiomeSource(referenceGenerator.getBiomeSource(), biomes),
|
||||
noiseProvider.bclib_getNoiseGeneratorSettingHolders());
|
||||
}
|
||||
}
|
||||
|
||||
return WorldGenUtilities.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);
|
||||
return settings;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package org.betterx.bclib.presets.worldgen;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.data.BuiltinRegistries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.WorldPresetTags;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.presets.WorldPreset;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.tag.TagAPI;
|
||||
import org.betterx.bclib.api.tag.TagType;
|
||||
import org.betterx.bclib.world.generator.BCLBiomeSource;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class BCLWorldPresets {
|
||||
|
||||
public static final TagType.Simple<WorldPreset> WORLD_PRESETS =
|
||||
TagAPI.registerType(BuiltinRegistries.WORLD_PRESET, "tags/worldgen/world_preset");
|
||||
private static Map<ResourceKey<WorldPreset>, PresetBuilder> BUILDERS = Maps.newHashMap();
|
||||
private static Map<ResourceKey<WorldPreset>, WorldPresetSettings> SETTINGS = Maps.newHashMap();
|
||||
public static final ResourceKey<WorldPreset> BCL_WORLD =
|
||||
register(BCLib.makeID("normal"),
|
||||
(overworldStem, netherContext, endContext) ->
|
||||
new BCLWorldPresetSettings(BCLBiomeSource.DEFAULT_BIOME_SOURCE_VERSION).buildPreset(
|
||||
overworldStem,
|
||||
netherContext,
|
||||
endContext),
|
||||
true);
|
||||
public static Optional<ResourceKey<WorldPreset>> DEFAULT = Optional.of(BCL_WORLD);
|
||||
public static final ResourceKey<WorldPreset> BCL_WORLD_17 = register(BCLib.makeID("legacy_17"),
|
||||
(overworldStem, netherContext, endContext) ->
|
||||
new BCLWorldPresetSettings(BCLBiomeSource.BIOME_SOURCE_VERSION_SQUARE).buildPreset(
|
||||
overworldStem,
|
||||
netherContext,
|
||||
endContext),
|
||||
true);
|
||||
|
||||
/**
|
||||
* Registers a custom WorldPreset (with custom rules and behaviour)
|
||||
* <p>
|
||||
* See also {@link org.betterx.bclib.client.presets.WorldPresetsUI} if you need to add a Customize Button/Screen
|
||||
* for your preset
|
||||
*
|
||||
* @param loc The ID of your Preset
|
||||
* @return The key you may use to reference your new Preset
|
||||
*/
|
||||
private 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);
|
||||
if (addToNormal) {
|
||||
WORLD_PRESETS.addUntyped(WorldPresetTags.NORMAL, key.location());
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
public static void registerPresets() {
|
||||
|
||||
}
|
||||
|
||||
public static ResourceKey<WorldPreset> register(ResourceLocation loc,
|
||||
PresetBuilder builder,
|
||||
boolean visibleInUI) {
|
||||
ResourceKey<WorldPreset> key = register(loc, visibleInUI);
|
||||
|
||||
if (BUILDERS == null) {
|
||||
BCLib.LOGGER.error("Unable to register WorldPreset '" + loc + "'.");
|
||||
|
||||
} else {
|
||||
BUILDERS.put(key, builder);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
public static void bootstrapPresets(Registry<WorldPreset> presets,
|
||||
LevelStem overworldStem,
|
||||
WorldGenUtilities.Context netherContext,
|
||||
WorldGenUtilities.Context endContext) {
|
||||
|
||||
for (Map.Entry<ResourceKey<WorldPreset>, PresetBuilder> e : BUILDERS.entrySet()) {
|
||||
BCLWorldPreset preset = e.getValue().create(overworldStem, netherContext, endContext);
|
||||
SETTINGS.put(e.getKey(), preset.settings);
|
||||
BuiltinRegistries.register(presets, e.getKey(), preset);
|
||||
}
|
||||
BUILDERS = null;
|
||||
}
|
||||
|
||||
public static WorldPresetSettings getSettingsForPreset(ResourceKey<WorldPreset> key) {
|
||||
return SETTINGS.getOrDefault(key, BCLWorldPresetSettings.DEFAULT);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PresetBuilder {
|
||||
BCLWorldPreset create(LevelStem overworldStem,
|
||||
WorldGenUtilities.Context netherContext,
|
||||
WorldGenUtilities.Context endContext);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,382 @@
|
|||
package org.betterx.bclib.presets.worldgen;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.Registry;
|
||||
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.util.RandomSource;
|
||||
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.DimensionType;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
import net.minecraft.world.level.levelgen.presets.WorldPreset;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureSet;
|
||||
import net.minecraft.world.level.levelgen.synth.NormalNoise;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.WorldDataAPI;
|
||||
import org.betterx.bclib.mixin.common.RegistryOpsAccessor;
|
||||
import org.betterx.bclib.util.ModUtil;
|
||||
import org.betterx.bclib.world.generator.BCLBiomeSource;
|
||||
import org.betterx.bclib.world.generator.BCLibEndBiomeSource;
|
||||
import org.betterx.bclib.world.generator.BCLibNetherBiomeSource;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class WorldGenUtilities {
|
||||
private static final String TAG_VERSION = "version";
|
||||
private static final String TAG_BN_GEN_VERSION = "generator_version";
|
||||
private static String TAG_GENERATOR = "generator";
|
||||
|
||||
@NotNull
|
||||
public static LevelStem getBCLNetherLevelStem(Context context, Optional<Integer> version) {
|
||||
BCLibNetherBiomeSource netherSource = new BCLibNetherBiomeSource(context.biomes, version);
|
||||
return getBCLNetherLevelStem(context, netherSource);
|
||||
}
|
||||
|
||||
public static LevelStem getBCLNetherLevelStem(StemContext context, BiomeSource biomeSource) {
|
||||
return new LevelStem(
|
||||
context.dimension,
|
||||
new BCLChunkGenerator(
|
||||
context.structureSets,
|
||||
context.noiseParameters,
|
||||
biomeSource,
|
||||
context.generatorSettings)
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static LevelStem getBCLEndLevelStem(StemContext context, BiomeSource biomeSource) {
|
||||
return new LevelStem(
|
||||
context.dimension,
|
||||
new BCLChunkGenerator(
|
||||
context.structureSets,
|
||||
context.noiseParameters,
|
||||
biomeSource,
|
||||
context.generatorSettings)
|
||||
);
|
||||
}
|
||||
|
||||
public static LevelStem getBCLEndLevelStem(Context context, Optional<Integer> version) {
|
||||
BCLibEndBiomeSource endSource = new BCLibEndBiomeSource(context.biomes, version);
|
||||
return getBCLEndLevelStem(context, endSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Datapacks can change the world's generator. This Method will ensure, that the Generators contain
|
||||
* the correct BiomeSources for this world
|
||||
*
|
||||
* @param settings
|
||||
* @return
|
||||
*/
|
||||
public static WorldGenSettings fixSettingsInCurrentWorld(Optional<RegistryOps<Tag>> registryOps,
|
||||
WorldGenSettings settings) {
|
||||
if (registryOps.orElse(null) instanceof RegistryOpsAccessor acc) {
|
||||
return getWorldSettings().repairSettingsOnLoad(acc.bcl_getRegistryAccess(), settings);
|
||||
} else {
|
||||
BCLib.LOGGER.error("Unable to obtain registryAccess when enforcing generators.");
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
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,
|
||||
long seed,
|
||||
boolean generateStructures,
|
||||
boolean generateBonusChest) {
|
||||
return createWorldFromPreset(BCLWorldPresets.DEFAULT.orElseThrow(),
|
||||
registryAccess,
|
||||
seed,
|
||||
generateStructures,
|
||||
generateBonusChest);
|
||||
}
|
||||
|
||||
public static Pair<WorldGenSettings, RegistryAccess.Frozen> defaultWorldDataSupplier(RegistryAccess.Frozen frozen) {
|
||||
WorldGenSettings worldGenSettings = createDefaultWorldFromPreset(frozen);
|
||||
return Pair.of(worldGenSettings, frozen);
|
||||
}
|
||||
|
||||
public static WorldGenSettings createDefaultWorldFromPreset(RegistryAccess registryAccess, long seed) {
|
||||
return createDefaultWorldFromPreset(registryAccess, seed, true, false);
|
||||
}
|
||||
|
||||
public static WorldGenSettings createDefaultWorldFromPreset(RegistryAccess registryAccess) {
|
||||
return createDefaultWorldFromPreset(registryAccess, RandomSource.create().nextLong());
|
||||
}
|
||||
|
||||
public static WorldGenSettings replaceGenerator(
|
||||
ResourceKey<LevelStem> dimensionKey,
|
||||
ResourceKey<DimensionType> dimensionTypeKey,
|
||||
int biomeSourceVersion,
|
||||
RegistryAccess registryAccess,
|
||||
WorldGenSettings worldGenSettings
|
||||
) {
|
||||
Optional<Holder<LevelStem>> oLevelStem = referenceStemForVersion(
|
||||
dimensionKey,
|
||||
biomeSourceVersion,
|
||||
registryAccess,
|
||||
worldGenSettings.seed(),
|
||||
worldGenSettings.generateStructures(),
|
||||
worldGenSettings.generateStructures()
|
||||
);
|
||||
return replaceGenerator(dimensionKey,
|
||||
dimensionTypeKey,
|
||||
registryAccess,
|
||||
worldGenSettings,
|
||||
oLevelStem.map(l -> l.value().generator()).orElseThrow());
|
||||
}
|
||||
|
||||
public static WorldGenSettings replaceGenerator(
|
||||
ResourceKey<LevelStem> dimensionKey,
|
||||
ResourceKey<DimensionType> dimensionTypeKey,
|
||||
RegistryAccess registryAccess,
|
||||
WorldGenSettings worldGenSettings,
|
||||
ChunkGenerator generator
|
||||
) {
|
||||
Registry<DimensionType> dimensionTypeRegistry = registryAccess.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY);
|
||||
Registry<LevelStem> newDimensions = withDimension(dimensionKey,
|
||||
dimensionTypeKey,
|
||||
dimensionTypeRegistry,
|
||||
worldGenSettings.dimensions(),
|
||||
generator);
|
||||
return new WorldGenSettings(worldGenSettings.seed(),
|
||||
worldGenSettings.generateStructures(),
|
||||
worldGenSettings.generateBonusChest(),
|
||||
newDimensions);
|
||||
}
|
||||
|
||||
public static WorldGenSettings replaceStem(
|
||||
ResourceKey<LevelStem> dimensionKey,
|
||||
WorldGenSettings worldGenSettings,
|
||||
LevelStem levelStem
|
||||
) {
|
||||
Registry<LevelStem> newDimensions = withDimension(dimensionKey,
|
||||
worldGenSettings.dimensions(),
|
||||
levelStem);
|
||||
return new WorldGenSettings(worldGenSettings.seed(),
|
||||
worldGenSettings.generateStructures(),
|
||||
worldGenSettings.generateBonusChest(),
|
||||
newDimensions);
|
||||
}
|
||||
|
||||
public static Registry<LevelStem> withDimension(ResourceKey<LevelStem> dimensionKey,
|
||||
ResourceKey<DimensionType> dimensionTypeKey,
|
||||
Registry<DimensionType> dimensionTypeRegistry,
|
||||
Registry<LevelStem> inputDimensions,
|
||||
ChunkGenerator generator) {
|
||||
|
||||
LevelStem levelStem = inputDimensions.get(dimensionKey);
|
||||
Holder<DimensionType> dimensionType = levelStem == null
|
||||
? dimensionTypeRegistry.getOrCreateHolderOrThrow(dimensionTypeKey)
|
||||
: levelStem.typeHolder();
|
||||
return withDimension(dimensionKey, inputDimensions, new LevelStem(dimensionType, generator));
|
||||
}
|
||||
|
||||
public static Registry<LevelStem> withDimension(ResourceKey<LevelStem> dimensionKey,
|
||||
Registry<LevelStem> inputDimensions,
|
||||
LevelStem levelStem) {
|
||||
MappedRegistry<LevelStem> writableRegistry = new MappedRegistry<>(Registry.LEVEL_STEM_REGISTRY,
|
||||
Lifecycle.experimental(),
|
||||
null);
|
||||
writableRegistry.register(dimensionKey,
|
||||
levelStem,
|
||||
Lifecycle.stable());
|
||||
for (Map.Entry<ResourceKey<LevelStem>, LevelStem> entry : inputDimensions.entrySet()) {
|
||||
ResourceKey<LevelStem> resourceKey = entry.getKey();
|
||||
if (resourceKey == dimensionKey) continue;
|
||||
writableRegistry.register(resourceKey,
|
||||
entry.getValue(),
|
||||
inputDimensions.lifecycle(entry.getValue()));
|
||||
}
|
||||
return writableRegistry;
|
||||
}
|
||||
|
||||
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,
|
||||
int biomeSourceVersion,
|
||||
RegistryAccess registryAccess,
|
||||
long seed,
|
||||
boolean generateStructures,
|
||||
boolean generateBonusChest
|
||||
) {
|
||||
final WorldGenSettings referenceSettings;
|
||||
if (biomeSourceVersion == BCLBiomeSource.BIOME_SOURCE_VERSION_VANILLA) {
|
||||
referenceSettings = net.minecraft.world.level.levelgen.presets.WorldPresets.createNormalWorldFromPreset(
|
||||
registryAccess,
|
||||
seed,
|
||||
generateStructures,
|
||||
generateBonusChest);
|
||||
} else if (biomeSourceVersion == BCLBiomeSource.BIOME_SOURCE_VERSION_SQUARE) {
|
||||
referenceSettings = createWorldFromPreset(
|
||||
BCLWorldPresets.BCL_WORLD_17,
|
||||
registryAccess,
|
||||
seed,
|
||||
generateStructures,
|
||||
generateBonusChest);
|
||||
} else {
|
||||
referenceSettings = 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 BCLBiomeSource.DEFAULT_BIOME_SOURCE_VERSION;
|
||||
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 void writeDimensionVersion(WorldGenSettings settings,
|
||||
CompoundTag generatorSettings,
|
||||
ResourceKey<LevelStem> key) {
|
||||
generatorSettings.putInt(key.location().toString(), getDimensionVersion(settings, key));
|
||||
}
|
||||
|
||||
public static void initializeWorldData(WorldGenSettings settings) {
|
||||
updateWorldData(getDimensionVersion(settings, LevelStem.NETHER), getDimensionVersion(settings, LevelStem.END));
|
||||
}
|
||||
|
||||
public static void updateWorldData(int netherVersion, int endVersion) {
|
||||
BCLWorldPresetSettings worldSettings = new BCLWorldPresetSettings(netherVersion, endVersion);
|
||||
final RegistryAccess registryAccess = RegistryAccess.builtinCopy();
|
||||
final RegistryOps<Tag> registryOps = RegistryOps.create(NbtOps.INSTANCE, registryAccess);
|
||||
final var codec = WorldPresetSettings.CODEC.orElse(worldSettings);
|
||||
final var encodeResult = codec.encodeStart(registryOps, worldSettings);
|
||||
|
||||
if (encodeResult.result().isPresent()) {
|
||||
final CompoundTag settingsNbt = WorldDataAPI.getRootTag(BCLib.TOGETHER_WORLDS);
|
||||
settingsNbt.put(TAG_GENERATOR, encodeResult.result().get());
|
||||
} else {
|
||||
BCLib.LOGGER.error("Unable to encode world generator settings generator for level.dat.");
|
||||
}
|
||||
|
||||
WorldDataAPI.saveFile(BCLib.TOGETHER_WORLDS);
|
||||
}
|
||||
|
||||
static CompoundTag getSettingsNbt() {
|
||||
return WorldDataAPI.getCompoundTag(BCLib.TOGETHER_WORLDS, TAG_GENERATOR);
|
||||
}
|
||||
|
||||
public static WorldPresetSettings getWorldSettings() {
|
||||
final RegistryAccess registryAccess = RegistryAccess.builtinCopy();
|
||||
final RegistryOps<Tag> registryOps = RegistryOps.create(NbtOps.INSTANCE, registryAccess);
|
||||
|
||||
Optional<WorldPresetSettings> oLevelStem = WorldPresetSettings.CODEC
|
||||
.parse(new Dynamic<>(registryOps, getSettingsNbt()))
|
||||
.resultOrPartial(BCLib.LOGGER::error);
|
||||
|
||||
return oLevelStem.orElse(BCLWorldPresetSettings.DEFAULT);
|
||||
}
|
||||
|
||||
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 = BCLBiomeSource.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 = BCLBiomeSource.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))
|
||||
? BCLBiomeSource.BIOME_SOURCE_VERSION_SQUARE
|
||||
: BCLBiomeSource.BIOME_SOURCE_VERSION_HEX;
|
||||
}
|
||||
|
||||
BCLib.LOGGER.info("Set world to BiomeSource Version " + biomeSourceVersion);
|
||||
updateWorldData(biomeSourceVersion, biomeSourceVersion);
|
||||
}
|
||||
}
|
||||
|
||||
public static class StemContext {
|
||||
public final Holder<DimensionType> dimension;
|
||||
public final Registry<StructureSet> structureSets;
|
||||
public final Registry<NormalNoise.NoiseParameters> noiseParameters;
|
||||
public final Holder<NoiseGeneratorSettings> generatorSettings;
|
||||
|
||||
public StemContext(Holder<DimensionType> dimension,
|
||||
Registry<StructureSet> structureSets,
|
||||
Registry<NormalNoise.NoiseParameters> noiseParameters,
|
||||
Holder<NoiseGeneratorSettings> generatorSettings) {
|
||||
this.dimension = dimension;
|
||||
this.structureSets = structureSets;
|
||||
this.noiseParameters = noiseParameters;
|
||||
this.generatorSettings = generatorSettings;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Context extends StemContext {
|
||||
public final Registry<Biome> biomes;
|
||||
|
||||
public Context(Registry<Biome> biomes, Holder<DimensionType> dimension,
|
||||
Registry<StructureSet> structureSets,
|
||||
Registry<NormalNoise.NoiseParameters> noiseParameters,
|
||||
Holder<NoiseGeneratorSettings> generatorSettings) {
|
||||
super(dimension, structureSets, noiseParameters, generatorSettings);
|
||||
this.biomes = biomes;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package org.betterx.bclib.presets.worldgen;
|
||||
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import org.betterx.bclib.BCLib;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public abstract class WorldPresetSettings {
|
||||
public static final ResourceKey<Registry<Codec<? extends WorldPresetSettings>>> WORLD_PRESET_SETTINGS_REGISTRY =
|
||||
createRegistryKey(BCLib.makeID("worldgen/world_preset_settings"));
|
||||
|
||||
public static final Registry<Codec<? extends WorldPresetSettings>> WORLD_PRESET_SETTINGS =
|
||||
registerSimple(WORLD_PRESET_SETTINGS_REGISTRY);
|
||||
|
||||
public static final Codec<WorldPresetSettings> CODEC = WORLD_PRESET_SETTINGS
|
||||
.byNameCodec()
|
||||
.dispatchStable(WorldPresetSettings::codec, Function.identity());
|
||||
|
||||
|
||||
private static <T> ResourceKey<Registry<T>> createRegistryKey(ResourceLocation location) {
|
||||
|
||||
return ResourceKey.createRegistryKey(location);
|
||||
}
|
||||
|
||||
private static <T> Registry<T> registerSimple(ResourceKey<? extends Registry<T>> resourceKey) {
|
||||
return new MappedRegistry<>(resourceKey, Lifecycle.stable(), null);
|
||||
}
|
||||
|
||||
public static Codec<? extends WorldPresetSettings> register(ResourceLocation loc,
|
||||
Codec<? extends WorldPresetSettings> codec) {
|
||||
return Registry.register(WORLD_PRESET_SETTINGS, loc, codec);
|
||||
}
|
||||
|
||||
public static void bootstrap() {
|
||||
register(BCLib.makeID("bcl_world_preset_settings"), BCLWorldPresetSettings.CODEC);
|
||||
}
|
||||
|
||||
public abstract Codec<? extends WorldPresetSettings> codec();
|
||||
public abstract WorldGenSettings repairSettingsOnLoad(RegistryAccess registryAccess, WorldGenSettings settings);
|
||||
}
|
|
@ -1,287 +0,0 @@
|
|||
package org.betterx.bclib.presets.worldgen;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.data.BuiltinRegistries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.WorldPresetTags;
|
||||
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;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
import net.minecraft.world.level.levelgen.presets.WorldPreset;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureSet;
|
||||
import net.minecraft.world.level.levelgen.synth.NormalNoise;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.tag.TagAPI;
|
||||
import org.betterx.bclib.api.tag.TagType;
|
||||
import org.betterx.bclib.interfaces.ChunkGeneratorAccessor;
|
||||
import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider;
|
||||
import org.betterx.bclib.world.generator.BCLBiomeSource;
|
||||
import org.betterx.bclib.world.generator.BCLibEndBiomeSource;
|
||||
import org.betterx.bclib.world.generator.BCLibNetherBiomeSource;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class WorldPresets {
|
||||
@NotNull
|
||||
public static LevelStem getBCLNetherLevelStem(Registry<Biome> biomes,
|
||||
Holder<DimensionType> dimension,
|
||||
Registry<StructureSet> structureSets,
|
||||
Registry<NormalNoise.NoiseParameters> noiseParameters,
|
||||
Holder<NoiseGeneratorSettings> generatorSettings,
|
||||
Optional<Integer> version) {
|
||||
BCLibNetherBiomeSource netherSource = new BCLibNetherBiomeSource(biomes, version);
|
||||
LevelStem bclNether = new LevelStem(
|
||||
dimension,
|
||||
new BCLChunkGenerator(
|
||||
structureSets,
|
||||
noiseParameters,
|
||||
netherSource,
|
||||
generatorSettings)
|
||||
);
|
||||
return bclNether;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static LevelStem getBCLEndLevelStem(Registry<Biome> biomes,
|
||||
Holder<DimensionType> dimension,
|
||||
Registry<StructureSet> structureSets,
|
||||
Registry<NormalNoise.NoiseParameters> noiseParameters,
|
||||
Holder<NoiseGeneratorSettings> generatorSettings,
|
||||
Optional<Integer> version) {
|
||||
BCLibEndBiomeSource netherSource = new BCLibEndBiomeSource(biomes, version);
|
||||
LevelStem bclEnd = new LevelStem(
|
||||
dimension,
|
||||
new BCLChunkGenerator(
|
||||
structureSets,
|
||||
noiseParameters,
|
||||
netherSource,
|
||||
generatorSettings)
|
||||
);
|
||||
return bclEnd;
|
||||
}
|
||||
|
||||
public static class SortableWorldPreset extends WorldPreset {
|
||||
public final int sortOrder;
|
||||
|
||||
public SortableWorldPreset(Map<ResourceKey<LevelStem>, LevelStem> map, int sortOrder) {
|
||||
super(map);
|
||||
this.sortOrder = sortOrder;
|
||||
}
|
||||
}
|
||||
|
||||
public static final TagType.Simple<WorldPreset> WORLD_PRESETS =
|
||||
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_17 = register(BCLib.makeID("legacy_17"), false);
|
||||
|
||||
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,
|
||||
long seed,
|
||||
boolean generateStructures,
|
||||
boolean generateBonusChest) {
|
||||
return createWorldFromPreset(DEFAULT.orElseThrow(),
|
||||
registryAccess,
|
||||
seed,
|
||||
generateStructures,
|
||||
generateBonusChest);
|
||||
}
|
||||
|
||||
public static Pair<WorldGenSettings, RegistryAccess.Frozen> defaultWorldDataSupplier(RegistryAccess.Frozen frozen) {
|
||||
WorldGenSettings worldGenSettings = createDefaultWorldFromPreset(frozen);
|
||||
return Pair.of(worldGenSettings, frozen);
|
||||
}
|
||||
|
||||
public static WorldGenSettings createDefaultWorldFromPreset(RegistryAccess registryAccess, long seed) {
|
||||
return createDefaultWorldFromPreset(registryAccess, seed, true, false);
|
||||
}
|
||||
|
||||
public static WorldGenSettings createDefaultWorldFromPreset(RegistryAccess registryAccess) {
|
||||
return createDefaultWorldFromPreset(registryAccess, RandomSource.create().nextLong());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public static WorldGenSettings fixSettingsInCurrentWorld(ResourceKey<LevelStem> dimensionKey,
|
||||
ResourceKey<DimensionType> dimensionTypeKey,
|
||||
WorldGenSettings settings) {
|
||||
var oldNether = settings.dimensions().getHolder(dimensionKey);
|
||||
int loaderVersion = BCLChunkGenerator.getBiomeVersionForGenerator(oldNether
|
||||
.map(h -> h.value().generator())
|
||||
.orElse(null));
|
||||
|
||||
int targetVersion = BCLChunkGenerator.getBiomeVersionForCurrentWorld(dimensionKey);
|
||||
if (loaderVersion != targetVersion) {
|
||||
BCLib.LOGGER.info("Enforcing Correct Generator for " + dimensionKey.location().toString() + ".");
|
||||
var chunkGenerator = oldNether.map(h -> h.value().generator()).orElse(null);
|
||||
RegistryAccess access = RegistryAccess.builtinCopy();
|
||||
Optional<Holder<LevelStem>> refLevelStem = BCLChunkGenerator.referenceStemForVersion(
|
||||
dimensionKey,
|
||||
targetVersion,
|
||||
access,
|
||||
settings.seed(),
|
||||
settings.generateStructures(),
|
||||
settings.generateStructures()
|
||||
);
|
||||
|
||||
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 (chunkGenerator instanceof ChunkGeneratorAccessor generator) {
|
||||
if (chunkGenerator instanceof NoiseGeneratorSettingsProvider noiseProvider) {
|
||||
//TODO: Make sure our BiomeSource reuses the BiomeList from the Datapack Source
|
||||
referenceGenerator = new BCLChunkGenerator(generator.bclib_getStructureSetsRegistry(),
|
||||
noiseProvider.bclib_getNoises(),
|
||||
referenceGenerator.getBiomeSource(),
|
||||
noiseProvider.bclib_getNoiseGeneratorSettingHolders());
|
||||
}
|
||||
}
|
||||
|
||||
return WorldPresets.replaceGenerator(dimensionKey,
|
||||
dimensionTypeKey,
|
||||
access,
|
||||
settings,
|
||||
referenceGenerator);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
public static WorldGenSettings replaceGenerator(
|
||||
ResourceKey<LevelStem> dimensionKey,
|
||||
ResourceKey<DimensionType> dimensionTypeKey,
|
||||
int biomeSourceVersion,
|
||||
RegistryAccess registryAccess,
|
||||
WorldGenSettings worldGenSettings
|
||||
) {
|
||||
Optional<Holder<LevelStem>> oLevelStem = BCLChunkGenerator.referenceStemForVersion(
|
||||
dimensionKey,
|
||||
biomeSourceVersion,
|
||||
registryAccess,
|
||||
worldGenSettings.seed(),
|
||||
worldGenSettings.generateStructures(),
|
||||
worldGenSettings.generateStructures()
|
||||
);
|
||||
return replaceGenerator(dimensionKey,
|
||||
dimensionTypeKey,
|
||||
registryAccess,
|
||||
worldGenSettings,
|
||||
oLevelStem.map(l -> l.value().generator()).orElseThrow());
|
||||
}
|
||||
|
||||
public static WorldGenSettings replaceGenerator(
|
||||
ResourceKey<LevelStem> dimensionKey,
|
||||
ResourceKey<DimensionType> dimensionTypeKey,
|
||||
RegistryAccess registryAccess,
|
||||
WorldGenSettings worldGenSettings,
|
||||
ChunkGenerator generator
|
||||
) {
|
||||
Registry<DimensionType> registry = registryAccess.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY);
|
||||
Registry<LevelStem> registry2 = withDimension(dimensionKey, dimensionTypeKey, registry,
|
||||
worldGenSettings.dimensions(),
|
||||
generator);
|
||||
return new WorldGenSettings(worldGenSettings.seed(),
|
||||
worldGenSettings.generateStructures(),
|
||||
worldGenSettings.generateBonusChest(),
|
||||
registry2);
|
||||
}
|
||||
|
||||
public static Registry<LevelStem> withDimension(ResourceKey<LevelStem> dimensionKey,
|
||||
ResourceKey<DimensionType> dimensionTypeKey,
|
||||
Registry<DimensionType> registry,
|
||||
Registry<LevelStem> registry2,
|
||||
ChunkGenerator chunkGenerator) {
|
||||
LevelStem levelStem = registry2.get(dimensionKey);
|
||||
Holder<DimensionType> holder = levelStem == null
|
||||
? registry.getOrCreateHolderOrThrow(dimensionTypeKey)
|
||||
: levelStem.typeHolder();
|
||||
return withDimension(dimensionKey, registry2, holder, chunkGenerator);
|
||||
}
|
||||
|
||||
public static Registry<LevelStem> withDimension(ResourceKey<LevelStem> dimensionKey, Registry<LevelStem> registry,
|
||||
Holder<DimensionType> holder,
|
||||
ChunkGenerator chunkGenerator) {
|
||||
MappedRegistry<LevelStem> writableRegistry = new MappedRegistry<LevelStem>(Registry.LEVEL_STEM_REGISTRY,
|
||||
Lifecycle.experimental(),
|
||||
null);
|
||||
writableRegistry.register(dimensionKey,
|
||||
new LevelStem(holder, chunkGenerator),
|
||||
Lifecycle.stable());
|
||||
for (Map.Entry<ResourceKey<LevelStem>, LevelStem> entry : registry.entrySet()) {
|
||||
ResourceKey<LevelStem> resourceKey = entry.getKey();
|
||||
if (resourceKey == dimensionKey) continue;
|
||||
writableRegistry.register(resourceKey,
|
||||
entry.getValue(),
|
||||
registry.lifecycle(entry.getValue()));
|
||||
}
|
||||
return writableRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a custom WorldPreset (with custom rules and behaviour)
|
||||
* <p>
|
||||
* See also {@link org.betterx.bclib.client.presets.WorldPresetsUI} if you need to add a Customize Button/Screen
|
||||
* for your preset
|
||||
*
|
||||
* @param loc The ID of your Preset
|
||||
* @return The key you may use to reference your new Preset
|
||||
*/
|
||||
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);
|
||||
if (addToNormal) {
|
||||
WORLD_PRESETS.addUntyped(WorldPresetTags.NORMAL, key.location());
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
public static void registerPresets() {
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue