[Fix] Modded WorldGenSettings
are not properly loaded for new Worlds (#20)
This commit is contained in:
parent
5fd087d8b7
commit
13acf48894
8 changed files with 93 additions and 18 deletions
|
@ -1,6 +1,7 @@
|
||||||
package org.betterx.bclib.api.v2.generator;
|
package org.betterx.bclib.api.v2.generator;
|
||||||
|
|
||||||
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
|
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
|
||||||
|
import org.betterx.bclib.api.v2.levelgen.biomes.InternalBiomeAPI;
|
||||||
import org.betterx.worlds.together.biomesource.BiomeSourceFromRegistry;
|
import org.betterx.worlds.together.biomesource.BiomeSourceFromRegistry;
|
||||||
import org.betterx.worlds.together.biomesource.MergeableBiomeSource;
|
import org.betterx.worlds.together.biomesource.MergeableBiomeSource;
|
||||||
import org.betterx.worlds.together.world.BiomeSourceWithNoiseRelatedSettings;
|
import org.betterx.worlds.together.world.BiomeSourceWithNoiseRelatedSettings;
|
||||||
|
@ -21,6 +22,7 @@ import java.util.Set;
|
||||||
|
|
||||||
public abstract class BCLBiomeSource extends BiomeSource implements BiomeSourceWithSeed, MergeableBiomeSource<BCLBiomeSource>, BiomeSourceWithNoiseRelatedSettings, BiomeSourceFromRegistry<BCLBiomeSource> {
|
public abstract class BCLBiomeSource extends BiomeSource implements BiomeSourceWithSeed, MergeableBiomeSource<BCLBiomeSource>, BiomeSourceWithNoiseRelatedSettings, BiomeSourceFromRegistry<BCLBiomeSource> {
|
||||||
protected final Registry<Biome> biomeRegistry;
|
protected final Registry<Biome> biomeRegistry;
|
||||||
|
private int registryModificationCounter;
|
||||||
protected long currentSeed;
|
protected long currentSeed;
|
||||||
protected int maxHeight;
|
protected int maxHeight;
|
||||||
|
|
||||||
|
@ -40,11 +42,16 @@ public abstract class BCLBiomeSource extends BiomeSource implements BiomeSourceW
|
||||||
long seed
|
long seed
|
||||||
) {
|
) {
|
||||||
super(preInit(biomeRegistry, list));
|
super(preInit(biomeRegistry, list));
|
||||||
|
this.registryModificationCounter = InternalBiomeAPI.getBiomeRegistryModificationCount(biomeRegistry);
|
||||||
this.biomeRegistry = biomeRegistry;
|
this.biomeRegistry = biomeRegistry;
|
||||||
this.currentSeed = seed;
|
this.currentSeed = seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean didBiomeRegistryChange() {
|
||||||
|
return this.registryModificationCounter != InternalBiomeAPI.getBiomeRegistryModificationCount(biomeRegistry);
|
||||||
|
}
|
||||||
|
|
||||||
final public void setSeed(long seed) {
|
final public void setSeed(long seed) {
|
||||||
if (seed != currentSeed) {
|
if (seed != currentSeed) {
|
||||||
System.out.println(this + " set Seed: " + seed);
|
System.out.println(this + " set Seed: " + seed);
|
||||||
|
|
|
@ -32,6 +32,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
@ -60,6 +61,8 @@ public class InternalBiomeAPI {
|
||||||
);
|
);
|
||||||
static final Map<Biome, BCLBiome> CLIENT = Maps.newHashMap();
|
static final Map<Biome, BCLBiome> CLIENT = Maps.newHashMap();
|
||||||
static final Map<Holder<PlacedFeature>, Integer> FEATURE_ORDER = Maps.newHashMap();
|
static final Map<Holder<PlacedFeature>, Integer> FEATURE_ORDER = Maps.newHashMap();
|
||||||
|
|
||||||
|
static final Map<Registry<Biome>, AtomicInteger> BIOME_ADDITIONS = Maps.newHashMap();
|
||||||
static final MutableInt FEATURE_ORDER_ID = new MutableInt(0);
|
static final MutableInt FEATURE_ORDER_ID = new MutableInt(0);
|
||||||
static final Map<ResourceKey<LevelStem>, List<BiConsumer<ResourceLocation, Holder<Biome>>>> MODIFICATIONS = Maps.newHashMap();
|
static final Map<ResourceKey<LevelStem>, List<BiConsumer<ResourceLocation, Holder<Biome>>>> MODIFICATIONS = Maps.newHashMap();
|
||||||
static final Map<ResourceKey, List<BiConsumer<ResourceLocation, Holder<Biome>>>> TAG_ADDERS = Maps.newHashMap();
|
static final Map<ResourceKey, List<BiConsumer<ResourceLocation, Holder<Biome>>>> TAG_ADDERS = Maps.newHashMap();
|
||||||
|
@ -359,13 +362,30 @@ public class InternalBiomeAPI {
|
||||||
.register((rawId, id, biome) -> {
|
.register((rawId, id, biome) -> {
|
||||||
BCLBiome b = BiomeAPI.getBiome(id);
|
BCLBiome b = BiomeAPI.getBiome(id);
|
||||||
if (!"minecraft".equals(id.getNamespace()) && (b == null || b == BCLBiomeRegistry.EMPTY_BIOME)) {
|
if (!"minecraft".equals(id.getNamespace()) && (b == null || b == BCLBiomeRegistry.EMPTY_BIOME)) {
|
||||||
//BCLib.LOGGER.info(" #### " + rawId + ", " + biome + ", " + id);
|
BCLib.LOGGER.info(" #### " + rawId + ", " + biome + ", " + id);
|
||||||
BIOMES_TO_SORT.add(id);
|
BIOMES_TO_SORT.add(id);
|
||||||
|
BIOME_ADDITIONS.computeIfAbsent(oBiomeRegistry.get(), reg -> new AtomicInteger(0))
|
||||||
|
.incrementAndGet();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The BCLBiomeSource keeps track of Modifications that happen after the BiomeSource was initialized.
|
||||||
|
* This appears to happen especially for new Worlds where the Biome Source is deserialized
|
||||||
|
* when the WolrdPreset registry is built for the CreateScreen. However Farbic Biomes are not yet
|
||||||
|
* added to the biomeRegistry at this stage.
|
||||||
|
* The counter is incremented in the DynamicRegistrySetupCallback.EVENT for the Biome Registry
|
||||||
|
*
|
||||||
|
* @param registry The registry you want to check
|
||||||
|
* @return The current number of additions since the world creation was started
|
||||||
|
*/
|
||||||
|
public static int getBiomeRegistryModificationCount(Registry<Biome> registry) {
|
||||||
|
if (registry == null) return 0;
|
||||||
|
return BIOME_ADDITIONS.computeIfAbsent(registry, reg -> new AtomicInteger(0)).get();
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean registryContainsBound(ResourceKey<Biome> key) {
|
public static boolean registryContainsBound(ResourceKey<Biome> key) {
|
||||||
Registry<Biome> reg = biomeRegistry;
|
Registry<Biome> reg = biomeRegistry;
|
||||||
if (reg == null) reg = BuiltinRegistries.BIOME;
|
if (reg == null) reg = BuiltinRegistries.BIOME;
|
||||||
|
|
|
@ -1,25 +1,16 @@
|
||||||
package org.betterx.worlds.together.biomesource;
|
package org.betterx.worlds.together.biomesource;
|
||||||
|
|
||||||
import net.minecraft.core.Holder;
|
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.world.level.biome.Biome;
|
import net.minecraft.world.level.biome.Biome;
|
||||||
import net.minecraft.world.level.biome.BiomeSource;
|
import net.minecraft.world.level.biome.BiomeSource;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public interface BiomeSourceFromRegistry<T extends BiomeSource> {
|
public interface BiomeSourceFromRegistry<T extends BiomeSource> {
|
||||||
Registry<Biome> getBiomeRegistry();
|
Registry<Biome> getBiomeRegistry();
|
||||||
|
boolean didBiomeRegistryChange();
|
||||||
|
|
||||||
default <R extends BiomeSource> boolean sameRegistryButDifferentBiomes(BiomeSourceFromRegistry<R> other) {
|
default <R extends BiomeSource> boolean togetherBiomeSourceContentChanged(BiomeSourceFromRegistry<R> other) {
|
||||||
if (other.getBiomeRegistry() == getBiomeRegistry()) {
|
if (other.getBiomeRegistry() != getBiomeRegistry()) return true;
|
||||||
Set<Holder<Biome>> mySet = ((T) this).possibleBiomes();
|
if (other.didBiomeRegistryChange() || didBiomeRegistryChange()) return true;
|
||||||
Set<Holder<Biome>> otherSet = ((R) other).possibleBiomes();
|
|
||||||
if (otherSet.size() != mySet.size()) return true;
|
|
||||||
for (Holder<Biome> b : mySet) {
|
|
||||||
if (!otherSet.contains(b))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,24 @@
|
||||||
package org.betterx.worlds.together.biomesource;
|
package org.betterx.worlds.together.biomesource;
|
||||||
|
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.world.level.biome.Biome;
|
||||||
import net.minecraft.world.level.biome.BiomeSource;
|
import net.minecraft.world.level.biome.BiomeSource;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public interface MergeableBiomeSource<B extends BiomeSource> {
|
public interface MergeableBiomeSource<B extends BiomeSource> {
|
||||||
|
default boolean togetherShouldMerge(BiomeSource inputBiomeSource) {
|
||||||
|
Set<Holder<Biome>> mySet = ((B) this).possibleBiomes();
|
||||||
|
Set<Holder<Biome>> otherSet = inputBiomeSource.possibleBiomes();
|
||||||
|
if (otherSet.size() != mySet.size()) return true;
|
||||||
|
|
||||||
|
for (Holder<Biome> b : mySet) {
|
||||||
|
if (!otherSet.contains(b))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a BiomeSource that merges the settings of this one with the Biomes (and possibly settings) from the
|
* Returns a BiomeSource that merges the settings of this one with the Biomes (and possibly settings) from the
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.betterx.worlds.together.chunkgenerator;
|
||||||
|
|
||||||
import org.betterx.worlds.together.biomesource.BiomeSourceFromRegistry;
|
import org.betterx.worlds.together.biomesource.BiomeSourceFromRegistry;
|
||||||
import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig;
|
import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig;
|
||||||
|
import org.betterx.worlds.together.biomesource.MergeableBiomeSource;
|
||||||
|
|
||||||
import net.minecraft.core.RegistryAccess;
|
import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
@ -20,7 +21,7 @@ public interface EnforceableChunkGenerator<G extends ChunkGenerator> {
|
||||||
WorldGenSettings settings
|
WorldGenSettings settings
|
||||||
);
|
);
|
||||||
|
|
||||||
default boolean needsChunkGeneratorRepair(ChunkGenerator chunkGenerator) {
|
default boolean togetherShouldRepair(ChunkGenerator chunkGenerator) {
|
||||||
ChunkGenerator self = (ChunkGenerator) this;
|
ChunkGenerator self = (ChunkGenerator) this;
|
||||||
if (this == chunkGenerator || chunkGenerator == null) return false;
|
if (this == chunkGenerator || chunkGenerator == null) return false;
|
||||||
|
|
||||||
|
@ -33,7 +34,11 @@ public interface EnforceableChunkGenerator<G extends ChunkGenerator> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (one instanceof BiomeSourceFromRegistry ba && two instanceof BiomeSourceFromRegistry bb) {
|
if (one instanceof BiomeSourceFromRegistry ba && two instanceof BiomeSourceFromRegistry bb) {
|
||||||
if (ba.sameRegistryButDifferentBiomes(bb))
|
if (ba.togetherBiomeSourceContentChanged(bb))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (one instanceof MergeableBiomeSource ba) {
|
||||||
|
if (ba.togetherShouldMerge(two))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@ import net.minecraft.world.level.levelgen.presets.WorldPreset;
|
||||||
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.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
public class WorldGenUtil {
|
public class WorldGenUtil {
|
||||||
public static final String TAG_PRESET = "preset";
|
public static final String TAG_PRESET = "preset";
|
||||||
public static final String TAG_GENERATOR = "generator";
|
public static final String TAG_GENERATOR = "generator";
|
||||||
|
@ -136,6 +138,7 @@ public class WorldGenUtil {
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ApiStatus.Internal
|
||||||
public static WorldGenSettings repairBiomeSourceInAllDimensions(
|
public static WorldGenSettings repairBiomeSourceInAllDimensions(
|
||||||
RegistryAccess registryAccess,
|
RegistryAccess registryAccess,
|
||||||
WorldGenSettings settings
|
WorldGenSettings settings
|
||||||
|
@ -148,9 +151,25 @@ public class WorldGenUtil {
|
||||||
|
|
||||||
ChunkGenerator referenceGenerator = dimensions.get(key);
|
ChunkGenerator referenceGenerator = dimensions.get(key);
|
||||||
if (referenceGenerator instanceof EnforceableChunkGenerator enforcer) {
|
if (referenceGenerator instanceof EnforceableChunkGenerator enforcer) {
|
||||||
|
// This list contains the vanilla default level stem (only available if a new world is loaded) as well as
|
||||||
|
// The currently loaded stem
|
||||||
|
if (WorldBootstrap.getDefaultCreateWorldPresetSettings() != null) {
|
||||||
|
LevelStem vanillaDefaultStem = WorldBootstrap.getDefaultCreateWorldPresetSettings()
|
||||||
|
.dimensions()
|
||||||
|
.get(key);
|
||||||
|
|
||||||
|
loadedStem = vanillaDefaultStem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// now compare the reference world settings (the ones that were created when the world was
|
||||||
|
// started) with the settings that were loaded by the game.
|
||||||
|
// If those do not match, we will create a new ChunkGenerator / BiomeSources with appropriate
|
||||||
|
// settings
|
||||||
|
|
||||||
final ChunkGenerator loadedChunkGenerator = loadedStem.generator();
|
final ChunkGenerator loadedChunkGenerator = loadedStem.generator();
|
||||||
|
|
||||||
if (enforcer.needsChunkGeneratorRepair(loadedChunkGenerator)) {
|
if (enforcer.togetherShouldRepair(loadedChunkGenerator)) {
|
||||||
settings = enforcer.enforceGeneratorInWorldGenSettings(
|
settings = enforcer.enforceGeneratorInWorldGenSettings(
|
||||||
registryAccess,
|
registryAccess,
|
||||||
key,
|
key,
|
||||||
|
@ -168,11 +187,13 @@ public class WorldGenUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!didRepair) {
|
if (!didRepair) {
|
||||||
if (loadedStem.generator().getBiomeSource() instanceof ReloadableBiomeSource reload) {
|
if (loadedStem.generator().getBiomeSource() instanceof ReloadableBiomeSource reload) {
|
||||||
reload.reloadBiomes();
|
reload.reloadBiomes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ public class CreateWorldScreenMixin {
|
||||||
private static WorldLoader.WorldDataSupplier<WorldGenSettings> wt_NewDefaultSettings(WorldLoader.WorldDataSupplier<WorldGenSettings> worldDataSupplier) {
|
private static WorldLoader.WorldDataSupplier<WorldGenSettings> wt_NewDefaultSettings(WorldLoader.WorldDataSupplier<WorldGenSettings> worldDataSupplier) {
|
||||||
return (resourceManager, dataPackConfig) -> {
|
return (resourceManager, dataPackConfig) -> {
|
||||||
Pair<WorldGenSettings, RegistryAccess.Frozen> res = worldDataSupplier.get(resourceManager, dataPackConfig);
|
Pair<WorldGenSettings, RegistryAccess.Frozen> res = worldDataSupplier.get(resourceManager, dataPackConfig);
|
||||||
|
WorldBootstrap.InGUI.setDefaultCreateWorldSettings(res.getFirst());
|
||||||
return WorldGenUtil.defaultWorldDataSupplier(res.getSecond());
|
return WorldGenUtil.defaultWorldDataSupplier(res.getSecond());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,12 @@ import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
public class WorldBootstrap {
|
public class WorldBootstrap {
|
||||||
|
private static WorldGenSettings DEFAULT_CREATE_WORLD_PRESET_SETTINGS;
|
||||||
|
|
||||||
|
public static WorldGenSettings getDefaultCreateWorldPresetSettings() {
|
||||||
|
return DEFAULT_CREATE_WORLD_PRESET_SETTINGS;
|
||||||
|
}
|
||||||
|
|
||||||
private static RegistryAccess LAST_REGISTRY_ACCESS = null;
|
private static RegistryAccess LAST_REGISTRY_ACCESS = null;
|
||||||
|
|
||||||
public static RegistryAccess getLastRegistryAccess() {
|
public static RegistryAccess getLastRegistryAccess() {
|
||||||
|
@ -144,6 +150,12 @@ public class WorldBootstrap {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class InGUI {
|
public static class InGUI {
|
||||||
|
|
||||||
|
|
||||||
|
public static void setDefaultCreateWorldSettings(WorldGenSettings worldGenSettings) {
|
||||||
|
DEFAULT_CREATE_WORLD_PRESET_SETTINGS = worldGenSettings;
|
||||||
|
}
|
||||||
|
|
||||||
public static void registryReadyOnNewWorld(WorldGenSettingsComponent worldGenSettingsComponent) {
|
public static void registryReadyOnNewWorld(WorldGenSettingsComponent worldGenSettingsComponent) {
|
||||||
Helpers.onRegistryReady(worldGenSettingsComponent.registryHolder());
|
Helpers.onRegistryReady(worldGenSettingsComponent.registryHolder());
|
||||||
}
|
}
|
||||||
|
@ -228,6 +240,8 @@ public class WorldBootstrap {
|
||||||
String levelID,
|
String levelID,
|
||||||
LevelStorageSource levelSource
|
LevelStorageSource levelSource
|
||||||
) {
|
) {
|
||||||
|
//when we load a world, we do not want to reuse the default world settings
|
||||||
|
DEFAULT_CREATE_WORLD_PRESET_SETTINGS = null;
|
||||||
try {
|
try {
|
||||||
var levelStorageAccess = levelSource.createAccess(levelID);
|
var levelStorageAccess = levelSource.createAccess(levelID);
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue