From 7693140ca0e713a557458b0aa2059595fa5d10a5 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Sat, 18 Nov 2023 16:29:14 -0800 Subject: [PATCH] More paper config cleanup (#9938) Also adds a warning and error message if a newer config version was found signaling a downgrade. --- ...dd-Early-Warning-Feature-to-WatchDog.patch | 4 +- ...d-version-history-to-version-command.patch | 2 +- patches/server/Anti-Xray.patch | 38 +-- ...ktraces-in-log-messages-crash-report.patch | 4 +- patches/server/Paper-Metrics.patch | 4 +- patches/server/Paper-command.patch | 4 +- patches/server/Paper-config-files.patch | 231 +++++++++++------- .../fix-converting-txt-to-json-file.patch | 4 +- 8 files changed, 175 insertions(+), 116 deletions(-) diff --git a/patches/server/Add-Early-Warning-Feature-to-WatchDog.patch b/patches/server/Add-Early-Warning-Feature-to-WatchDog.patch index 2c6ef0eebd..80a20277f5 100644 --- a/patches/server/Add-Early-Warning-Feature-to-WatchDog.patch +++ b/patches/server/Add-Early-Warning-Feature-to-WatchDog.patch @@ -26,8 +26,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java @@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface // Paper start - paperConfigurations.initializeGlobalConfiguration(); - paperConfigurations.initializeWorldDefaultsConfiguration(); + paperConfigurations.initializeGlobalConfiguration(this.registryAccess()); + paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess()); + org.spigotmc.WatchdogThread.doStart(org.spigotmc.SpigotConfig.timeoutTime, org.spigotmc.SpigotConfig.restartOnCrash); io.papermc.paper.command.PaperCommands.registerCommands(this); com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); diff --git a/patches/server/Add-version-history-to-version-command.patch b/patches/server/Add-version-history-to-version-command.patch index 72e0c5a96f..b91dbeed8d 100644 --- a/patches/server/Add-version-history-to-version-command.patch +++ b/patches/server/Add-version-history-to-version-command.patch @@ -213,7 +213,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java @@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - paperConfigurations.initializeWorldDefaultsConfiguration(); + paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess()); io.papermc.paper.command.PaperCommands.registerCommands(this); com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); + com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now diff --git a/patches/server/Anti-Xray.patch b/patches/server/Anti-Xray.patch index 65bd1d8729..e690b0409f 100644 --- a/patches/server/Anti-Xray.patch +++ b/patches/server/Anti-Xray.patch @@ -207,13 +207,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import io.papermc.paper.configuration.WorldConfiguration; +import io.papermc.paper.configuration.type.EngineMode; ++import java.util.ArrayList; ++import java.util.LinkedHashSet; ++import java.util.LinkedList; ++import java.util.List; ++import java.util.Set; ++import java.util.concurrent.Executor; ++import java.util.concurrent.ThreadLocalRandom; ++import java.util.function.IntSupplier; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; -+import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; +import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; -+import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; @@ -225,14 +231,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.state.BlockState; -+import net.minecraft.world.level.chunk.*; ++import net.minecraft.world.level.chunk.EmptyLevelChunk; ++import net.minecraft.world.level.chunk.GlobalPalette; ++import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.chunk.LevelChunkSection; ++import net.minecraft.world.level.chunk.MissingPaletteEntryException; ++import net.minecraft.world.level.chunk.Palette; +import org.bukkit.Bukkit; + -+import java.util.*; -+import java.util.concurrent.Executor; -+import java.util.concurrent.ThreadLocalRandom; -+import java.util.function.IntSupplier; -+ +public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockController { + + private static final Palette GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY); @@ -265,7 +271,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + maxBlockHeight = paperWorldConfig.maxBlockHeight >> 4 << 4; + updateRadius = paperWorldConfig.updateRadius; + usePermission = paperWorldConfig.usePermission; -+ List toObfuscate; ++ List toObfuscate; + + if (engineMode == EngineMode.HIDE) { + toObfuscate = paperWorldConfig.hiddenBlocks; @@ -284,11 +290,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + toObfuscate = new ArrayList<>(paperWorldConfig.replacementBlocks); + List presetBlockStateList = new LinkedList<>(); + -+ for (String id : paperWorldConfig.hiddenBlocks) { -+ Block block = BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(id)).orElse(null); ++ for (Block block : paperWorldConfig.hiddenBlocks) { + -+ if (block != null && !(block instanceof EntityBlock)) { -+ toObfuscate.add(id); ++ if (!(block instanceof EntityBlock)) { ++ toObfuscate.add(block); + presetBlockStateList.add(block.defaultBlockState()); + } + } @@ -315,8 +320,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + presetBlockStateBitsEndStoneGlobal = null; + } + -+ for (String id : toObfuscate) { -+ Block block = BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(id)).orElse(null); ++ for (Block block : toObfuscate) { + + // Don't obfuscate air because air causes unnecessary block updates and causes block updates to fail in the void + if (block != null && !block.defaultBlockState().isAir()) { @@ -1107,8 +1111,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Holder holder = worlddimension.type(); // CraftBukkit - decompile error // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error -- super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> minecraftserver.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig))); // Paper -+ super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> minecraftserver.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig)), executor); // Paper - Async-Anti-Xray - Pass executor +- super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> minecraftserver.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig, minecraftserver.registryAccess()))); // Paper ++ super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> minecraftserver.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig, minecraftserver.registryAccess())), executor); // Paper - Async-Anti-Xray - Pass executor this.pvpMode = minecraftserver.isPvpAllowed(); this.convertable = convertable_conversionsession; this.uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile()); diff --git a/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch b/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch index 5b8d2b6d60..fb77c979f4 100644 --- a/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch +++ b/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch @@ -552,8 +552,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Spigot end // Paper start + io.papermc.paper.util.ObfHelper.INSTANCE.getClass(); // Paper - load mappings for stacktrace deobf and etc. - paperConfigurations.initializeGlobalConfiguration(); - paperConfigurations.initializeWorldDefaultsConfiguration(); + paperConfigurations.initializeGlobalConfiguration(this.registryAccess()); + paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess()); org.spigotmc.WatchdogThread.doStart(org.spigotmc.SpigotConfig.timeoutTime, org.spigotmc.SpigotConfig.restartOnCrash); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 diff --git a/patches/server/Paper-Metrics.patch b/patches/server/Paper-Metrics.patch index bc307c004e..49f21e6233 100644 --- a/patches/server/Paper-Metrics.patch +++ b/patches/server/Paper-Metrics.patch @@ -702,8 +702,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java @@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - paperConfigurations.initializeGlobalConfiguration(); - paperConfigurations.initializeWorldDefaultsConfiguration(); + paperConfigurations.initializeGlobalConfiguration(this.registryAccess()); + paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess()); io.papermc.paper.command.PaperCommands.registerCommands(this); + com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper end diff --git a/patches/server/Paper-command.patch b/patches/server/Paper-command.patch index 869e536513..0fb425c653 100644 --- a/patches/server/Paper-command.patch +++ b/patches/server/Paper-command.patch @@ -610,8 +610,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java @@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface // Paper start - paperConfigurations.initializeGlobalConfiguration(); - paperConfigurations.initializeWorldDefaultsConfiguration(); + paperConfigurations.initializeGlobalConfiguration(this.registryAccess()); + paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess()); + io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper end diff --git a/patches/server/Paper-config-files.patch b/patches/server/Paper-config-files.patch index 61748d90e3..745af0c654 100644 --- a/patches/server/Paper-config-files.patch +++ b/patches/server/Paper-config-files.patch @@ -131,6 +131,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import io.leangen.geantyref.TypeToken; +import io.papermc.paper.configuration.constraint.Constraint; +import io.papermc.paper.configuration.constraint.Constraints; ++import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import org.checkerframework.checker.nullness.qual.Nullable; @@ -196,6 +197,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + protected abstract boolean isConfigType(final Type type); + ++ protected abstract int globalConfigVersion(); ++ ++ protected abstract int worldConfigVersion(); ++ + protected ObjectMapper.Factory.Builder createGlobalObjectMapperFactoryBuilder() { + return this.createObjectMapper(); + } @@ -224,7 +229,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }; + } + -+ public G initializeGlobalConfiguration() throws ConfigurateException { ++ public G initializeGlobalConfiguration(final RegistryAccess registryAccess) throws ConfigurateException { + return this.initializeGlobalConfiguration(creator(this.globalConfigClass, true)); + } + @@ -245,10 +250,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .path(configFile) + .build(); + final ConfigurationNode node; -+ if (Files.exists(configFile)) { -+ node = loader.load(); -+ } else { ++ if (Files.notExists(configFile)) { + node = CommentedConfigurationNode.root(loader.defaultOptions()); ++ node.node(Configuration.VERSION_FIELD).raw(this.globalConfigVersion()); ++ } else { ++ node = loader.load(); ++ this.verifyGlobalConfigVersion(node); + } + this.applyGlobalConfigTransformations(node); + final G instance = creator.apply(node); @@ -256,18 +263,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return instance; + } + ++ protected void verifyGlobalConfigVersion(final ConfigurationNode globalNode) { ++ final ConfigurationNode version = globalNode.node(Configuration.VERSION_FIELD); ++ if (version.virtual()) { ++ LOGGER.warn("The global config file didn't have a version set, assuming latest"); ++ version.raw(this.globalConfigVersion()); ++ } else if (version.getInt() > this.globalConfigVersion()) { ++ LOGGER.error("Loading a newer configuration than is supported ({} > {})! You may have to backup & delete your global config file to start the server.", version.getInt(), this.globalConfigVersion()); ++ } ++ } ++ + protected void applyGlobalConfigTransformations(final ConfigurationNode node) throws ConfigurateException { + } + + @MustBeInvokedByOverriders -+ protected ContextMap.Builder createDefaultContextMap() { ++ protected ContextMap.Builder createDefaultContextMap(final RegistryAccess registryAccess) { + return ContextMap.builder() + .put(WORLD_NAME, WORLD_DEFAULTS) -+ .put(WORLD_KEY, WORLD_DEFAULTS_KEY); ++ .put(WORLD_KEY, WORLD_DEFAULTS_KEY) ++ .put(REGISTRY_ACCESS, registryAccess); + } + -+ public void initializeWorldDefaultsConfiguration() throws ConfigurateException { -+ final ContextMap contextMap = this.createDefaultContextMap() ++ public void initializeWorldDefaultsConfiguration(final RegistryAccess registryAccess) throws ConfigurateException { ++ final ContextMap contextMap = this.createDefaultContextMap(registryAccess) + .put(FIRST_DEFAULT) + .build(); + final Path configFile = this.globalFolder.resolve(this.defaultWorldConfigFileName); @@ -275,7 +293,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final YamlConfigurationLoader loader = result.loader(); + final ConfigurationNode node = loader.load(); + if (result.isNewFile()) { // add version to new files -+ node.node(Configuration.VERSION_FIELD).raw(WorldConfiguration.CURRENT_VERSION); ++ node.node(Configuration.VERSION_FIELD).raw(this.worldConfigVersion()); ++ } else { ++ this.verifyWorldConfigVersion(contextMap, node); + } + this.applyWorldConfigTransformations(contextMap, node); + final W instance = node.require(this.worldConfigClass); @@ -316,7 +336,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + protected W createWorldConfig(final ContextMap contextMap, final CheckedFunction creator) throws IOException { + final Path defaultsConfigFile = this.globalFolder.resolve(this.defaultWorldConfigFileName); -+ final YamlConfigurationLoader defaultsLoader = this.createDefaultWorldLoader(true, this.createDefaultContextMap().build(), defaultsConfigFile).loader(); ++ final YamlConfigurationLoader defaultsLoader = this.createDefaultWorldLoader(true, this.createDefaultContextMap(contextMap.require(REGISTRY_ACCESS)).build(), defaultsConfigFile).loader(); + final ConfigurationNode defaultsNode = defaultsLoader.load(); + + boolean newFile = false; @@ -334,7 +354,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .build(); + final ConfigurationNode worldNode = worldLoader.load(); + if (newFile) { // set the version field if new file -+ worldNode.node(Configuration.VERSION_FIELD).set(WorldConfiguration.CURRENT_VERSION); ++ worldNode.node(Configuration.VERSION_FIELD).set(this.worldConfigVersion()); ++ } else { ++ this.verifyWorldConfigVersion(contextMap, worldNode); + } + this.applyWorldConfigTransformations(contextMap, worldNode); + this.applyDefaultsAwareWorldConfigTransformations(contextMap, worldNode, defaultsNode); @@ -343,6 +365,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return creator.apply(worldNode); + } + ++ protected void verifyWorldConfigVersion(final ContextMap contextMap, final ConfigurationNode worldNode) { ++ final ConfigurationNode version = worldNode.node(Configuration.VERSION_FIELD); ++ final String worldName = contextMap.require(WORLD_NAME); ++ if (version.virtual()) { ++ if (worldName.equals(WORLD_DEFAULTS)) { ++ LOGGER.warn("The world defaults config file didn't have a version set, assuming latest"); ++ } else { ++ LOGGER.warn("The world config file for " + worldName + " didn't have a version set, assuming latest"); ++ } ++ version.raw(this.worldConfigVersion()); ++ } else if (version.getInt() > this.worldConfigVersion()) { ++ String msg = "Loading a newer configuration than is supported ({} > {})! "; ++ if (worldName.equals(WORLD_DEFAULTS)) { ++ msg += "You may have to backup & delete the world defaults config file to start the server."; ++ } else { ++ msg += "You may have to backup & delete the " + worldName + " config file to start the server."; ++ } ++ LOGGER.error(msg, version.getInt(), this.worldConfigVersion()); ++ } ++ } ++ + protected void applyWorldConfigTransformations(final ContextMap contextMap, final ConfigurationNode node) throws ConfigurateException { + } + @@ -423,6 +466,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static final ContextKey WORLD_NAME = new ContextKey<>(String.class, "world name"); // TODO remove when we deprecate level names + public static final ContextKey WORLD_KEY = new ContextKey<>(ResourceLocation.class, "world key"); + public static final ContextKey FIRST_DEFAULT = new ContextKey<>(Void.class, "first default"); ++ public static final ContextKey REGISTRY_ACCESS = new ContextKey<>(RegistryAccess.class, "registry access"); + + public record ContextKey(TypeToken type, String name) { + @@ -824,9 +868,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import io.papermc.paper.configuration.type.Duration; +import io.papermc.paper.configuration.type.DurationOrDisabled; +import io.papermc.paper.configuration.type.EngineMode; ++import io.papermc.paper.configuration.type.fallback.FallbackValueSerializer; +import io.papermc.paper.configuration.type.number.DoubleOr; +import io.papermc.paper.configuration.type.number.IntOr; -+import io.papermc.paper.configuration.type.fallback.FallbackValueSerializer; +import it.unimi.dsi.fastutil.objects.Reference2IntMap; +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Reference2LongMap; @@ -840,12 +884,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import java.util.List; +import java.util.function.Function; +import java.util.function.Supplier; ++import net.minecraft.core.RegistryAccess; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.Item; ++import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import org.apache.commons.lang3.RandomStringUtils; +import org.bukkit.configuration.ConfigurationSection; @@ -941,6 +987,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override ++ protected int globalConfigVersion() { ++ return GlobalConfiguration.CURRENT_VERSION; ++ } ++ ++ @Override ++ protected int worldConfigVersion() { ++ return WorldConfiguration.CURRENT_VERSION; ++ } ++ ++ @Override + protected YamlConfigurationLoader.Builder createLoaderBuilder() { + return super.createLoaderBuilder() + .defaultOptions(PaperConfigurations::defaultOptions); @@ -979,15 +1035,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public GlobalConfiguration initializeGlobalConfiguration() throws ConfigurateException { -+ GlobalConfiguration configuration = super.initializeGlobalConfiguration(); ++ public GlobalConfiguration initializeGlobalConfiguration(final RegistryAccess registryAccess) throws ConfigurateException { ++ GlobalConfiguration configuration = super.initializeGlobalConfiguration(registryAccess); + GlobalConfiguration.set(configuration); + return configuration; + } + + @Override -+ protected ContextMap.Builder createDefaultContextMap() { -+ return super.createDefaultContextMap() ++ protected ContextMap.Builder createDefaultContextMap(final RegistryAccess registryAccess) { ++ return super.createDefaultContextMap(registryAccess) + .put(SPIGOT_WORLD_CONFIG_CONTEXT_KEY, SPIGOT_WORLD_DEFAULTS); + } + @@ -1008,6 +1064,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + protected YamlConfigurationLoader.Builder createWorldConfigLoaderBuilder(final ContextMap contextMap) { ++ final RegistryAccess access = contextMap.require(REGISTRY_ACCESS); + return super.createWorldConfigLoaderBuilder(contextMap) + .defaultOptions(options -> options + .header(contextMap.require(WORLD_NAME).equals(WORLD_DEFAULTS) ? WORLD_DEFAULTS_HEADER : WORLD_HEADER.apply(contextMap)) @@ -1025,22 +1082,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .register(EngineMode.SERIALIZER) + .register(NbtPathSerializer.SERIALIZER) + .register(FallbackValueSerializer.create(contextMap.require(SPIGOT_WORLD_CONFIG_CONTEXT_KEY).get(), MinecraftServer::getServer)) -+ .register(new RegistryValueSerializer<>(new TypeToken>() {}, Registries.ENTITY_TYPE, true)) -+ .register(new RegistryValueSerializer<>(Item.class, Registries.ITEM, true)) -+ .register(new RegistryHolderSerializer<>(new TypeToken>() {}, Registries.CONFIGURED_FEATURE, false)) -+ .register(new RegistryHolderSerializer<>(Item.class, Registries.ITEM, true)) ++ .register(new RegistryValueSerializer<>(new TypeToken>() {}, access, Registries.ENTITY_TYPE, true)) ++ .register(new RegistryValueSerializer<>(Item.class, access, Registries.ITEM, true)) ++ .register(new RegistryValueSerializer<>(Block.class, access, Registries.BLOCK, true)) ++ .register(new RegistryHolderSerializer<>(new TypeToken>() {}, access, Registries.CONFIGURED_FEATURE, false)) + ) + ); + } + + @Override + protected void applyWorldConfigTransformations(final ContextMap contextMap, final ConfigurationNode node) throws ConfigurateException { -+ final ConfigurationNode version = node.node(Configuration.VERSION_FIELD); -+ final String world = contextMap.require(WORLD_NAME); -+ if (version.virtual()) { -+ LOGGER.warn("The world config file for " + world + " didn't have a version set, assuming latest"); -+ version.raw(WorldConfiguration.CURRENT_VERSION); -+ } + ConfigurationTransformation.Builder builder = ConfigurationTransformation.builder(); + for (NodePath path : RemovedConfigurations.REMOVED_WORLD_PATHS) { + builder.addAction(path, TransformAction.remove()); @@ -1103,7 +1154,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public void reloadConfigs(MinecraftServer server) { + try { + this.initializeGlobalConfiguration(reloader(this.globalConfigClass, GlobalConfiguration.get())); -+ this.initializeWorldDefaultsConfiguration(); ++ this.initializeWorldDefaultsConfiguration(server.registryAccess()); + for (ServerLevel level : server.getAllLevels()) { + this.createWorldConfig(createWorldContextMap(level), reloader(this.worldConfigClass, level.paperConfig())); + } @@ -1113,15 +1164,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private static ContextMap createWorldContextMap(ServerLevel level) { -+ return createWorldContextMap(level.convertable.levelDirectory.path(), level.serverLevelData.getLevelName(), level.dimension().location(), level.spigotConfig); ++ return createWorldContextMap(level.convertable.levelDirectory.path(), level.serverLevelData.getLevelName(), level.dimension().location(), level.spigotConfig, level.registryAccess()); + } + -+ public static ContextMap createWorldContextMap(Path dir, String levelName, ResourceLocation worldKey, SpigotWorldConfig spigotConfig) { ++ public static ContextMap createWorldContextMap(Path dir, String levelName, ResourceLocation worldKey, SpigotWorldConfig spigotConfig, RegistryAccess registryAccess) { + return ContextMap.builder() + .put(WORLD_DIRECTORY, dir) + .put(WORLD_NAME, levelName) + .put(WORLD_KEY, worldKey) + .put(SPIGOT_WORLD_CONFIG_CONTEXT_KEY, Suppliers.ofInstance(spigotConfig)) ++ .put(REGISTRY_ACCESS, registryAccess) + .build(); + } + @@ -1367,6 +1419,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import it.unimi.dsi.fastutil.objects.Reference2LongMap; +import it.unimi.dsi.fastutil.objects.Reference2LongOpenHashMap; +import java.util.Arrays; ++import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; @@ -1384,8 +1437,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +import net.minecraft.world.entity.decoration.HangingEntity; -+import net.minecraft.world.entity.decoration.ItemFrame; -+import net.minecraft.world.entity.decoration.Painting; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.monster.Vindicator; +import net.minecraft.world.entity.monster.Zombie; @@ -1393,10 +1444,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.NaturalSpawner; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import org.slf4j.Logger; +import org.spigotmc.SpigotWorldConfig; -+import org.spigotmc.TrackingRange; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; +import org.spongepowered.configurate.objectmapping.meta.PostProcess; +import org.spongepowered.configurate.objectmapping.meta.Required; @@ -1445,10 +1497,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public int updateRadius = 2; + public boolean lavaObscures = false; + public boolean usePermission = false; -+ public List hiddenBlocks = List.of("copper_ore", "deepslate_copper_ore", "raw_copper_block", "gold_ore", "deepslate_gold_ore", "iron_ore", "deepslate_iron_ore", "raw_iron_block", -+ "coal_ore", "deepslate_coal_ore", "lapis_ore", "deepslate_lapis_ore", "mossy_cobblestone", "obsidian", "chest", "diamond_ore", "deepslate_diamond_ore", -+ "redstone_ore", "deepslate_redstone_ore", "clay", "emerald_ore", "deepslate_emerald_ore", "ender_chest"); // TODO update type to List -+ public List replacementBlocks = List.of("stone", "oak_planks", "deepslate"); // TODO update type to List ++ public List hiddenBlocks = List.of( ++ // ++ Blocks.COPPER_ORE, ++ Blocks.DEEPSLATE_COPPER_ORE, ++ Blocks.RAW_COPPER_BLOCK, ++ Blocks.GOLD_ORE, ++ Blocks.DEEPSLATE_GOLD_ORE, ++ Blocks.IRON_ORE, ++ Blocks.DEEPSLATE_IRON_ORE, ++ Blocks.RAW_IRON_BLOCK, ++ Blocks.COAL_ORE, ++ Blocks.DEEPSLATE_COAL_ORE, ++ Blocks.LAPIS_ORE, ++ Blocks.DEEPSLATE_LAPIS_ORE, ++ Blocks.MOSSY_COBBLESTONE, ++ Blocks.OBSIDIAN, ++ Blocks.CHEST, ++ Blocks.DIAMOND_ORE, ++ Blocks.DEEPSLATE_DIAMOND_ORE, ++ Blocks.REDSTONE_ORE, ++ Blocks.DEEPSLATE_REDSTONE_ORE, ++ Blocks.CLAY, ++ Blocks.EMERALD_ORE, ++ Blocks.DEEPSLATE_EMERALD_ORE, ++ Blocks.ENDER_CHEST ++ // ++ ); ++ public List replacementBlocks = List.of(Blocks.STONE, Blocks.OAK_PLANKS, Blocks.DEEPSLATE); + } + } + @@ -1579,38 +1655,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public boolean piglinsGuardChests = true; + public double babyZombieMovementModifier = 0.5; + public boolean allowSpiderWorldBorderClimbing = true; -+ public DoorBreakingDifficulty doorBreakingDifficulty; + -+ public class DoorBreakingDifficulty extends ConfigurationPart { // TODO convert to map at some point -+ public List zombie = Arrays.stream(Difficulty.values()).filter(Zombie.DOOR_BREAKING_PREDICATE).toList(); -+ public List husk = Arrays.stream(Difficulty.values()).filter(Zombie.DOOR_BREAKING_PREDICATE).toList(); -+ @Setting("zombie_villager") -+ public List zombieVillager = Arrays.stream(Difficulty.values()).filter(Zombie.DOOR_BREAKING_PREDICATE).toList(); -+ @Setting("zombified_piglin") -+ public List zombified_piglin = Arrays.stream(Difficulty.values()).filter(Zombie.DOOR_BREAKING_PREDICATE).toList(); -+ public List vindicator = Arrays.stream(Difficulty.values()).filter(Vindicator.DOOR_BREAKING_PREDICATE).toList(); -+ -+ // TODO remove when this becomes a proper map -+ public List get(EntityType type) { -+ return this.getOrDefault(type, null); ++ private static final List> ZOMBIE_LIKE = List.of(EntityType.ZOMBIE, EntityType.HUSK, EntityType.ZOMBIE_VILLAGER, EntityType.ZOMBIFIED_PIGLIN); ++ @MergeMap ++ public Map, List> doorBreakingDifficulty = Util.make(new IdentityHashMap<>(), map -> { ++ for (final EntityType type : ZOMBIE_LIKE) { ++ map.put(type, Arrays.stream(Difficulty.values()).filter(Zombie.DOOR_BREAKING_PREDICATE).toList()); + } -+ -+ public List getOrDefault(EntityType type, List fallback) { -+ if (type == EntityType.ZOMBIE) { -+ return this.zombie; -+ } else if (type == EntityType.HUSK) { -+ return this.husk; -+ } else if (type == EntityType.ZOMBIE_VILLAGER) { -+ return this.zombieVillager; -+ } else if (type == EntityType.ZOMBIFIED_PIGLIN) { -+ return this.zombified_piglin; -+ } else if (type == EntityType.VINDICATOR) { -+ return this.vindicator; -+ } else { -+ return fallback; -+ } -+ } -+ } ++ map.put(EntityType.VINDICATOR, Arrays.stream(Difficulty.values()).filter(Vindicator.DOOR_BREAKING_PREDICATE).toList()); ++ }); + + public boolean disableCreeperLingeringEffect = false; + public boolean enderDragonsDeathAlwaysPlacesDragonEgg = false; @@ -3019,36 +3072,38 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package io.papermc.paper.configuration.serializer.registry; + +import io.leangen.geantyref.TypeToken; ++import java.lang.reflect.Type; ++import java.util.function.Predicate; +import net.minecraft.core.Registry; ++import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MinecraftServer; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.configurate.serialize.ScalarSerializer; +import org.spongepowered.configurate.serialize.SerializationException; + -+import java.lang.reflect.Type; -+import java.util.function.Predicate; -+ +abstract class RegistryEntrySerializer extends ScalarSerializer { + ++ private final RegistryAccess registryAccess; + private final ResourceKey> registryKey; + private final boolean omitMinecraftNamespace; + -+ protected RegistryEntrySerializer(TypeToken type, ResourceKey> registryKey, boolean omitMinecraftNamespace) { ++ protected RegistryEntrySerializer(TypeToken type, final RegistryAccess registryAccess, ResourceKey> registryKey, boolean omitMinecraftNamespace) { + super(type); ++ this.registryAccess = registryAccess; + this.registryKey = registryKey; + this.omitMinecraftNamespace = omitMinecraftNamespace; + } + -+ protected RegistryEntrySerializer(Class type, ResourceKey> registryKey, boolean omitMinecraftNamespace) { ++ protected RegistryEntrySerializer(Class type, final RegistryAccess registryAccess, ResourceKey> registryKey, boolean omitMinecraftNamespace) { + super(type); ++ this.registryAccess = registryAccess; + this.registryKey = registryKey; + this.omitMinecraftNamespace = omitMinecraftNamespace; + } + + protected final Registry registry() { -+ return MinecraftServer.getServer().registryAccess().registryOrThrow(this.registryKey); // TODO don't depend on MinecraftServer#getServer ++ return this.registryAccess.registryOrThrow(this.registryKey); + } + + protected abstract T convertFromResourceKey(ResourceKey key) throws SerializationException; @@ -3089,22 +3144,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import com.google.common.base.Preconditions; +import io.leangen.geantyref.TypeFactory; +import io.leangen.geantyref.TypeToken; ++import java.util.function.Function; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; ++import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.ResourceKey; +import org.spongepowered.configurate.serialize.SerializationException; + -+import java.util.function.Function; -+ +public final class RegistryHolderSerializer extends RegistryEntrySerializer, T> { + + @SuppressWarnings("unchecked") -+ public RegistryHolderSerializer(TypeToken typeToken, ResourceKey> registryKey, boolean omitMinecraftNamespace) { -+ super((TypeToken>) TypeToken.get(TypeFactory.parameterizedClass(Holder.class, typeToken.getType())), registryKey, omitMinecraftNamespace); ++ public RegistryHolderSerializer(TypeToken typeToken, final RegistryAccess registryAccess, ResourceKey> registryKey, boolean omitMinecraftNamespace) { ++ super((TypeToken>) TypeToken.get(TypeFactory.parameterizedClass(Holder.class, typeToken.getType())), registryAccess, registryKey, omitMinecraftNamespace); + } + -+ public RegistryHolderSerializer(Class type, ResourceKey> registryKey, boolean omitMinecraftNamespace) { -+ this(TypeToken.get(type), registryKey, omitMinecraftNamespace); ++ public RegistryHolderSerializer(Class type, final RegistryAccess registryAccess, ResourceKey> registryKey, boolean omitMinecraftNamespace) { ++ this(TypeToken.get(type), registryAccess, registryKey, omitMinecraftNamespace); + Preconditions.checkArgument(type.getTypeParameters().length == 0, "%s must have 0 type parameters", type); + } + @@ -3128,6 +3183,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import io.leangen.geantyref.TypeToken; +import net.minecraft.core.Registry; ++import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.ResourceKey; +import org.spongepowered.configurate.serialize.SerializationException; + @@ -3136,12 +3192,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + */ +public final class RegistryValueSerializer extends RegistryEntrySerializer { + -+ public RegistryValueSerializer(TypeToken type, ResourceKey> registryKey, boolean omitMinecraftNamespace) { -+ super(type, registryKey, omitMinecraftNamespace); ++ public RegistryValueSerializer(TypeToken type, final RegistryAccess registryAccess, ResourceKey> registryKey, boolean omitMinecraftNamespace) { ++ super(type, registryAccess, registryKey, omitMinecraftNamespace); + } + -+ public RegistryValueSerializer(Class type, ResourceKey> registryKey, boolean omitMinecraftNamespace) { -+ super(type, registryKey, omitMinecraftNamespace); ++ public RegistryValueSerializer(Class type, final RegistryAccess registryAccess, ResourceKey> registryKey, boolean omitMinecraftNamespace) { ++ super(type, registryAccess, registryKey, omitMinecraftNamespace); + } + + @Override @@ -3468,9 +3524,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + builder.addVersion(VERSION, ConfigurationTransformation.builder().addAction(PATH, INSTANCE).build()); + } + -+ @Nullable + @Override -+ public Object[] visitPath(final NodePath path, final ConfigurationNode value) throws ConfigurateException { ++ public Object @Nullable [] visitPath(final NodePath path, final ConfigurationNode value) throws ConfigurateException { + DedicatedServer server = ((DedicatedServer) MinecraftServer.getServer()); + + boolean val = value.getBoolean(server.settings.getProperties().logIPs); @@ -4840,8 +4895,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 org.spigotmc.SpigotConfig.registerCommands(); // Spigot end + // Paper start -+ paperConfigurations.initializeGlobalConfiguration(); -+ paperConfigurations.initializeWorldDefaultsConfiguration(); ++ paperConfigurations.initializeGlobalConfiguration(this.registryAccess()); ++ paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess()); + // Paper end this.setPvpAllowed(dedicatedserverproperties.pvp); @@ -4867,7 +4922,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error - super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env); -+ super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> minecraftserver.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig))); // Paper ++ super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> minecraftserver.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig, minecraftserver.registryAccess()))); // Paper this.pvpMode = minecraftserver.isPvpAllowed(); this.convertable = convertable_conversionsession; this.uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile()); diff --git a/patches/server/fix-converting-txt-to-json-file.patch b/patches/server/fix-converting-txt-to-json-file.patch index 9f76db6a32..24c860cda0 100644 --- a/patches/server/fix-converting-txt-to-json-file.patch +++ b/patches/server/fix-converting-txt-to-json-file.patch @@ -26,8 +26,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java @@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface io.papermc.paper.util.ObfHelper.INSTANCE.getClass(); // Paper - load mappings for stacktrace deobf and etc. - paperConfigurations.initializeGlobalConfiguration(); - paperConfigurations.initializeWorldDefaultsConfiguration(); + paperConfigurations.initializeGlobalConfiguration(this.registryAccess()); + paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess()); + // Paper start - moved up to right after PlayerList creation but before file load/save + if (this.convertOldUsers()) { + this.getProfileCache().save(false); // Paper