[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;
|
||||
|
||||
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.MergeableBiomeSource;
|
||||
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> {
|
||||
protected final Registry<Biome> biomeRegistry;
|
||||
private int registryModificationCounter;
|
||||
protected long currentSeed;
|
||||
protected int maxHeight;
|
||||
|
||||
|
@ -40,11 +42,16 @@ public abstract class BCLBiomeSource extends BiomeSource implements BiomeSourceW
|
|||
long seed
|
||||
) {
|
||||
super(preInit(biomeRegistry, list));
|
||||
|
||||
this.registryModificationCounter = InternalBiomeAPI.getBiomeRegistryModificationCount(biomeRegistry);
|
||||
this.biomeRegistry = biomeRegistry;
|
||||
this.currentSeed = seed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean didBiomeRegistryChange() {
|
||||
return this.registryModificationCounter != InternalBiomeAPI.getBiomeRegistryModificationCount(biomeRegistry);
|
||||
}
|
||||
|
||||
final public void setSeed(long seed) {
|
||||
if (seed != currentSeed) {
|
||||
System.out.println(this + " set Seed: " + seed);
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Stream;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
@ -60,6 +61,8 @@ public class InternalBiomeAPI {
|
|||
);
|
||||
static final Map<Biome, BCLBiome> CLIENT = 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 Map<ResourceKey<LevelStem>, List<BiConsumer<ResourceLocation, Holder<Biome>>>> MODIFICATIONS = 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) -> {
|
||||
BCLBiome b = BiomeAPI.getBiome(id);
|
||||
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);
|
||||
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) {
|
||||
Registry<Biome> reg = biomeRegistry;
|
||||
if (reg == null) reg = BuiltinRegistries.BIOME;
|
||||
|
|
|
@ -1,25 +1,16 @@
|
|||
package org.betterx.worlds.together.biomesource;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface BiomeSourceFromRegistry<T extends BiomeSource> {
|
||||
Registry<Biome> getBiomeRegistry();
|
||||
boolean didBiomeRegistryChange();
|
||||
|
||||
default <R extends BiomeSource> boolean sameRegistryButDifferentBiomes(BiomeSourceFromRegistry<R> other) {
|
||||
if (other.getBiomeRegistry() == getBiomeRegistry()) {
|
||||
Set<Holder<Biome>> mySet = ((T) this).possibleBiomes();
|
||||
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;
|
||||
}
|
||||
}
|
||||
default <R extends BiomeSource> boolean togetherBiomeSourceContentChanged(BiomeSourceFromRegistry<R> other) {
|
||||
if (other.getBiomeRegistry() != getBiomeRegistry()) return true;
|
||||
if (other.didBiomeRegistryChange() || didBiomeRegistryChange()) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,24 @@
|
|||
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 java.util.Set;
|
||||
|
||||
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
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.betterx.worlds.together.chunkgenerator;
|
|||
|
||||
import org.betterx.worlds.together.biomesource.BiomeSourceFromRegistry;
|
||||
import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig;
|
||||
import org.betterx.worlds.together.biomesource.MergeableBiomeSource;
|
||||
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
|
@ -20,7 +21,7 @@ public interface EnforceableChunkGenerator<G extends ChunkGenerator> {
|
|||
WorldGenSettings settings
|
||||
);
|
||||
|
||||
default boolean needsChunkGeneratorRepair(ChunkGenerator chunkGenerator) {
|
||||
default boolean togetherShouldRepair(ChunkGenerator chunkGenerator) {
|
||||
ChunkGenerator self = (ChunkGenerator) this;
|
||||
if (this == chunkGenerator || chunkGenerator == null) return false;
|
||||
|
||||
|
@ -33,7 +34,11 @@ public interface EnforceableChunkGenerator<G extends ChunkGenerator> {
|
|||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.synth.NormalNoise;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
public class WorldGenUtil {
|
||||
public static final String TAG_PRESET = "preset";
|
||||
public static final String TAG_GENERATOR = "generator";
|
||||
|
@ -136,6 +138,7 @@ public class WorldGenUtil {
|
|||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@ApiStatus.Internal
|
||||
public static WorldGenSettings repairBiomeSourceInAllDimensions(
|
||||
RegistryAccess registryAccess,
|
||||
WorldGenSettings settings
|
||||
|
@ -148,9 +151,25 @@ public class WorldGenUtil {
|
|||
|
||||
ChunkGenerator referenceGenerator = dimensions.get(key);
|
||||
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();
|
||||
|
||||
if (enforcer.needsChunkGeneratorRepair(loadedChunkGenerator)) {
|
||||
if (enforcer.togetherShouldRepair(loadedChunkGenerator)) {
|
||||
settings = enforcer.enforceGeneratorInWorldGenSettings(
|
||||
registryAccess,
|
||||
key,
|
||||
|
@ -168,11 +187,13 @@ public class WorldGenUtil {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (!didRepair) {
|
||||
if (loadedStem.generator().getBiomeSource() instanceof ReloadableBiomeSource reload) {
|
||||
reload.reloadBiomes();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ public class CreateWorldScreenMixin {
|
|||
private static WorldLoader.WorldDataSupplier<WorldGenSettings> wt_NewDefaultSettings(WorldLoader.WorldDataSupplier<WorldGenSettings> worldDataSupplier) {
|
||||
return (resourceManager, dataPackConfig) -> {
|
||||
Pair<WorldGenSettings, RegistryAccess.Frozen> res = worldDataSupplier.get(resourceManager, dataPackConfig);
|
||||
WorldBootstrap.InGUI.setDefaultCreateWorldSettings(res.getFirst());
|
||||
return WorldGenUtil.defaultWorldDataSupplier(res.getSecond());
|
||||
};
|
||||
}
|
||||
|
|
|
@ -33,6 +33,12 @@ import org.jetbrains.annotations.ApiStatus;
|
|||
|
||||
@ApiStatus.Internal
|
||||
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;
|
||||
|
||||
public static RegistryAccess getLastRegistryAccess() {
|
||||
|
@ -144,6 +150,12 @@ public class WorldBootstrap {
|
|||
}
|
||||
|
||||
public static class InGUI {
|
||||
|
||||
|
||||
public static void setDefaultCreateWorldSettings(WorldGenSettings worldGenSettings) {
|
||||
DEFAULT_CREATE_WORLD_PRESET_SETTINGS = worldGenSettings;
|
||||
}
|
||||
|
||||
public static void registryReadyOnNewWorld(WorldGenSettingsComponent worldGenSettingsComponent) {
|
||||
Helpers.onRegistryReady(worldGenSettingsComponent.registryHolder());
|
||||
}
|
||||
|
@ -228,6 +240,8 @@ public class WorldBootstrap {
|
|||
String levelID,
|
||||
LevelStorageSource levelSource
|
||||
) {
|
||||
//when we load a world, we do not want to reuse the default world settings
|
||||
DEFAULT_CREATE_WORLD_PRESET_SETTINGS = null;
|
||||
try {
|
||||
var levelStorageAccess = levelSource.createAccess(levelID);
|
||||
try {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue