From 94894f63d4f956fcd92d4490b3abae664f062786 Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Tue, 27 Apr 2021 21:43:17 +0800 Subject: [PATCH] Fix GameData get injected multiple times (#170) --- .../forge/FMLWorldPersistenceHookMixin.java | 84 +++++++++++++++++++ .../main/resources/mixins.arclight.forge.json | 1 + 2 files changed, 85 insertions(+) create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/forge/FMLWorldPersistenceHookMixin.java diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/forge/FMLWorldPersistenceHookMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/forge/FMLWorldPersistenceHookMixin.java new file mode 100644 index 00000000..69f32b79 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/forge/FMLWorldPersistenceHookMixin.java @@ -0,0 +1,84 @@ +package io.izzel.arclight.common.mixin.forge; + +import com.google.common.collect.Multimap; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.storage.IServerConfiguration; +import net.minecraft.world.storage.SaveFormat; +import net.minecraftforge.fml.FMLWorldPersistenceHook; +import net.minecraftforge.fml.MavenVersionStringHelper; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.registries.ForgeRegistry; +import net.minecraftforge.registries.GameData; +import net.minecraftforge.registries.RegistryManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +@Mixin(value = FMLWorldPersistenceHook.class, remap = false) +public class FMLWorldPersistenceHookMixin { + + @Shadow @Final private static Logger LOGGER; + @Shadow @Final private static Marker WORLDPERSISTENCE; + + private final Map map = new HashMap<>(); + private boolean injected = false; + + @Redirect(method = "readData", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/registries/GameData;injectSnapshot(Ljava/util/Map;ZZ)Lcom/google/common/collect/Multimap;")) + private Multimap arclight$handleInject(Map snapshot, boolean injectFrozenData, boolean isLocalWorld, + SaveFormat.LevelSave levelSave, IServerConfiguration serverInfo, CompoundNBT tag) { + if (!injected) { + injected = true; + return GameData.injectSnapshot(snapshot, injectFrozenData, isLocalWorld); + } else { + // TODO Properly remap registry and id + map.put(levelSave.getWorldDir(), tag.getCompound("Registries").copy()); + LOGGER.debug(WORLDPERSISTENCE, "Skipped registry injection for {}", serverInfo.getWorldName()); + return null; + } + } + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + public CompoundNBT getDataForWriting(SaveFormat.LevelSave levelSave, IServerConfiguration serverInfo) { + CompoundNBT fmlData = new CompoundNBT(); + ListNBT modList = new ListNBT(); + ModList.get().getMods().forEach(mi -> + { + final CompoundNBT mod = new CompoundNBT(); + mod.putString("ModId", mi.getModId()); + mod.putString("ModVersion", MavenVersionStringHelper.artifactVersionToString(mi.getVersion())); + modList.add(mod); + }); + fmlData.put("LoadingModList", modList); + + CompoundNBT nbt = map.get(levelSave.getWorldDir()); + if (nbt != null) { + fmlData.put("Registries", nbt); + LOGGER.debug(WORLDPERSISTENCE, "Skipped ID Map collection for {}", serverInfo.getWorldName()); + } else { + CompoundNBT registries = new CompoundNBT(); + fmlData.put("Registries", registries); + LOGGER.debug(WORLDPERSISTENCE, "Gathering id map for writing to world save {}", serverInfo.getWorldName()); + + for (Map.Entry e : RegistryManager.ACTIVE.takeSnapshot(true).entrySet()) { + registries.put(e.getKey().toString(), e.getValue().write()); + } + LOGGER.debug(WORLDPERSISTENCE, "ID Map collection complete {}", serverInfo.getWorldName()); + } + return fmlData; + } +} diff --git a/arclight-common/src/main/resources/mixins.arclight.forge.json b/arclight-common/src/main/resources/mixins.arclight.forge.json index b6300287..362088dd 100644 --- a/arclight-common/src/main/resources/mixins.arclight.forge.json +++ b/arclight-common/src/main/resources/mixins.arclight.forge.json @@ -9,6 +9,7 @@ "defaultRequire": 1 }, "mixins": [ + "FMLWorldPersistenceHookMixin", "ForgeEventFactoryMixin", "ForgeHooksMixin", "NetworkHooksMixin",