diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/InternalBiomeAPI.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/InternalBiomeAPI.java index 5f35c4aa..cfa08852 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/InternalBiomeAPI.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/InternalBiomeAPI.java @@ -362,10 +362,10 @@ 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); - BIOMES_TO_SORT.add(id); - BIOME_ADDITIONS.computeIfAbsent(oBiomeRegistry.get(), reg -> new AtomicInteger(0)) - .incrementAndGet(); + //BCLib.LOGGER.info(" #### " + rawId + ", " + biome + ", " + id); + //BIOMES_TO_SORT.add(id); +// BIOME_ADDITIONS.computeIfAbsent(oBiomeRegistry.get(), reg -> new AtomicInteger(0)) +// .incrementAndGet(); } }); }); diff --git a/src/main/java/org/betterx/worlds/together/levelgen/WorldGenUtil.java b/src/main/java/org/betterx/worlds/together/levelgen/WorldGenUtil.java index 0d86d867..55f2dade 100644 --- a/src/main/java/org/betterx/worlds/together/levelgen/WorldGenUtil.java +++ b/src/main/java/org/betterx/worlds/together/levelgen/WorldGenUtil.java @@ -4,6 +4,7 @@ import org.betterx.worlds.together.WorldsTogether; import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig; import org.betterx.worlds.together.biomesource.ReloadableBiomeSource; import org.betterx.worlds.together.chunkgenerator.EnforceableChunkGenerator; +import org.betterx.worlds.together.mixin.common.WorldPresetAccessor; import org.betterx.worlds.together.world.BiomeSourceWithNoiseRelatedSettings; import org.betterx.worlds.together.world.BiomeSourceWithSeed; import org.betterx.worlds.together.world.WorldConfig; @@ -12,12 +13,16 @@ import org.betterx.worlds.together.worldPreset.TogetherWorldPreset; import org.betterx.worlds.together.worldPreset.WorldPresets; import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.JsonOps; +import net.minecraft.Util; 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.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.util.RandomSource; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.chunk.ChunkGenerator; @@ -30,6 +35,11 @@ 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.google.common.collect.ImmutableMap; +import com.google.gson.JsonElement; + +import java.util.HashMap; +import java.util.Map; import org.jetbrains.annotations.ApiStatus; public class WorldGenUtil { @@ -78,11 +88,95 @@ public class WorldGenUtil { ); } - public static Pair defaultWorldDataSupplier(RegistryAccess.Frozen frozen) { - WorldGenSettings worldGenSettings = createDefaultWorldFromPreset(frozen); + @ApiStatus.Internal + public static Pair defaultWorldDataSupplier( + RegistryOps loaderOps, + RegistryAccess.Frozen frozen + ) { + WorldGenSettings defaultGen = createDefaultWorldFromPreset(frozen); + RegistryOps registryOps = RegistryOps.create(JsonOps.INSTANCE, frozen); + WorldGenSettings worldGenSettings = WorldGenSettings.CODEC + .encodeStart(registryOps, defaultGen) + .flatMap(json -> WorldGenSettings.CODEC.parse( + loaderOps, + json + )) + .getOrThrow( + false, + Util.prefix( + "Error parsing worldgen settings after loading data packs: ", + WorldsTogether.LOGGER::error + ) + ); +// WorldGenSettings worldGenSettings = createDefaultWorldFromPreset(frozen); return Pair.of(worldGenSettings, frozen); } + private static final Map, Map, LevelStem>> WORLD_PRESET_MAP = new HashMap<>(); + + @ApiStatus.Internal + public static Map, LevelStem> getDimensionsWithModData(ResourceKey preset) { + var data = WORLD_PRESET_MAP.get(preset); + if (data == null) return new HashMap<>(); + return data; + } + + @ApiStatus.Internal + public static Holder reloadWithModData(Holder preset) { + if (preset.value() instanceof WorldPresetAccessor acc) { + var data = WORLD_PRESET_MAP.get(preset.unwrapKey().orElseThrow()); + if (data != null) { + acc.bcl_setDimensions(data); + } + } + return preset; + } + + public static void clearPreloadedWorldPresets() { + WORLD_PRESET_MAP.clear(); + } + + public static void preloadWorldPresets(ResourceManager resourceManager, RegistryAccess.Writable writable) { + clearPreloadedWorldPresets(); + Registry registry = writable.registryOrThrow(Registry.WORLD_PRESET_REGISTRY); + //for (ResourceKey key : registry.registryKeySet()) + ResourceKey key = net.minecraft.world.level.levelgen.presets.WorldPresets.NORMAL; + { + RegistryOps loaderOps = RegistryOps.createAndLoad( + JsonOps.INSTANCE, writable, resourceManager + ); + Holder in = registry.getHolderOrThrow(key); + if (in.unwrapKey().isPresent()) { + RegistryOps registryOps = RegistryOps.create(JsonOps.INSTANCE, writable); + WorldGenSettings settings = WorldGenUtil.createWorldFromPreset( + in.unwrapKey().orElseThrow(), + writable, + RandomSource.create().nextLong(), + true, + false + ); + WorldGenSettings worldGenSettings = WorldGenSettings.CODEC + .encodeStart(registryOps, settings) + .flatMap(json -> WorldGenSettings.CODEC.parse( + loaderOps, + json + )) + .getOrThrow( + false, + Util.prefix( + "Error parsing world preset settings after loading data packs: ", + WorldsTogether.LOGGER::error + ) + ); + ImmutableMap.Builder, LevelStem> map = ImmutableMap.builder(); + for (Map.Entry, LevelStem> entry : worldGenSettings.dimensions().entrySet()) { + map.put(entry.getKey(), entry.getValue()); + } + WORLD_PRESET_MAP.put(key, map.build()); + } + } + } + public static WorldGenSettings createDefaultWorldFromPreset(RegistryAccess registryAccess, long seed) { return createDefaultWorldFromPreset(registryAccess, seed, true, false); } @@ -153,11 +247,10 @@ public class WorldGenUtil { 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); + var vanillaDimensionMap = WorldGenUtil.getDimensionsWithModData(net.minecraft.world.level.levelgen.presets.WorldPresets.NORMAL); + LevelStem vanillaDefaultStem = vanillaDimensionMap.get(key); + if (vanillaDefaultStem != null) { loadedStem = vanillaDefaultStem; } diff --git a/src/main/java/org/betterx/worlds/together/mixin/client/CreateWorldScreenMixin.java b/src/main/java/org/betterx/worlds/together/mixin/client/CreateWorldScreenMixin.java index 72bb69a6..e7b6d495 100644 --- a/src/main/java/org/betterx/worlds/together/mixin/client/CreateWorldScreenMixin.java +++ b/src/main/java/org/betterx/worlds/together/mixin/client/CreateWorldScreenMixin.java @@ -4,11 +4,12 @@ import org.betterx.worlds.together.levelgen.WorldGenUtil; import org.betterx.worlds.together.world.event.WorldBootstrap; import org.betterx.worlds.together.worldPreset.WorldPresets; -import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.JsonOps; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.worldselection.CreateWorldScreen; import net.minecraft.client.gui.screens.worldselection.WorldGenSettingsComponent; import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceKey; import net.minecraft.server.WorldLoader; import net.minecraft.world.level.DataPackConfig; @@ -16,6 +17,7 @@ import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.presets.WorldPreset; import net.minecraft.world.level.storage.LevelStorageSource; +import com.google.gson.JsonElement; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -33,6 +35,7 @@ public class CreateWorldScreenMixin { @Final public WorldGenSettingsComponent worldGenSettingsComponent; + @Inject(method = "", at = @At("TAIL")) private void wt_init( Screen screen, @@ -48,14 +51,36 @@ public class CreateWorldScreenMixin { private static Optional> wt_NewDefault(Optional> preset) { return Optional.of(WorldPresets.getDEFAULT()); } +// +// @Redirect(method = "method_41854", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/RegistryAccess$Writable;freeze()Lnet/minecraft/core/RegistryAccess$Frozen;")) +// private static RegistryAccess.Frozen loadDynamicRegistry( +// RegistryAccess.Writable mutableRegistryManager, +// ResourceManager dataPackManager +// ) { +// // This loads the dynamic registry from the data pack +// RegistryOps.createAndLoad(JsonOps.INSTANCE, mutableRegistryManager, dataPackManager); +// return mutableRegistryManager.freeze(); +// } //Make sure the WorldGenSettings used to populate the create screen match the default WorldPreset @ModifyArg(method = "openFresh", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader;load(Lnet/minecraft/server/WorldLoader$InitConfig;Lnet/minecraft/server/WorldLoader$WorldDataSupplier;Lnet/minecraft/server/WorldLoader$ResultFactory;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) private static WorldLoader.WorldDataSupplier wt_NewDefaultSettings(WorldLoader.WorldDataSupplier worldDataSupplier) { return (resourceManager, dataPackConfig) -> { - Pair res = worldDataSupplier.get(resourceManager, dataPackConfig); - WorldBootstrap.InGUI.setDefaultCreateWorldSettings(res.getFirst()); - return WorldGenUtil.defaultWorldDataSupplier(res.getSecond()); +// Pair res = worldDataSupplier.get(resourceManager, dataPackConfig); +// WorldGenSettings defaultGen = net.minecraft.world.level.levelgen.presets.WorldPresets.createNormalWorldFromPreset(frozen); +// WorldBootstrap.InGUI.setDefaultCreateWorldSettings(defaultGen); + RegistryAccess.Writable writable = RegistryAccess.builtinCopy(); + + + WorldGenUtil.preloadWorldPresets(resourceManager, writable); + RegistryOps registryOps = RegistryOps.createAndLoad( + JsonOps.INSTANCE, writable, resourceManager + ); + RegistryAccess.Frozen frozen = writable.freeze(); + WorldBootstrap.InGUI.registryReady(frozen); + + + return WorldGenUtil.defaultWorldDataSupplier(registryOps, frozen); }; } diff --git a/src/main/java/org/betterx/worlds/together/mixin/client/WorldGenSettingsComponentMixin.java b/src/main/java/org/betterx/worlds/together/mixin/client/WorldGenSettingsComponentMixin.java index 69e7e821..b1a1f54e 100644 --- a/src/main/java/org/betterx/worlds/together/mixin/client/WorldGenSettingsComponentMixin.java +++ b/src/main/java/org/betterx/worlds/together/mixin/client/WorldGenSettingsComponentMixin.java @@ -1,19 +1,13 @@ package org.betterx.worlds.together.mixin.client; -import org.betterx.worlds.together.mixin.common.WorldPresetAccessor; -import org.betterx.worlds.together.world.event.WorldBootstrap; +import org.betterx.worlds.together.levelgen.WorldGenUtil; import org.betterx.worlds.together.worldPreset.WorldGenSettingsComponentAccessor; import net.minecraft.client.gui.screens.worldselection.WorldCreationContext; import net.minecraft.client.gui.screens.worldselection.WorldGenSettingsComponent; import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.levelgen.presets.WorldPreset; -import net.minecraft.world.level.levelgen.presets.WorldPresets; -import com.google.common.collect.ImmutableMap; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.gen.Accessor; @@ -22,7 +16,6 @@ import org.spongepowered.asm.mixin.injection.ModifyArg; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -47,38 +40,17 @@ public abstract class WorldGenSettingsComponentMixin implements WorldGenSettings .location() .getNamespace() .equals("minecraft")); + + List> custom = list .stream() .filter(p -> !vanilla.test(p)) .collect(Collectors.toCollection(LinkedList::new)); - Registry registry = settings.registryAccess().registryOrThrow(Registry.WORLD_PRESET_REGISTRY); - custom.addAll(list .stream() .filter(vanilla) - // this code will inject the original vanilla default dimensions into the WorldPreset list that is - // used on the world type selection button. This is supposed to mitigate the issue described - // here: https://github.com/quiqueck/BCLib/issues/20 - // it may be removed once this behaviour is fixed in either fabric or vanilla - .map(p -> { - if (WorldBootstrap.getDefaultCreateWorldPresetSettings() != null) { - ResourceKey key = p.unwrapKey().orElseThrow(); - if (key.location().equals(WorldPresets.NORMAL.location())) { - ImmutableMap.Builder, LevelStem> map = ImmutableMap.builder(); - for (Map.Entry, LevelStem> entry : WorldBootstrap.getDefaultCreateWorldPresetSettings() - .dimensions() - .entrySet()) { - map.put(entry.getKey(), entry.getValue()); - } - - if (p.value() instanceof WorldPresetAccessor ax) { - ax.bcl_setDimensions(map.build()); - } - } - } - return p; - }) + .map(WorldGenUtil::reloadWithModData) .toList()); return custom; diff --git a/src/main/java/org/betterx/worlds/together/world/event/WorldBootstrap.java b/src/main/java/org/betterx/worlds/together/world/event/WorldBootstrap.java index 2ce79614..44aa4cd4 100644 --- a/src/main/java/org/betterx/worlds/together/world/event/WorldBootstrap.java +++ b/src/main/java/org/betterx/worlds/together/world/event/WorldBootstrap.java @@ -33,12 +33,6 @@ 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() { @@ -150,12 +144,6 @@ 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()); } @@ -240,8 +228,7 @@ 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; + WorldGenUtil.clearPreloadedWorldPresets(); try { var levelStorageAccess = levelSource.createAccess(levelID); try { @@ -285,6 +272,7 @@ public class WorldBootstrap { ) { //LifeCycleAPI._runBeforeLevelLoad(); WorldEventsImpl.ON_WORLD_LOAD.emit(OnWorldLoad::onLoad); + WorldGenUtil.clearPreloadedWorldPresets(); } }