mirror of
https://github.com/FabricMC/fabric.git
synced 2025-04-21 03:10:54 -04:00
Fix custom dimension not getting loaded on first world load (#2345)
* re-enable custom dimension test * port ServerBugfixMixin to 1.19 * fix custom dimension not loading on first load on client
This commit is contained in:
parent
07df213ec3
commit
a6d2f785a8
3 changed files with 81 additions and 9 deletions
fabric-dimensions-v1/src
main/java/net/fabricmc/fabric/mixin/dimension
testmod/java/net/fabricmc/fabric/test/dimension
fabric-resource-loader-v0/src/client/java/net/fabricmc/fabric/mixin/resource/loader/client
|
@ -16,9 +16,22 @@
|
|||
|
||||
package net.fabricmc.fabric.mixin.dimension;
|
||||
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.resource.DataPackSettings;
|
||||
import net.minecraft.server.Main;
|
||||
import net.minecraft.util.registry.DynamicRegistryManager;
|
||||
import net.minecraft.world.gen.GeneratorOptions;
|
||||
import net.minecraft.world.level.LevelInfo;
|
||||
import net.minecraft.world.level.LevelProperties;
|
||||
import net.minecraft.world.level.storage.LevelStorage;
|
||||
|
||||
/**
|
||||
* This Mixin aims to solve a Minecraft Vanilla bug where datapacks are ignored during creation of the
|
||||
|
@ -33,11 +46,48 @@ import net.minecraft.server.Main;
|
|||
*
|
||||
* <p>See https://bugs.mojang.com/browse/MC-195468 for a related bug report.
|
||||
*
|
||||
* <p>In 1.18: Retest if this bug still occurs without this Mixin by launching a dedicated server with the
|
||||
* <p>TODO: Retest if this bug still occurs without this Mixin by launching a dedicated server with the
|
||||
* dimension testmod, and no world directory. If the dimension is available (i.e. in /execute in, or via
|
||||
* the testmod's commands), then the bug is fixed and this Mixin can be removed.
|
||||
*/
|
||||
@Mixin(value = Main.class)
|
||||
public class ServerBugfixMixin {
|
||||
// TODO fix me 22w06a
|
||||
@Unique
|
||||
private static LevelStorage.Session session;
|
||||
|
||||
@Unique
|
||||
private static DynamicRegistryManager.Mutable drm;
|
||||
|
||||
@Unique
|
||||
private static DynamicOps<NbtElement> ops;
|
||||
|
||||
@ModifyVariable(method = "main", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/level/storage/LevelStorage;createSession(Ljava/lang/String;)Lnet/minecraft/world/level/storage/LevelStorage$Session;"))
|
||||
private static LevelStorage.Session captureSession(LevelStorage.Session value) {
|
||||
session = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
@ModifyVariable(method = "method_43613", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/util/registry/DynamicRegistryManager;createAndLoad()Lnet/minecraft/util/registry/DynamicRegistryManager$Mutable;"))
|
||||
private static DynamicRegistryManager.Mutable captureDrm(DynamicRegistryManager.Mutable value) {
|
||||
drm = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
// The value is stored as DynamicOps instead of RegistryOps in the bytecode
|
||||
@ModifyVariable(method = "method_43613", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/util/dynamic/RegistryOps;ofLoaded(Lcom/mojang/serialization/DynamicOps;Lnet/minecraft/util/registry/DynamicRegistryManager$Mutable;Lnet/minecraft/resource/ResourceManager;)Lnet/minecraft/util/dynamic/RegistryOps;"))
|
||||
private static DynamicOps<NbtElement> captureOps(DynamicOps<NbtElement> value) {
|
||||
ops = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
@Redirect(method = "method_43613", at = @At(value = "NEW", target = "net/minecraft/world/level/LevelProperties"))
|
||||
private static LevelProperties onCreateNewLevelProperties(LevelInfo levelInfo, GeneratorOptions generatorOptions, Lifecycle lifecycle) {
|
||||
DataPackSettings dataPackSettings = levelInfo.getDataPackSettings();
|
||||
|
||||
// Save the level.dat file
|
||||
session.backupLevelDataFile(drm, new LevelProperties(levelInfo, generatorOptions, lifecycle));
|
||||
|
||||
// And reload it again, and replace the actual level properties with it
|
||||
return (LevelProperties) session.readLevelProperties(ops, dataPackSettings, drm.getRegistryLifecycle());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,11 +65,6 @@ public class FabricDimensionTest implements ModInitializer {
|
|||
}
|
||||
|
||||
ServerLifecycleEvents.SERVER_STARTED.register(server -> {
|
||||
if (true) {
|
||||
// TODO 22w06a ServerBugfixMixin
|
||||
return;
|
||||
}
|
||||
|
||||
ServerWorld overworld = server.getWorld(World.OVERWORLD);
|
||||
ServerWorld world = server.getWorld(WORLD_KEY);
|
||||
|
||||
|
|
|
@ -18,8 +18,11 @@ package net.fabricmc.fabric.mixin.resource.loader.client;
|
|||
|
||||
import java.io.File;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
@ -35,21 +38,31 @@ import net.minecraft.resource.DataPackSettings;
|
|||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.resource.ResourcePackManager;
|
||||
import net.minecraft.resource.ResourceType;
|
||||
import net.minecraft.util.Util;
|
||||
import net.minecraft.util.dynamic.RegistryOps;
|
||||
import net.minecraft.util.registry.DynamicRegistryManager;
|
||||
import net.minecraft.world.gen.GeneratorOptions;
|
||||
import net.minecraft.world.gen.WorldPresets;
|
||||
|
||||
import net.fabricmc.fabric.impl.resource.loader.ModResourcePackCreator;
|
||||
import net.fabricmc.fabric.impl.resource.loader.ModResourcePackUtil;
|
||||
import net.fabricmc.fabric.mixin.resource.loader.ResourcePackManagerAccessor;
|
||||
|
||||
@Mixin(CreateWorldScreen.class)
|
||||
public class CreateWorldScreenMixin {
|
||||
public abstract class CreateWorldScreenMixin {
|
||||
@Unique
|
||||
private static DataPackSettings defaultDataPackSettings;
|
||||
|
||||
@Shadow
|
||||
private ResourcePackManager packManager;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private static Logger LOGGER;
|
||||
|
||||
@Unique
|
||||
private static RegistryOps<JsonElement> loadedOps;
|
||||
|
||||
@ModifyVariable(method = "create(Lnet/minecraft/client/MinecraftClient;Lnet/minecraft/client/gui/screen/Screen;)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/world/CreateWorldScreen;createServerConfig(Lnet/minecraft/resource/ResourcePackManager;Lnet/minecraft/resource/DataPackSettings;)Lnet/minecraft/server/SaveLoading$ServerConfig;"))
|
||||
private static ResourcePackManager onCreateResManagerInit(ResourcePackManager manager) {
|
||||
|
@ -71,10 +84,24 @@ public class CreateWorldScreenMixin {
|
|||
@Redirect(method = "method_41854", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/registry/DynamicRegistryManager$Mutable;toImmutable()Lnet/minecraft/util/registry/DynamicRegistryManager$Immutable;"))
|
||||
private static DynamicRegistryManager.Immutable loadDynamicRegistry(DynamicRegistryManager.Mutable mutableRegistryManager, ResourceManager dataPackManager) {
|
||||
// This loads the dynamic registry from the data pack
|
||||
RegistryOps.ofLoaded(JsonOps.INSTANCE, mutableRegistryManager, dataPackManager);
|
||||
loadedOps = RegistryOps.ofLoaded(JsonOps.INSTANCE, mutableRegistryManager, dataPackManager);
|
||||
return mutableRegistryManager.toImmutable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix GeneratorOptions not having custom dimensions.
|
||||
* Taken from {@link CreateWorldScreen#applyDataPacks(ResourcePackManager)}.
|
||||
*/
|
||||
@SuppressWarnings("JavadocReference")
|
||||
@Redirect(method = "method_41854", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/gen/WorldPresets;createDefaultOptions(Lnet/minecraft/util/registry/DynamicRegistryManager;)Lnet/minecraft/world/gen/GeneratorOptions;"))
|
||||
private static GeneratorOptions loadDatapackDimensions(DynamicRegistryManager dynamicRegistryManager) {
|
||||
GeneratorOptions defaultGen = WorldPresets.createDefaultOptions(dynamicRegistryManager);
|
||||
RegistryOps<JsonElement> registryOps = RegistryOps.of(JsonOps.INSTANCE, dynamicRegistryManager);
|
||||
return GeneratorOptions.CODEC.encodeStart(registryOps, defaultGen)
|
||||
.flatMap(json -> GeneratorOptions.CODEC.parse(loadedOps, json))
|
||||
.getOrThrow(false, Util.addPrefix("Error parsing worldgen settings after loading data packs: ", LOGGER::error));
|
||||
}
|
||||
|
||||
@Inject(method = "getScannedPack",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourcePackManager;scanPacks()V", shift = At.Shift.BEFORE))
|
||||
private void onScanPacks(CallbackInfoReturnable<Pair<File, ResourcePackManager>> cir) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue