Make sure BiomeAPI is initialized with the correct registry

This commit is contained in:
Frank 2022-05-27 18:12:43 +02:00
parent 5d970a27ba
commit 3e41a4630d
8 changed files with 117 additions and 112 deletions

View file

@ -1,6 +1,10 @@
package org.betterx.bclib.api; package org.betterx.bclib.api;
import net.minecraft.client.gui.screens.worldselection.WorldGenSettingsComponent;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@ -15,9 +19,12 @@ import net.minecraft.world.level.storage.ServerLevelData;
import org.betterx.bclib.api.biomes.BiomeAPI; import org.betterx.bclib.api.biomes.BiomeAPI;
import org.betterx.bclib.api.dataexchange.DataExchangeAPI; import org.betterx.bclib.api.dataexchange.DataExchangeAPI;
import org.betterx.bclib.api.datafixer.DataFixerAPI; import org.betterx.bclib.api.datafixer.DataFixerAPI;
import org.betterx.bclib.api.worldgen.WorldGenUtil;
import org.betterx.bclib.mixin.common.RegistryOpsAccessor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
/** /**
@ -28,7 +35,7 @@ public class LifeCycleAPI {
private final static List<LevelLoadCall> onLoadLevel = new ArrayList<>(2); private final static List<LevelLoadCall> onLoadLevel = new ArrayList<>(2);
private final static List<BeforeLevelLoadCall> beforeLoadLevel = new ArrayList<>(2); private final static List<BeforeLevelLoadCall> beforeLoadLevel = new ArrayList<>(2);
public static void startingWorld(LevelStorageSource.LevelStorageAccess levelStorageAccess, public static void newWorldSetup(LevelStorageSource.LevelStorageAccess levelStorageAccess,
WorldGenSettings settings) { WorldGenSettings settings) {
DataExchangeAPI.prepareServerside(); DataExchangeAPI.prepareServerside();
BiomeAPI.prepareNewLevel(); BiomeAPI.prepareNewLevel();
@ -37,7 +44,7 @@ public class LifeCycleAPI {
_runBeforeLevelLoad(); _runBeforeLevelLoad();
} }
public static void startingWorld(String levelID, public static void newWorldSetup(String levelID,
WorldGenSettings worldGenSettings, WorldGenSettings worldGenSettings,
LevelStorageSource levelSource) { LevelStorageSource levelSource) {
DataExchangeAPI.prepareServerside(); DataExchangeAPI.prepareServerside();
@ -47,6 +54,48 @@ public class LifeCycleAPI {
_runBeforeLevelLoad(); _runBeforeLevelLoad();
} }
public static void newWorldSetup(LevelStorageSource.LevelStorageAccess levelStorageAccess) {
BiomeAPI.prepareNewLevel();
DataFixerAPI.fixData(levelStorageAccess, false, (didFix) -> {/* not called when showUI==false */});
_runBeforeLevelLoad();
}
public static WorldGenSettings worldLoadStarted(WorldGenSettings settings,
Optional<RegistryOps<Tag>> registryOps) {
if (registryOps.orElse(null) instanceof RegistryOpsAccessor acc) {
BiomeAPI.initRegistry(acc.bcl_getRegistryAccess()
.registry(Registry.BIOME_REGISTRY)
.orElse(null));
}
settings = WorldGenUtil.fixSettingsInCurrentWorld(registryOps, settings);
return settings;
}
private static void worldCreationStarted(RegistryAccess access) {
BiomeAPI.initRegistry(access
.registry(Registry.BIOME_REGISTRY)
.orElse(null));
}
public static void worldCreationStarted(RegistryOps<Tag> regOps) {
if (regOps instanceof RegistryOpsAccessor acc) {
worldCreationStarted(acc.bcl_getRegistryAccess());
}
}
public static void worldCreationStarted(Optional<LevelStorageSource.LevelStorageAccess> levelStorageAccess,
WorldGenSettingsComponent worldGenSettingsComponent) {
worldCreationStarted(worldGenSettingsComponent.registryHolder());
if (levelStorageAccess.isPresent()) {
newWorldSetup(levelStorageAccess.get(),
worldGenSettingsComponent.settings().worldGenSettings());
}
}
/** /**
* A callback function that is used for each new ServerLevel instance * A callback function that is used for each new ServerLevel instance
*/ */
@ -143,18 +192,18 @@ public class LifeCycleAPI {
List<CustomSpawner> list, List<CustomSpawner> list,
boolean bl2) { boolean bl2) {
onLoadLevel.forEach(c -> c.onLoad( onLoadLevel.forEach(c -> c.onLoad(
world, world,
minecraftServer, minecraftServer,
executor, executor,
levelStorageAccess, levelStorageAccess,
serverLevelData, serverLevelData,
resourceKey, resourceKey,
chunkProgressListener, chunkProgressListener,
bl, bl,
l, l,
list, list,
bl2) bl2)
); );
final long seed = world.getSeed(); final long seed = world.getSeed();
final Registry<Biome> biomeRegistry = world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY); final Registry<Biome> biomeRegistry = world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);

