[Change] WorldPresets are configured through BiomeSources

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,36 @@
package org.betterx.worlds.together.mixin.common;
import org.betterx.worlds.together.chunkgenerator.ChunkGeneratorUtils;
import com.mojang.datafixers.DataFixer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.Services;
import net.minecraft.server.WorldStem;
import net.minecraft.server.level.progress.ChunkProgressListenerFactory;
import net.minecraft.server.packs.repository.PackRepository;
import net.minecraft.world.level.storage.LevelStorageSource;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.net.Proxy;
@Mixin(value = MinecraftServer.class, priority = 2000)
public class MinecraftServerMixinLate {
@Inject(at = @At("RETURN"), method = "<init>")
private void bcl_restoreBiomeSource(
Thread thread,
LevelStorageSource.LevelStorageAccess levelStorageAccess,
PackRepository packRepository,
WorldStem worldStem,
Proxy proxy,
DataFixer dataFixer,
Services services,
ChunkProgressListenerFactory chunkProgressListenerFactory,
CallbackInfo ci
) {
ChunkGeneratorUtils.restoreOriginalBiomeSourceInAllDimension(worldStem.worldData().worldGenSettings());
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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