From 15d3df28187dc0439e17fa87384cfb4ea5c2803e Mon Sep 17 00:00:00 2001 From: Alex O'Neill <35673674+alcatrazEscapee@users.noreply.github.com> Date: Tue, 11 Jan 2022 21:00:04 -0500 Subject: [PATCH] Rework world persistence hooks to fix the double registry injection when loading single player worlds. (#8234) --- .../net/minecraft/client/Minecraft.java.patch | 23 ++-- .../net/minecraft/server/Main.java.patch | 9 +- .../storage/LevelStorageSource.java.patch | 48 +++---- .../net/minecraftforge/common/ForgeHooks.java | 90 +++++++++++++ .../net/minecraftforge/common/ForgeMod.java | 126 +----------------- .../internal/WorldPersistenceHooks.java | 53 -------- 6 files changed, 127 insertions(+), 222 deletions(-) delete mode 100644 src/main/java/net/minecraftforge/internal/WorldPersistenceHooks.java diff --git a/patches/minecraft/net/minecraft/client/Minecraft.java.patch b/patches/minecraft/net/minecraft/client/Minecraft.java.patch index 1ad1099bcb..4a9e166c99 100644 --- a/patches/minecraft/net/minecraft/client/Minecraft.java.patch +++ b/patches/minecraft/net/minecraft/client/Minecraft.java.patch @@ -307,12 +307,13 @@ } private boolean m_91278_() { -@@ -1821,11 +_,11 @@ +@@ -1821,11 +_,12 @@ } public void m_91200_(String p_91201_) { - this.m_91219_(p_91201_, RegistryAccess.m_123086_(), Minecraft::m_91133_, Minecraft::m_91135_, false, Minecraft.ExperimentalDialogType.BACKUP); -+ this.doLoadLevel(p_91201_, RegistryAccess.m_123086_(), Minecraft::m_91133_, Minecraft::m_91135_, false, Minecraft.ExperimentalDialogType.BACKUP, false); ++ // We need to delay the call to RegistryAccess.builtin() as long as possible, in order to allow our world persistence hooks to run. So we pass in null here, and fix it later, only in the case where creating = false ++ this.doLoadLevel(p_91201_, null, Minecraft::m_91133_, Minecraft::m_91135_, false, Minecraft.ExperimentalDialogType.BACKUP, false); } public void m_91202_(String p_91203_, LevelSettings p_91204_, RegistryAccess.RegistryHolder p_91205_, WorldGenSettings p_91206_) { @@ -334,18 +335,16 @@ LevelStorageSource.LevelStorageAccess levelstoragesource$levelstorageaccess; try { levelstoragesource$levelstorageaccess = this.f_91031_.m_78260_(p_91220_); -@@ -1850,12 +_,17 @@ +@@ -1850,12 +_,15 @@ } Minecraft.ServerStem minecraft$serverstem; -+ final RegistryAccess.RegistryHolder dyn_f; ++ final RegistryAccess.RegistryHolder registryHolder; try { - minecraft$serverstem = this.m_91190_(p_91221_, p_91222_, p_91223_, p_91224_, levelstoragesource$levelstorageaccess); -+ Minecraft.ServerStem mgr = this.m_91190_(p_91221_, p_91222_, p_91223_, p_91224_, levelstoragesource$levelstorageaccess); -+ // We need to rebuild this if we're loading world, so that it gets all the information from AFTER we inject our mappings from the save. -+ dyn_f = creating ? p_91221_ : RegistryAccess.m_123086_(); -+ minecraft$serverstem = creating ? mgr : this.m_91190_(dyn_f, p_91222_, p_91223_, p_91224_, levelstoragesource$levelstorageaccess); //Note this runs the injection again... which isn't good.. but hey.. we need a better spot to hook in. -+ ++ if (!creating) levelstoragesource$levelstorageaccess.readAdditionalLevelSaveData(); ++ registryHolder = creating ? p_91221_ : RegistryAccess.m_123086_(); ++ minecraft$serverstem = this.m_91190_(registryHolder, p_91222_, p_91223_, p_91224_, levelstoragesource$levelstorageaccess); } catch (Exception exception) { f_90982_.warn("Failed to load datapacks, can't proceed with server load", (Throwable)exception); this.m_91152_(new DatapackLoadFailureScreen(() -> { @@ -359,7 +358,7 @@ try { - levelstoragesource$levelstorageaccess.m_78287_(p_91221_, worlddata); -+ levelstoragesource$levelstorageaccess.m_78287_(dyn_f, worlddata); ++ levelstoragesource$levelstorageaccess.m_78287_(registryHolder, worlddata); minecraft$serverstem.m_91433_().m_136179_(); YggdrasilAuthenticationService yggdrasilauthenticationservice = new YggdrasilAuthenticationService(this.f_91030_); MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); @@ -368,7 +367,7 @@ GameProfileCache.m_11004_(false); this.f_91007_ = MinecraftServer.m_129872_((p_167898_) -> { - return new IntegratedServer(p_167898_, this, p_91221_, levelstoragesource$levelstorageaccess, minecraft$serverstem.m_91432_(), minecraft$serverstem.m_91433_(), worlddata, minecraftsessionservice, gameprofilerepository, gameprofilecache, (p_168000_) -> { -+ return new IntegratedServer(p_167898_, this, dyn_f, levelstoragesource$levelstorageaccess, minecraft$serverstem.m_91432_(), minecraft$serverstem.m_91433_(), worlddata, minecraftsessionservice, gameprofilerepository, gameprofilecache, (p_168000_) -> { ++ return new IntegratedServer(p_167898_, this, registryHolder, levelstoragesource$levelstorageaccess, minecraft$serverstem.m_91432_(), minecraft$serverstem.m_91433_(), worlddata, minecraftsessionservice, gameprofilerepository, gameprofilecache, (p_168000_) -> { StoringChunkProgressListener storingchunkprogresslistener = new StoringChunkProgressListener(p_168000_ + 0); this.f_90999_.set(storingchunkprogresslistener); return ProcessorChunkProgressListener.m_143583_(storingchunkprogresslistener, this.f_91023_::add); @@ -387,7 +386,7 @@ } else { this.m_91143_(p_91225_, p_91220_, flag, () -> { - this.m_91219_(p_91220_, p_91221_, p_91222_, p_91223_, p_91224_, Minecraft.ExperimentalDialogType.NONE); -+ this.doLoadLevel(p_91220_, dyn_f, p_91222_, p_91223_, p_91224_, Minecraft.ExperimentalDialogType.NONE, creating); ++ this.doLoadLevel(p_91220_, registryHolder, p_91222_, p_91223_, p_91224_, Minecraft.ExperimentalDialogType.NONE, creating); }); minecraft$serverstem.close(); diff --git a/patches/minecraft/net/minecraft/server/Main.java.patch b/patches/minecraft/net/minecraft/server/Main.java.patch index a475dd84bf..87d904c1b8 100644 --- a/patches/minecraft/net/minecraft/server/Main.java.patch +++ b/patches/minecraft/net/minecraft/server/Main.java.patch @@ -23,12 +23,13 @@ CrashReport.m_127529_(); if (optionset.has(optionspec13)) { -@@ -92,28 +_,26 @@ +@@ -92,30 +_,30 @@ Bootstrap.m_135870_(); Bootstrap.m_135889_(); Util.m_137584_(); +- RegistryAccess.RegistryHolder registryaccess$registryholder = RegistryAccess.m_123086_(); + if (!optionset.has(optionspec1)) net.minecraftforge.server.loading.ServerModLoader.load(); // Load mods before we load almost anything else anymore. Single spot now. Only loads if they haven't passed the initserver param - RegistryAccess.RegistryHolder registryaccess$registryholder = RegistryAccess.m_123086_(); ++ RegistryAccess.RegistryHolder registryaccess$registryholder; // RegistryAccess.builtin(); // Delay initialization until after we read additional save data Path path = Paths.get("server.properties"); DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(path); dedicatedserversettings.m_139780_(); @@ -56,7 +57,11 @@ + } LevelStorageSource levelstoragesource = LevelStorageSource.m_78242_(file1.toPath()); LevelStorageSource.LevelStorageAccess levelstoragesource$levelstorageaccess = levelstoragesource.m_78260_(s); ++ levelstoragesource$levelstorageaccess.readAdditionalLevelSaveData(); ++ registryaccess$registryholder = RegistryAccess.m_123086_(); LevelSummary levelsummary = levelstoragesource$levelstorageaccess.m_78308_(); + if (levelsummary != null) { + if (levelsummary.m_193020_()) { @@ -164,6 +_,8 @@ worldgensettings = optionset.has(optionspec3) ? dedicatedserverproperties.m_180927_(registryaccess$registryholder).m_64671_() : dedicatedserverproperties.m_180927_(registryaccess$registryholder); } diff --git a/patches/minecraft/net/minecraft/world/level/storage/LevelStorageSource.java.patch b/patches/minecraft/net/minecraft/world/level/storage/LevelStorageSource.java.patch index 2ebdd08337..21f38fc7a0 100644 --- a/patches/minecraft/net/minecraft/world/level/storage/LevelStorageSource.java.patch +++ b/patches/minecraft/net/minecraft/world/level/storage/LevelStorageSource.java.patch @@ -1,42 +1,30 @@ --- a/net/minecraft/world/level/storage/LevelStorageSource.java +++ b/net/minecraft/world/level/storage/LevelStorageSource.java -@@ -178,6 +_,10 @@ - } - - static BiFunction m_78247_(DynamicOps p_78248_, DataPackConfig p_78249_) { -+ return getReader(p_78248_, p_78249_, null); -+ } -+ -+ private static BiFunction getReader(DynamicOps p_78248_, DataPackConfig p_78249_, @Nullable LevelStorageAccess levelSave) { - return (p_193010_, p_193011_) -> { - try { - CompoundTag compoundtag = NbtIo.m_128937_(p_193010_); -@@ -189,7 +_,10 @@ - Pair pair = m_78204_(dynamic, p_193011_, i); - LevelVersion levelversion = LevelVersion.m_78390_(dynamic); - LevelSettings levelsettings = LevelSettings.m_46924_(dynamic, p_78249_); -- return PrimaryLevelData.m_78530_(dynamic, p_193011_, i, compoundtag2, levelsettings, levelversion, pair.getFirst(), pair.getSecond()); -+ PrimaryLevelData info = PrimaryLevelData.m_78530_(dynamic, p_193011_, i, compoundtag2, levelsettings, levelversion, pair.getFirst(), pair.getSecond()); -+ if (levelSave != null) -+ net.minecraftforge.internal.WorldPersistenceHooks.handleWorldDataLoad(levelSave, info, compoundtag); -+ return info; - } catch (Exception exception) { - f_78191_.error("Exception reading {}", p_193010_, exception); - return null; -@@ -296,7 +_,7 @@ - @Nullable - public WorldData m_78280_(DynamicOps p_78281_, DataPackConfig p_78282_) { - this.m_78313_(); -- return LevelStorageSource.this.m_78229_(this.f_78271_.toFile(), LevelStorageSource.m_78247_(p_78281_, p_78282_)); -+ return LevelStorageSource.this.m_78229_(this.f_78271_.toFile(), LevelStorageSource.getReader(p_78281_, p_78282_, this)); +@@ -299,6 +_,19 @@ + return LevelStorageSource.this.m_78229_(this.f_78271_.toFile(), LevelStorageSource.m_78247_(p_78281_, p_78282_)); } ++ public void readAdditionalLevelSaveData() { ++ m_78313_(); ++ LevelStorageSource.this.m_78229_(this.f_78271_.toFile(), (file, dataFixer) -> { ++ try { ++ CompoundTag compoundTag = NbtIo.m_128937_(file); ++ net.minecraftforge.common.ForgeHooks.readAdditionalLevelSaveData(compoundTag); ++ } catch (Exception e) { ++ f_78191_.error("Exception reading {}", file, e); ++ } ++ return ""; // Return non-null to prevent level.dat-old inject ++ }); ++ } ++ @Nullable + public DataPackConfig m_78309_() { + this.m_78313_(); @@ -315,6 +_,8 @@ CompoundTag compoundtag1 = new CompoundTag(); compoundtag1.m_128365_("Data", compoundtag); -+ net.minecraftforge.internal.WorldPersistenceHooks.handleWorldDataSave(this, p_78292_, compoundtag1); ++ net.minecraftforge.common.ForgeHooks.writeAdditionalLevelSaveData(p_78292_, compoundtag1); + try { File file2 = File.createTempFile("level", ".dat", file1); diff --git a/src/main/java/net/minecraftforge/common/ForgeHooks.java b/src/main/java/net/minecraftforge/common/ForgeHooks.java index 3800bb6a16..570dce836b 100644 --- a/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -29,6 +29,8 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.function.Supplier; @@ -62,6 +64,7 @@ import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.item.*; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.storage.WorldData; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.LootTables; @@ -116,6 +119,7 @@ import net.minecraftforge.common.loot.IGlobalLootModifier; import net.minecraftforge.common.loot.LootModifierManager; import net.minecraftforge.common.loot.LootTableIdCondition; import net.minecraftforge.common.util.BlockSnapshot; +import net.minecraftforge.common.util.MavenVersionStringHelper; import net.minecraftforge.common.world.BiomeGenerationSettingsBuilder; import net.minecraftforge.common.world.ForgeWorldPreset; import net.minecraftforge.common.world.MobSpawnSettingsBuilder; @@ -152,6 +156,8 @@ import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.world.NoteBlockEvent; import net.minecraftforge.eventbus.api.Event.Result; import net.minecraftforge.fluids.FluidAttributes; +import net.minecraftforge.fml.ModContainer; +import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModLoader; import net.minecraftforge.resource.ResourcePackLoader; import net.minecraftforge.registries.DataSerializerEntry; @@ -159,6 +165,7 @@ import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistry; import net.minecraftforge.registries.GameData; import net.minecraftforge.registries.IRegistryDelegate; +import net.minecraftforge.registries.RegistryManager; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -189,6 +196,7 @@ public class ForgeHooks private static final Logger LOGGER = LogManager.getLogger(); @SuppressWarnings("unused") private static final Marker FORGEHOOKS = MarkerManager.getMarker("FORGEHOOKS"); + private static final Marker WORLDPERSISTENCE = MarkerManager.getMarker("WP"); public static boolean canContinueUsing(@Nonnull ItemStack from, @Nonnull ItemStack to) { @@ -1242,4 +1250,86 @@ public class ForgeHooks MinecraftForge.EVENT_BUS.post(new EntityEvent.EnteringSection(entity, packedOldPos, packedNewPos)); } + public static void writeAdditionalLevelSaveData(WorldData worldData, CompoundTag levelTag) + { + CompoundTag fmlData = new CompoundTag(); + ListTag modList = new ListTag(); + ModList.get().getMods().forEach(mi -> + { + final CompoundTag mod = new CompoundTag(); + mod.putString("ModId", mi.getModId()); + mod.putString("ModVersion", MavenVersionStringHelper.artifactVersionToString(mi.getVersion())); + modList.add(mod); + }); + fmlData.put("LoadingModList", modList); + + CompoundTag registries = new CompoundTag(); + fmlData.put("Registries", registries); + LOGGER.debug(WORLDPERSISTENCE, "Gathering id map for writing to world save {}", worldData.getLevelName()); + + for (Map.Entry e : RegistryManager.ACTIVE.takeSnapshot(true).entrySet()) + { + registries.put(e.getKey().toString(), e.getValue().write()); + } + LOGGER.debug(WORLDPERSISTENCE, "ID Map collection complete {}", worldData.getLevelName()); + levelTag.put("fml", fmlData); + } + + public static void readAdditionalLevelSaveData(CompoundTag rootTag) + { + CompoundTag tag = rootTag.getCompound("fml"); + if (tag.contains("LoadingModList")) + { + ListTag modList = tag.getList("LoadingModList", net.minecraft.nbt.Tag.TAG_COMPOUND); + for (int i = 0; i < modList.size(); i++) + { + CompoundTag mod = modList.getCompound(i); + String modId = mod.getString("ModId"); + if (Objects.equals("minecraft", modId)) + { + continue; + } + String modVersion = mod.getString("ModVersion"); + Optional container = ModList.get().getModContainerById(modId); + if (container.isEmpty()) + { + LOGGER.error(WORLDPERSISTENCE,"This world was saved with mod {} which appears to be missing, things may not work well", modId); + continue; + } + if (!Objects.equals(modVersion, MavenVersionStringHelper.artifactVersionToString(container.get().getModInfo().getVersion()))) + { + LOGGER.warn(WORLDPERSISTENCE,"This world was saved with mod {} version {} and it is now at version {}, things may not work well", modId, modVersion, MavenVersionStringHelper.artifactVersionToString(container.get().getModInfo().getVersion())); + } + } + } + + Multimap failedElements = null; + + if (tag.contains("Registries")) + { + Map snapshot = new HashMap<>(); + CompoundTag regs = tag.getCompound("Registries"); + for (String key : regs.getAllKeys()) + { + snapshot.put(new ResourceLocation(key), ForgeRegistry.Snapshot.read(regs.getCompound(key))); + } + failedElements = GameData.injectSnapshot(snapshot, true, true); + } + + if (failedElements != null && !failedElements.isEmpty()) + { + StringBuilder buf = new StringBuilder(); + buf.append("Forge Mod Loader could not load this save.\n\n") + .append("There are ").append(failedElements.size()).append(" unassigned registry entries in this save.\n") + .append("You will not be able to load until they are present again.\n\n"); + + failedElements.asMap().forEach((name, entries) -> + { + buf.append("Missing ").append(name).append(":\n"); + entries.forEach(rl -> buf.append(" ").append(rl).append("\n")); + }); + LOGGER.error(WORLDPERSISTENCE, buf.toString()); + } + } + } diff --git a/src/main/java/net/minecraftforge/common/ForgeMod.java b/src/main/java/net/minecraftforge/common/ForgeMod.java index 7dda4c9e6d..1b810c2c89 100644 --- a/src/main/java/net/minecraftforge/common/ForgeMod.java +++ b/src/main/java/net/minecraftforge/common/ForgeMod.java @@ -50,7 +50,6 @@ import net.minecraftforge.fml.*; import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.event.lifecycle.*; import net.minecraftforge.registries.*; -import net.minecraftforge.internal.WorldPersistenceHooks; import net.minecraftforge.network.NetworkConstants; import net.minecraftforge.event.server.ServerStoppingEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; @@ -98,7 +97,7 @@ import org.apache.logging.log4j.MarkerManager; import java.util.*; @Mod("forge") -public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook +public class ForgeMod { public static final String VERSION_CHECK_CAT = "version_checking"; private static final Logger LOGGER = LogManager.getLogger(); @@ -145,8 +144,6 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook CrashReportCallables.registerCrashCallable("FML", ForgeVersion::getSpec); CrashReportCallables.registerCrashCallable("Forge", ()->ForgeVersion.getGroup()+":"+ForgeVersion.getVersion()); - WorldPersistenceHooks.addHook(this); - WorldPersistenceHooks.addHook(new FMLWorldPersistenceHook()); final IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); modEventBus.addListener(this::registerCapabilities); modEventBus.addListener(this::preInit); @@ -203,38 +200,11 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook WorldWorkerManager.clear(); } - @Override - public CompoundTag getDataForWriting(LevelStorageSource.LevelStorageAccess levelSave, WorldData serverInfo) - { - CompoundTag forgeData = new CompoundTag(); - CompoundTag dims = new CompoundTag(); - //TODO Dimensions -// DimensionManager.writeRegistry(dims); - if (!dims.isEmpty()) - forgeData.put("dims", dims); - return forgeData; - } - - @Override - public void readData(LevelStorageSource.LevelStorageAccess levelSave, WorldData serverInfo, CompoundTag tag) - { - //TODO Dimensions -// if (tag.contains("dims", 10)) -// DimensionManager.readRegistry(tag.getCompound("dims")); -// DimensionManager.processScheduledDeletions(levelSave); - } - public void mappingChanged(RegistryEvent.IdMappingEvent evt) { Ingredient.invalidateAll(); } - @Override - public String getModId() - { - return ForgeVersion.MOD_ID; - } - public void gatherData(GatherDataEvent event) { DataGenerator gen = event.getGenerator(); @@ -312,98 +282,4 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook Registry.register(Registry.LOOT_CONDITION_TYPE, new ResourceLocation("forge:loot_table_id"), LootTableIdCondition.LOOT_TABLE_ID); Registry.register(Registry.LOOT_CONDITION_TYPE, new ResourceLocation("forge:can_tool_perform_action"), CanToolPerformAction.LOOT_CONDITION_TYPE); } - - private static final class FMLWorldPersistenceHook implements WorldPersistenceHooks.WorldPersistenceHook - { - - private static final Logger LOGGER = LogManager.getLogger(); - private static final Marker WORLDPERSISTENCE = MarkerManager.getMarker("WP"); - - @Override - public String getModId() - { - return "fml"; - } - - @Override - public CompoundTag getDataForWriting(LevelStorageSource.LevelStorageAccess levelSave, WorldData serverInfo) - { - CompoundTag fmlData = new CompoundTag(); - ListTag modList = new ListTag(); - ModList.get().getMods().forEach(mi-> - { - final CompoundTag mod = new CompoundTag(); - mod.putString("ModId", mi.getModId()); - mod.putString("ModVersion", MavenVersionStringHelper.artifactVersionToString(mi.getVersion())); - modList.add(mod); - }); - fmlData.put("LoadingModList", modList); - - CompoundTag registries = new CompoundTag(); - fmlData.put("Registries", registries); - LOGGER.debug(WORLDPERSISTENCE,"Gathering id map for writing to world save {}", serverInfo.getLevelName()); - - 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.getLevelName()); - return fmlData; - } - - @Override - public void readData(LevelStorageSource.LevelStorageAccess levelSave, WorldData serverInfo, CompoundTag tag) - { - if (tag.contains("LoadingModList")) - { - ListTag modList = tag.getList("LoadingModList", (byte)10); - for (int i = 0; i < modList.size(); i++) - { - CompoundTag mod = modList.getCompound(i); - String modId = mod.getString("ModId"); - if (Objects.equals("minecraft", modId)) { - continue; - } - String modVersion = mod.getString("ModVersion"); - Optional container = ModList.get().getModContainerById(modId); - if (!container.isPresent()) - { - LOGGER.error(WORLDPERSISTENCE,"This world was saved with mod {} which appears to be missing, things may not work well", modId); - continue; - } - if (!Objects.equals(modVersion, MavenVersionStringHelper.artifactVersionToString(container.get().getModInfo().getVersion()))) - { - LOGGER.warn(WORLDPERSISTENCE,"This world was saved with mod {} version {} and it is now at version {}, things may not work well", modId, modVersion, MavenVersionStringHelper.artifactVersionToString(container.get().getModInfo().getVersion())); - } - } - } - - Multimap failedElements = null; - - if (tag.contains("Registries")) // 1.8, genericed out the 'registries' list - { - Map snapshot = new HashMap<>(); - CompoundTag regs = tag.getCompound("Registries"); - for (String key : regs.getAllKeys()) - { - snapshot.put(new ResourceLocation(key), ForgeRegistry.Snapshot.read(regs.getCompound(key))); - } - failedElements = GameData.injectSnapshot(snapshot, true, true); - } - - if (failedElements != null && !failedElements.isEmpty()) - { - StringBuilder buf = new StringBuilder(); - buf.append("Forge Mod Loader could not load this save.\n\n") - .append("There are ").append(failedElements.size()).append(" unassigned registry entries in this save.\n") - .append("You will not be able to load until they are present again.\n\n"); - - failedElements.asMap().forEach((name, entries) -> - { - buf.append("Missing ").append(name).append(":\n"); - entries.forEach(rl -> buf.append(" ").append(rl).append("\n")); - }); - } - } - } } diff --git a/src/main/java/net/minecraftforge/internal/WorldPersistenceHooks.java b/src/main/java/net/minecraftforge/internal/WorldPersistenceHooks.java deleted file mode 100644 index ee9b16b8a5..0000000000 --- a/src/main/java/net/minecraftforge/internal/WorldPersistenceHooks.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2021. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.minecraftforge.internal; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.storage.WorldData; -import net.minecraft.world.level.storage.LevelStorageSource; - -import java.util.ArrayList; -import java.util.List; - -public class WorldPersistenceHooks -{ - private static List worldPersistenceHooks = new ArrayList<>(); - - public static void addHook(WorldPersistenceHook hook) { - worldPersistenceHooks.add(hook); - } - - public static void handleWorldDataSave(final LevelStorageSource.LevelStorageAccess levelSave, final WorldData serverInfo, final CompoundTag tagCompound) - { - worldPersistenceHooks.forEach(wac->tagCompound.put(wac.getModId(), wac.getDataForWriting(levelSave, serverInfo))); - } - - public static void handleWorldDataLoad(LevelStorageSource.LevelStorageAccess levelSave, WorldData serverInfo, CompoundTag tagCompound) - { - worldPersistenceHooks.forEach(wac->wac.readData(levelSave, serverInfo, tagCompound.getCompound(wac.getModId()))); - } - - public interface WorldPersistenceHook - { - String getModId(); - CompoundTag getDataForWriting(LevelStorageSource.LevelStorageAccess levelSave, WorldData serverInfo); - void readData(LevelStorageSource.LevelStorageAccess levelSave, WorldData serverInfo, CompoundTag tag); - } -}