View file

@ -169,8 +169,7 @@ public class BiomeAPI {
*/ */
public static void initRegistry(Registry<Biome> biomeRegistry) { public static void initRegistry(Registry<Biome> biomeRegistry) {
if (biomeRegistry != BiomeAPI.biomeRegistry) { if (biomeRegistry != BiomeAPI.biomeRegistry) {
System.out.println("Switching Registry to " + biomeRegistry);//17015, 19009, 19058, 19009 BiomeAPI.biomeRegistry = biomeRegistry; //12819
BiomeAPI.biomeRegistry = biomeRegistry;
CLIENT.clear(); CLIENT.clear();
} }
} }

View file

@ -37,7 +37,6 @@ import org.betterx.bclib.world.generator.BCLibNetherBiomeSource;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class WorldGenUtil { public class WorldGenUtil {
@ -85,6 +84,8 @@ public class WorldGenUtil {
* *
* @param settings * @param settings
* @return * @return
* @see BCLChunkGenerator#injectNoiseSettings(WorldGenSettings) for the correcponding behaviour
* for new worlds
*/ */
public static WorldGenSettings fixSettingsInCurrentWorld(Optional<RegistryOps<Tag>> registryOps, public static WorldGenSettings fixSettingsInCurrentWorld(Optional<RegistryOps<Tag>> registryOps,
WorldGenSettings settings) { WorldGenSettings settings) {
@ -121,10 +122,10 @@ public class WorldGenUtil {
boolean generateStructures, boolean generateStructures,
boolean generateBonusChest) { boolean generateBonusChest) {
return createWorldFromPreset(BCLWorldPresets.DEFAULT.orElseThrow(), return createWorldFromPreset(BCLWorldPresets.DEFAULT.orElseThrow(),
registryAccess, registryAccess,
seed, seed,
generateStructures, generateStructures,
generateBonusChest); generateBonusChest);
} }
public static Pair<WorldGenSettings, RegistryAccess.Frozen> defaultWorldDataSupplier(RegistryAccess.Frozen frozen) { public static Pair<WorldGenSettings, RegistryAccess.Frozen> defaultWorldDataSupplier(RegistryAccess.Frozen frozen) {
@ -146,7 +147,7 @@ public class WorldGenUtil {
int biomeSourceVersion, int biomeSourceVersion,
RegistryAccess registryAccess, RegistryAccess registryAccess,
WorldGenSettings worldGenSettings WorldGenSettings worldGenSettings
) { ) {
Optional<Holder<LevelStem>> oLevelStem = referenceStemForVersion( Optional<Holder<LevelStem>> oLevelStem = referenceStemForVersion(
dimensionKey, dimensionKey,
biomeSourceVersion, biomeSourceVersion,
@ -154,12 +155,12 @@ public class WorldGenUtil {
worldGenSettings.seed(), worldGenSettings.seed(),
worldGenSettings.generateStructures(), worldGenSettings.generateStructures(),
worldGenSettings.generateStructures() worldGenSettings.generateStructures()
); );
return replaceGenerator(dimensionKey, return replaceGenerator(dimensionKey,
dimensionTypeKey, dimensionTypeKey,
registryAccess, registryAccess,
worldGenSettings, worldGenSettings,
oLevelStem.map(l -> l.value().generator()).orElseThrow()); oLevelStem.map(l -> l.value().generator()).orElseThrow());
} }
public static WorldGenSettings replaceGenerator( public static WorldGenSettings replaceGenerator(
@ -168,31 +169,31 @@ public class WorldGenUtil {
RegistryAccess registryAccess, RegistryAccess registryAccess,
WorldGenSettings worldGenSettings, WorldGenSettings worldGenSettings,
ChunkGenerator generator ChunkGenerator generator
) { ) {
Registry<DimensionType> dimensionTypeRegistry = registryAccess.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY); Registry<DimensionType> dimensionTypeRegistry = registryAccess.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY);
Registry<LevelStem> newDimensions = withDimension(dimensionKey, Registry<LevelStem> newDimensions = withDimension(dimensionKey,
dimensionTypeKey, dimensionTypeKey,
dimensionTypeRegistry, dimensionTypeRegistry,
worldGenSettings.dimensions(), worldGenSettings.dimensions(),
generator); generator);
return new WorldGenSettings(worldGenSettings.seed(), return new WorldGenSettings(worldGenSettings.seed(),
worldGenSettings.generateStructures(), worldGenSettings.generateStructures(),
worldGenSettings.generateBonusChest(), worldGenSettings.generateBonusChest(),
newDimensions); newDimensions);
} }
public static WorldGenSettings replaceStem( public static WorldGenSettings replaceStem(
ResourceKey<LevelStem> dimensionKey, ResourceKey<LevelStem> dimensionKey,
WorldGenSettings worldGenSettings, WorldGenSettings worldGenSettings,
LevelStem levelStem LevelStem levelStem
) { ) {
Registry<LevelStem> newDimensions = withDimension(dimensionKey, Registry<LevelStem> newDimensions = withDimension(dimensionKey,
worldGenSettings.dimensions(), worldGenSettings.dimensions(),
levelStem); levelStem);
return new WorldGenSettings(worldGenSettings.seed(), return new WorldGenSettings(worldGenSettings.seed(),
worldGenSettings.generateStructures(), worldGenSettings.generateStructures(),
worldGenSettings.generateBonusChest(), worldGenSettings.generateBonusChest(),
newDimensions); newDimensions);
} }
public static Registry<LevelStem> withDimension(ResourceKey<LevelStem> dimensionKey, public static Registry<LevelStem> withDimension(ResourceKey<LevelStem> dimensionKey,
@ -212,17 +213,17 @@ public class WorldGenUtil {
Registry<LevelStem> inputDimensions, Registry<LevelStem> inputDimensions,
LevelStem levelStem) { LevelStem levelStem) {
MappedRegistry<LevelStem> writableRegistry = new MappedRegistry<>(Registry.LEVEL_STEM_REGISTRY, MappedRegistry<LevelStem> writableRegistry = new MappedRegistry<>(Registry.LEVEL_STEM_REGISTRY,
Lifecycle.experimental(), Lifecycle.experimental(),
null); null);
writableRegistry.register(dimensionKey, writableRegistry.register(dimensionKey,
levelStem, levelStem,
Lifecycle.stable()); Lifecycle.stable());
for (Map.Entry<ResourceKey<LevelStem>, LevelStem> entry : inputDimensions.entrySet()) { for (Map.Entry<ResourceKey<LevelStem>, LevelStem> entry : inputDimensions.entrySet()) {
ResourceKey<LevelStem> resourceKey = entry.getKey(); ResourceKey<LevelStem> resourceKey = entry.getKey();
if (resourceKey == dimensionKey) continue; if (resourceKey == dimensionKey) continue;
writableRegistry.register(resourceKey, writableRegistry.register(resourceKey,
entry.getValue(), entry.getValue(),
inputDimensions.lifecycle(entry.getValue())); inputDimensions.lifecycle(entry.getValue()));
} }
return writableRegistry; return writableRegistry;
} }
@ -239,7 +240,7 @@ public class WorldGenUtil {
long seed, long seed,
boolean generateStructures, boolean generateStructures,
boolean generateBonusChest boolean generateBonusChest
) { ) {
final WorldGenSettings referenceSettings; final WorldGenSettings referenceSettings;
if (biomeSourceVersion == BCLBiomeSource.BIOME_SOURCE_VERSION_VANILLA) { if (biomeSourceVersion == BCLBiomeSource.BIOME_SOURCE_VERSION_VANILLA) {
referenceSettings = net.minecraft.world.level.levelgen.presets.WorldPresets.createNormalWorldFromPreset( referenceSettings = net.minecraft.world.level.levelgen.presets.WorldPresets.createNormalWorldFromPreset(
@ -383,5 +384,5 @@ public class WorldGenUtil {
this.biomes = biomes; this.biomes = biomes;
} }
} }
} }

View file

@ -57,13 +57,9 @@ public class CreateWorldScreenMixin {
}; };
} }
//this is called when a new world is first created
@Inject(method = "createNewWorldDirectory", at = @At("RETURN")) @Inject(method = "createNewWorldDirectory", at = @At("RETURN"))
void bcl_createNewWorld(CallbackInfoReturnable<Optional<LevelStorageSource.LevelStorageAccess>> cir) { void bcl_createNewWorld(CallbackInfoReturnable<Optional<LevelStorageSource.LevelStorageAccess>> cir) {
Optional<LevelStorageSource.LevelStorageAccess> levelStorageAccess = cir.getReturnValue(); LifeCycleAPI.worldCreationStarted(cir.getReturnValue(), this.worldGenSettingsComponent);
if (levelStorageAccess.isPresent()) {
LifeCycleAPI.startingWorld(levelStorageAccess.get(),
worldGenSettingsComponent.settings().worldGenSettings());
}
} }
} }

View file

@ -1,72 +1,32 @@
package org.betterx.bclib.mixin.common; package org.betterx.bclib.mixin.common;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.RegistryOps;
import net.minecraft.server.Main; import net.minecraft.server.Main;
import net.minecraft.server.dedicated.DedicatedServerSettings;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import joptsimple.ArgumentAcceptingOptionSpec; import com.mojang.serialization.DynamicOps;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import org.betterx.bclib.api.LifeCycleAPI; import org.betterx.bclib.api.LifeCycleAPI;
import org.betterx.bclib.api.biomes.BiomeAPI;
import org.betterx.bclib.api.datafixer.DataFixerAPI;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
@Mixin(Main.class) @Mixin(Main.class)
abstract public class MainMixin { abstract public class MainMixin {
@ModifyVariable(method = "main", ordinal = 0, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;getSummary()Lnet/minecraft/world/level/storage/LevelSummary;")) @ModifyVariable(method = "main", ordinal = 0, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;getSummary()Lnet/minecraft/world/level/storage/LevelSummary;"))
private static LevelStorageSource.LevelStorageAccess bc_createAccess(LevelStorageSource.LevelStorageAccess levelStorageAccess) { private static LevelStorageSource.LevelStorageAccess bc_createAccess(LevelStorageSource.LevelStorageAccess levelStorageAccess) {
BiomeAPI.prepareNewLevel(); LifeCycleAPI.newWorldSetup(levelStorageAccess);
DataFixerAPI.fixData(levelStorageAccess, false, (didFix) -> {/* not called when showUI==false */});
LifeCycleAPI._runBeforeLevelLoad();
return levelStorageAccess; return levelStorageAccess;
} }
//@Inject(method = "main", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/LevelStorageSource;createDefault(Ljava/nio/file/Path;)Lnet/minecraft/world/level/storage/LevelStorageSource;")) @ModifyArg(method = "method_43613", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;getDataTag(Lcom/mojang/serialization/DynamicOps;Lnet/minecraft/world/level/DataPackConfig;Lcom/mojang/serialization/Lifecycle;)Lnet/minecraft/world/level/storage/WorldData;"))
private static void bclib_callServerFix(String[] args, CallbackInfo ci) { private static DynamicOps<Tag> bcl_onCreate(DynamicOps<Tag> dynamicOps) {
OptionParser parser = new OptionParser(); if (dynamicOps instanceof RegistryOps<Tag> regOps) {
ArgumentAcceptingOptionSpec<String> optionUniverse = parser.accepts("universe") LifeCycleAPI.worldCreationStarted(regOps);
.withRequiredArg() }
.defaultsTo(".", new String[0]); return dynamicOps;
ArgumentAcceptingOptionSpec<String> optionWorld = parser.accepts("world").withRequiredArg();
//this is only for compat reasons, we do not need to read thise options in our mixin, but it seems to cause
//errors if they are not defined
parser.accepts("nogui");
parser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits");
parser.accepts("demo");
parser.accepts("bonusChest");
parser.accepts("forceUpgrade");
parser.accepts("eraseCache");
parser.accepts("safeMode", "Loads level with vanilla datapack only");
parser.accepts("help").forHelp();
parser.accepts("singleplayer").withRequiredArg();
parser.accepts("port").withRequiredArg().ofType(Integer.class).defaultsTo(-1, new Integer[0]);
parser.accepts("serverId").withRequiredArg();
parser.accepts("jfrProfile");
parser.nonOptions();
OptionSet options = parser.parse(args);
Path settingPath = Paths.get("server.properties");
DedicatedServerSettings settings = new DedicatedServerSettings(settingPath);
File file = new File(options.valueOf(optionUniverse));
String levelID = Optional.ofNullable(options.valueOf(optionWorld)).orElse(settings.getProperties().levelName);
LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(file.toPath());
DataFixerAPI.fixData(levelStorageSource, levelID, false, (didFix) -> {/* not called when showUI==false */});
LifeCycleAPI._runBeforeLevelLoad();
} }
} }

View file

@ -11,8 +11,8 @@ import net.minecraft.world.level.storage.PrimaryLevelData;
import com.mojang.datafixers.DataFixer; import com.mojang.datafixers.DataFixer;
import com.mojang.serialization.Dynamic; import com.mojang.serialization.Dynamic;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import org.betterx.bclib.api.LifeCycleAPI;
import org.betterx.bclib.api.worldgen.BCLChunkGenerator; import org.betterx.bclib.api.worldgen.BCLChunkGenerator;
import org.betterx.bclib.api.worldgen.WorldGenUtil;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@ -59,9 +59,9 @@ public class PrimaryLevelDataMixin {
@ModifyArg(method = "parse", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/PrimaryLevelData;<init>(Lcom/mojang/datafixers/DataFixer;ILnet/minecraft/nbt/CompoundTag;ZIIIFJJIIIZIZZZLnet/minecraft/world/level/border/WorldBorder$Settings;IILjava/util/UUID;Ljava/util/Set;Lnet/minecraft/world/level/timers/TimerQueue;Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/world/level/LevelSettings;Lnet/minecraft/world/level/levelgen/WorldGenSettings;Lcom/mojang/serialization/Lifecycle;)V")) @ModifyArg(method = "parse", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/PrimaryLevelData;<init>(Lcom/mojang/datafixers/DataFixer;ILnet/minecraft/nbt/CompoundTag;ZIIIFJJIIIZIZZZLnet/minecraft/world/level/border/WorldBorder$Settings;IILjava/util/UUID;Ljava/util/Set;Lnet/minecraft/world/level/timers/TimerQueue;Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/world/level/LevelSettings;Lnet/minecraft/world/level/levelgen/WorldGenSettings;Lcom/mojang/serialization/Lifecycle;)V"))
private static WorldGenSettings bcl_fixSettings(WorldGenSettings settings) { private static WorldGenSettings bcl_fixSettings(WorldGenSettings settings) {
Optional<RegistryOps<Tag>> registryOps = bcl_lastRegistryAccess.get(); Optional<RegistryOps<Tag>> registryOps = bcl_lastRegistryAccess.get();
settings = WorldGenUtil.fixSettingsInCurrentWorld(registryOps, settings); settings = LifeCycleAPI.worldLoadStarted(settings, registryOps);
bcl_lastRegistryAccess.set(Optional.empty()); bcl_lastRegistryAccess.set(Optional.empty());
return settings; return settings;
} }
} }

View file

@ -58,7 +58,7 @@ public abstract class WorldOpenFlowsMixin {
RegistryAccess registryAccess, RegistryAccess registryAccess,
WorldGenSettings worldGenSettings, WorldGenSettings worldGenSettings,
CallbackInfo ci) { CallbackInfo ci) {
LifeCycleAPI.startingWorld(levelID, worldGenSettings, this.levelSource); LifeCycleAPI.newWorldSetup(levelID, worldGenSettings, this.levelSource);
} }
@Inject(method = "createLevelFromExistingSettings", at = @At("HEAD")) @Inject(method = "createLevelFromExistingSettings", at = @At("HEAD"))

View file

@ -42,7 +42,7 @@ public abstract class BCLBiomeSource extends BiomeSource {
System.out.println(this + " with Registry: " + biomeRegistry.getClass().getName() + "@" + Integer.toHexString( System.out.println(this + " with Registry: " + biomeRegistry.getClass().getName() + "@" + Integer.toHexString(
biomeRegistry.hashCode())); biomeRegistry.hashCode()));
BiomeAPI.initRegistry(biomeRegistry); //BiomeAPI.initRegistry(biomeRegistry);
} }
final public void setSeed(long seed) { final public void setSeed(long seed) {