diff --git a/build.gradle.kts b/build.gradle.kts index 27f3493..3a393cc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -55,8 +55,6 @@ allprojects { } subprojects { - apply(plugin = "java") - tasks { withType().configureEach { options.compilerArgs.addAll(listOf("--add-modules=jdk.incubator.vector", "-Xmaxwarns", "1")) @@ -83,10 +81,9 @@ subprojects { repositories { mavenCentral() - maven("https://papermc.io/repo/repository/maven-public/") maven("https://jitpack.io") + maven("https://papermc.io/repo/repository/maven-public/") } - } paperweight { @@ -123,6 +120,14 @@ alwaysUpToDate { } tasks { + applyPatches { + dependsOn("applyGeneratedApiPatches") + } + + rebuildPatches { + dependsOn("rebuildGeneratedApiPatches") + } + generateDevelopmentBundle { apiCoordinates.set("org.plazmamc.plazma:plazma-api") mojangApiCoordinates.set("io.papermc.paper:paper-mojangapi") diff --git a/patches/server/0008-Plazma-Configurations.patch b/patches/server/0008-Plazma-Configurations.patch index 026b474..dd27d11 100644 --- a/patches/server/0008-Plazma-Configurations.patch +++ b/patches/server/0008-Plazma-Configurations.patch @@ -5,13 +5,27 @@ Subject: [PATCH] Plazma Configurations diff --git a/src/main/java/io/papermc/paper/configuration/Configurations.java b/src/main/java/io/papermc/paper/configuration/Configurations.java -index c01b4393439838976965823298f12e4762e72eff..c8fa51dcfaf1990cce322b25525b6fced24c59cf 100644 +index c01b4393439838976965823298f12e4762e72eff..ca03933d30cb3a6243f6fa243af8dc62cba05050 100644 --- a/src/main/java/io/papermc/paper/configuration/Configurations.java +++ b/src/main/java/io/papermc/paper/configuration/Configurations.java -@@ -41,6 +41,16 @@ public abstract class Configurations { - protected final String globalConfigFileName; - protected final String defaultWorldConfigFileName; - protected final String worldConfigFileName; +@@ -36,28 +36,93 @@ public abstract class Configurations { + public static final String WORLD_DEFAULTS = "__world_defaults__"; + public static final ResourceLocation WORLD_DEFAULTS_KEY = new ResourceLocation("configurations", WORLD_DEFAULTS); + protected final Path globalFolder; +- protected final Class globalConfigClass; +- protected final Class worldConfigClass; +- protected final String globalConfigFileName; +- protected final String defaultWorldConfigFileName; +- protected final String worldConfigFileName; +- +- public Configurations( +- final Path globalFolder, +- final Class globalConfigType, +- final Class worldConfigClass, +- final String globalConfigFileName, +- final String defaultWorldConfigFileName, +- final String worldConfigFileName +- ) { + // Plazma start - Configurable Plazma + @org.jetbrains.annotations.VisibleForTesting + public static final java.util.function.Supplier SPIGOT_WORLD_DEFAULTS = com.google.common.base.Suppliers.memoize(() -> new org.spigotmc.SpigotWorldConfig(org.apache.commons.lang.RandomStringUtils.randomAlphabetic(255)) { @@ -21,97 +35,65 @@ index c01b4393439838976965823298f12e4762e72eff..c8fa51dcfaf1990cce322b25525b6fce + } + }); + protected static final ContextKey> SPIGOT_WORLD_CONFIG_CONTEXT_KEY = new ContextKey<>(new TypeToken<>() {}, "spigot world config"); -+ // Plazma end - Configurable Plazma - - public Configurations( - final Path globalFolder, -@@ -64,18 +74,34 @@ public abstract class Configurations { - .addConstraint(Constraints.Min.class, Number.class, new Constraints.Min.Factory()); ++ ++ public Configurations(final Path globalFolder) { ++ try { ++ createDirectoriesSymlinkAware(globalFolder); ++ } catch (IOException e) { ++ throw new RuntimeException("Could not setup configurations", e); ++ } + this.globalFolder = globalFolder; +- this.globalConfigClass = globalConfigType; +- this.worldConfigClass = worldConfigClass; +- this.globalConfigFileName = globalConfigFileName; +- this.defaultWorldConfigFileName = defaultWorldConfigFileName; +- this.worldConfigFileName = worldConfigFileName; } -+ // Plazma start - Configurable Plazma - protected YamlConfigurationLoader.Builder createLoaderBuilder() { -- return ConfigurationLoaders.naturallySorted(); -+ return ConfigurationLoaders.naturallySorted().defaultOptions(Configurations::defaultOptions); - } - -- protected abstract boolean isConfigType(final Type type); ++ protected abstract Class globalConfigClass(); ++ protected abstract String globalConfigFileName(); ++ protected abstract org.spongepowered.configurate.NodePath[] removedGlobalPaths(); ++ protected abstract G getGlobalConfiguration(); ++ protected abstract Class worldConfigClass(); ++ protected abstract String defaultWorldConfigFileName(); ++ protected abstract String worldConfigFileName(); ++ protected abstract String worldDefaultHeader(); ++ protected abstract org.spongepowered.configurate.NodePath[] removedWorldPaths(); ++ protected abstract W getWorldConfiguration(final ServerLevel level); ++ protected abstract String buildWorldHeader(final ContextMap contextMap); ++ protected abstract Object createWorldConfigInstance(final ContextMap contextMap); ++ + protected static ConfigurationOptions defaultOptions(ConfigurationOptions options) { + return options.serializers(builder -> builder -+ .register(io.papermc.paper.configuration.serializer.collections.MapSerializer.TYPE, new io.papermc.paper.configuration.serializer.collections.MapSerializer(false)) -+ .register(new io.papermc.paper.configuration.serializer.EnumValueSerializer()) -+ .register(new io.papermc.paper.configuration.serializer.ComponentSerializer()) ++ .register(io.papermc.paper.configuration.serializer.collections.MapSerializer.TYPE, new io.papermc.paper.configuration.serializer.collections.MapSerializer(false)) ++ .register(new io.papermc.paper.configuration.serializer.EnumValueSerializer()) ++ .register(new io.papermc.paper.configuration.serializer.ComponentSerializer()) + ); + } + -+ protected boolean isConfigType(final Type type) { -+ return ConfigurationPart.class.isAssignableFrom(io.leangen.geantyref.GenericTypeReflector.erase(type)); -+ } -+ + protected static ObjectMapper.Factory.Builder defaultGlobalFactoryBuilder(ObjectMapper.Factory.Builder builder) { + return builder.addDiscoverer(io.papermc.paper.configuration.mapping.InnerClassFieldDiscoverer.globalConfig()); + } -+ // Plazma end - Configurable Plazma - - protected abstract int globalConfigVersion(); - - protected abstract int worldConfigVersion(); - - protected ObjectMapper.Factory.Builder createGlobalObjectMapperFactoryBuilder() { -- return this.createObjectMapper(); -+ return defaultGlobalFactoryBuilder(this.createObjectMapper()); // Plazma - Configurable Plazma - } - - @MustBeInvokedByOverriders -@@ -93,7 +119,7 @@ public abstract class Configurations { - }; - } - -- static CheckedFunction reloader(Class type, T instance) { -+ protected static CheckedFunction reloader(Class type, T instance) { // Plazma - package -> protected - return node -> { - ObjectMapper.Factory factory = (ObjectMapper.Factory) Objects.requireNonNull(node.options().serializers().get(type)); - ObjectMapper.Mutable mutable = (ObjectMapper.Mutable) factory.get(type); -@@ -154,6 +180,7 @@ public abstract class Configurations { - return ContextMap.builder() - .put(WORLD_NAME, WORLD_DEFAULTS) - .put(WORLD_KEY, WORLD_DEFAULTS_KEY) -+ .put(SPIGOT_WORLD_CONFIG_CONTEXT_KEY, SPIGOT_WORLD_DEFAULTS) // Plazma - Configurable Plazma - .put(REGISTRY_ACCESS, registryAccess); - } - -@@ -194,7 +221,11 @@ public abstract class Configurations { - } - - protected ObjectMapper.Factory.Builder createWorldObjectMapperFactoryBuilder(final ContextMap contextMap) { -- return this.createObjectMapper(); -+ // Plazma start - Configurable Plazma -+ return this.createObjectMapper() -+ .addNodeResolver(new io.papermc.paper.configuration.legacy.RequiresSpigotInitialization.Factory(contextMap.require(SPIGOT_WORLD_CONFIG_CONTEXT_KEY).get())) -+ .addNodeResolver(new NestedSetting.Factory()); -+ // Plazma end - Configurable Plazma - } - - @MustBeInvokedByOverriders -@@ -216,7 +247,7 @@ public abstract class Configurations { - final Path dir = contextMap.require(WORLD_DIRECTORY); - final Path worldConfigFile = dir.resolve(this.worldConfigFileName); - if (Files.notExists(worldConfigFile)) { -- PaperConfigurations.createDirectoriesSymlinkAware(dir); -+ createDirectoriesSymlinkAware(dir); // Plazma - Configurable Plazma - Files.createFile(worldConfigFile); // create empty file as template - newFile = true; - } -@@ -275,6 +306,39 @@ public abstract class Configurations { - return level.convertable.levelDirectory.path().resolve(this.worldConfigFileName); - } - -+ // Plazma start - Configurable Plazma ++ ++ protected static ContextMap createWorldContextMap(ServerLevel level) { ++ 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, org.spigotmc.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, com.google.common.base.Suppliers.ofInstance(spigotConfig)) ++ .put(REGISTRY_ACCESS, registryAccess) ++ .build(); ++ } ++ + @Deprecated + public org.bukkit.configuration.file.YamlConfiguration createLegacyObject(final net.minecraft.server.MinecraftServer server) { -+ org.bukkit.configuration.file.YamlConfiguration global = org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(this.globalFolder.resolve(this.globalConfigFileName).toFile()); ++ org.bukkit.configuration.file.YamlConfiguration global = org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(this.globalFolder.resolve(this.globalConfigFileName()).toFile()); + org.bukkit.configuration.ConfigurationSection worlds = global.createSection("__________WORLDS__________"); -+ worlds.set("__defaults__", org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(this.globalFolder.resolve(this.defaultWorldConfigFileName).toFile())); ++ worlds.set("__defaults__", org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(this.globalFolder.resolve(this.defaultWorldConfigFileName()).toFile())); + for (ServerLevel level : server.getAllLevels()) + worlds.set(level.getWorld().getName(), org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(getWorldConfigFile(level).toFile())); + return global; @@ -124,26 +106,198 @@ index c01b4393439838976965823298f12e4762e72eff..c8fa51dcfaf1990cce322b25525b6fce + } + } + -+ protected static ContextMap createWorldContextMap(ServerLevel level) { -+ 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, org.spigotmc.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, com.google.common.base.Suppliers.ofInstance(spigotConfig)) -+ .put(REGISTRY_ACCESS, registryAccess) -+ .build(); ++ public void reloadConfigs(net.minecraft.server.MinecraftServer server) { ++ try { ++ this.initializeGlobalConfiguration(reloader(this.globalConfigClass(), getGlobalConfiguration())); ++ this.initializeWorldDefaultsConfiguration(server.registryAccess()); ++ for (ServerLevel level : server.getAllLevels()) ++ this.createWorldConfig(createWorldContextMap(level), reloader(this.worldConfigClass(), getWorldConfiguration(level))); ++ } catch (Exception e) { ++ throw new RuntimeException("Could not reload configuration files", e); ++ } + } + // Plazma end - Configurable Plazma + - public static class ContextMap { - private static final Object VOID = new Object(); + protected ObjectMapper.Factory.Builder createObjectMapper() { + return ObjectMapper.factoryBuilder() + .addConstraint(Constraint.class, new Constraint.Factory()) +@@ -65,17 +130,21 @@ public abstract class Configurations { + } + protected YamlConfigurationLoader.Builder createLoaderBuilder() { +- return ConfigurationLoaders.naturallySorted(); ++ return ConfigurationLoaders.naturallySorted().defaultOptions(Configurations::defaultOptions); // Plazma - Configurable Plazma + } + +- protected abstract boolean isConfigType(final Type type); ++ // Plazma start ++ protected boolean isConfigType(final Type type) { ++ return ConfigurationPart.class.isAssignableFrom(io.leangen.geantyref.GenericTypeReflector.erase(type)); ++ } ++ // Plazma end + + protected abstract int globalConfigVersion(); + + protected abstract int worldConfigVersion(); + + protected ObjectMapper.Factory.Builder createGlobalObjectMapperFactoryBuilder() { +- return this.createObjectMapper(); ++ return defaultGlobalFactoryBuilder(this.createObjectMapper()); // Plazma - Configurable Plazma + } + + @MustBeInvokedByOverriders +@@ -93,7 +162,7 @@ public abstract class Configurations { + }; + } + +- static CheckedFunction reloader(Class type, T instance) { ++ protected static CheckedFunction reloader(Class type, T instance) { // Plazma - package -> protected + return node -> { + ObjectMapper.Factory factory = (ObjectMapper.Factory) Objects.requireNonNull(node.options().serializers().get(type)); + ObjectMapper.Mutable mutable = (ObjectMapper.Mutable) factory.get(type); +@@ -103,7 +172,7 @@ public abstract class Configurations { + } + + public G initializeGlobalConfiguration(final RegistryAccess registryAccess) throws ConfigurateException { +- return this.initializeGlobalConfiguration(creator(this.globalConfigClass, true)); ++ return this.initializeGlobalConfiguration(creator(this.globalConfigClass(), true)); // Plazma - Configurable Plazma + } + + private void trySaveFileNode(YamlConfigurationLoader loader, ConfigurationNode node, String filename) throws ConfigurateException { +@@ -117,7 +186,7 @@ public abstract class Configurations { + } + + protected G initializeGlobalConfiguration(final CheckedFunction creator) throws ConfigurateException { +- final Path configFile = this.globalFolder.resolve(this.globalConfigFileName); ++ final Path configFile = this.globalFolder.resolve(this.globalConfigFileName()); // Plazma - Configurable Plazma + final YamlConfigurationLoader loader = this.createGlobalLoaderBuilder() + .defaultOptions(this.applyObjectMapperFactory(this.createGlobalObjectMapperFactoryBuilder().build())) + .path(configFile) +@@ -147,6 +216,13 @@ public abstract class Configurations { + } + + protected void applyGlobalConfigTransformations(final ConfigurationNode node) throws ConfigurateException { ++ // Plazma start - Configurable Plazma ++ org.spongepowered.configurate.transformation.ConfigurationTransformation.Builder builder = org.spongepowered.configurate.transformation.ConfigurationTransformation.builder(); ++ for (org.spongepowered.configurate.NodePath path : removedGlobalPaths()) { ++ builder.addAction(path, org.spongepowered.configurate.transformation.TransformAction.remove()); ++ } ++ builder.build().apply(node); ++ // Plazma end - Configurable Plazma + } + + @MustBeInvokedByOverriders +@@ -154,6 +230,7 @@ public abstract class Configurations { + return ContextMap.builder() + .put(WORLD_NAME, WORLD_DEFAULTS) + .put(WORLD_KEY, WORLD_DEFAULTS_KEY) ++ .put(SPIGOT_WORLD_CONFIG_CONTEXT_KEY, SPIGOT_WORLD_DEFAULTS) // Plazma - Configurable Plazma + .put(REGISTRY_ACCESS, registryAccess); + } + +@@ -161,7 +238,7 @@ public abstract class Configurations { + final ContextMap contextMap = this.createDefaultContextMap(registryAccess) + .put(FIRST_DEFAULT) + .build(); +- final Path configFile = this.globalFolder.resolve(this.defaultWorldConfigFileName); ++ final Path configFile = this.globalFolder.resolve(this.defaultWorldConfigFileName()); // Plazma - Configurable Plazma + final DefaultWorldLoader result = this.createDefaultWorldLoader(false, contextMap, configFile); + final YamlConfigurationLoader loader = result.loader(); + final ConfigurationNode node = loader.load(); +@@ -171,8 +248,8 @@ public abstract class Configurations { + this.verifyWorldConfigVersion(contextMap, node); + } + this.applyWorldConfigTransformations(contextMap, node); +- final W instance = node.require(this.worldConfigClass); +- node.set(this.worldConfigClass, instance); ++ final W instance = node.require(this.worldConfigClass()); // Plazma - Configurable Plazma ++ node.set(this.worldConfigClass(), instance); // Plazma - Configurable Plazma + trySaveFileNode(loader, node, configFile.toString()); + } + +@@ -193,30 +270,41 @@ public abstract class Configurations { + private record DefaultWorldLoader(YamlConfigurationLoader loader, boolean isNewFile) { + } + ++ // Plazma start - Configurable Plazma + protected ObjectMapper.Factory.Builder createWorldObjectMapperFactoryBuilder(final ContextMap contextMap) { +- return this.createObjectMapper(); ++ return this.createObjectMapper() ++ .addNodeResolver(new io.papermc.paper.configuration.legacy.RequiresSpigotInitialization.Factory(contextMap.require(SPIGOT_WORLD_CONFIG_CONTEXT_KEY).get())) ++ .addNodeResolver(new NestedSetting.Factory()) ++ .addDiscoverer(new io.papermc.paper.configuration.mapping.InnerClassFieldDiscoverer(Map.of(this.worldConfigClass(), createWorldConfigInstance(contextMap)))); + } + + @MustBeInvokedByOverriders + protected YamlConfigurationLoader.Builder createWorldConfigLoaderBuilder(final ContextMap contextMap) { +- return this.createLoaderBuilder(); ++ return this.createLoaderBuilder().defaultOptions(options -> options ++ .header(contextMap.require(WORLD_NAME).equals(WORLD_DEFAULTS) ? this.worldDefaultHeader() : this.buildWorldHeader(contextMap))); + } + + // Make sure to run version transforms on the default world config first via #setupWorldDefaultsConfig +- public W createWorldConfig(final ContextMap contextMap) throws IOException { +- return this.createWorldConfig(contextMap, creator(this.worldConfigClass, false)); ++ public W createWorldConfig(final ContextMap contextMap) { ++ final String levelName = contextMap.require(WORLD_NAME); ++ try { ++ return this.createWorldConfig(contextMap, creator(this.worldConfigClass(), false)); ++ } catch (IOException exception) { ++ throw new RuntimeException("Could not create world config for " + levelName, exception); ++ } + } ++ // Plazma end - Configurable Plazma + + protected W createWorldConfig(final ContextMap contextMap, final CheckedFunction creator) throws IOException { +- final Path defaultsConfigFile = this.globalFolder.resolve(this.defaultWorldConfigFileName); ++ final Path defaultsConfigFile = this.globalFolder.resolve(this.defaultWorldConfigFileName()); // Plazma - Configurable Plazma + final YamlConfigurationLoader defaultsLoader = this.createDefaultWorldLoader(true, this.createDefaultContextMap(contextMap.require(REGISTRY_ACCESS)).build(), defaultsConfigFile).loader(); + final ConfigurationNode defaultsNode = defaultsLoader.load(); + + boolean newFile = false; + final Path dir = contextMap.require(WORLD_DIRECTORY); +- final Path worldConfigFile = dir.resolve(this.worldConfigFileName); ++ final Path worldConfigFile = dir.resolve(this.worldConfigFileName()); // Plazma - Configurable Plazma + if (Files.notExists(worldConfigFile)) { +- PaperConfigurations.createDirectoriesSymlinkAware(dir); ++ createDirectoriesSymlinkAware(dir); // Plazma - Configurable Plazma + Files.createFile(worldConfigFile); // create empty file as template + newFile = true; + } +@@ -245,7 +333,7 @@ public abstract class Configurations { + 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"); ++ LOGGER.warn("The world config file for {} didn't have a version set, assuming latest", worldName); // Plazma + } + version.raw(this.worldConfigVersion()); + } else if (version.getInt() > this.worldConfigVersion()) { +@@ -260,6 +348,13 @@ public abstract class Configurations { + } + + protected void applyWorldConfigTransformations(final ContextMap contextMap, final ConfigurationNode node) throws ConfigurateException { ++ // Plazma start - Configurable Plazma ++ org.spongepowered.configurate.transformation.ConfigurationTransformation.Builder builder = org.spongepowered.configurate.transformation.ConfigurationTransformation.builder(); ++ for (org.spongepowered.configurate.NodePath path : removedWorldPaths()) { ++ builder.addAction(path, org.spongepowered.configurate.transformation.TransformAction.remove()); ++ } ++ builder.build().apply(node); ++ // Plazma end - Configurable Plazma + } + + protected void applyDefaultsAwareWorldConfigTransformations(final ContextMap contextMap, final ConfigurationNode worldNode, final ConfigurationNode defaultsNode) throws ConfigurateException { +@@ -272,7 +367,7 @@ public abstract class Configurations { + } + + public Path getWorldConfigFile(ServerLevel level) { +- return level.convertable.levelDirectory.path().resolve(this.worldConfigFileName); ++ return level.convertable.levelDirectory.path().resolve(this.worldConfigFileName()); // Plazma - Configurable Plazma + } + + public static class ContextMap { diff --git a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java -index fa1c0aee8c3a4d0868482cf5c703bbfd08e09874..a2502999965e88e30202894e7bc82b153d43bfbd 100644 +index fa1c0aee8c3a4d0868482cf5c703bbfd08e09874..4a444ac90d357e1b5cc432bccad958054b8a8665 100644 --- a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java +++ b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java @@ -131,6 +131,7 @@ public class PaperConfigurations extends Configurations SPIGOT_WORLD_DEFAULTS = Suppliers.memoize(() -> new SpigotWorldConfig(RandomStringUtils.randomAlphabetic(255)) { @Override // override to ensure "verbose" is false -@@ -139,6 +140,7 @@ public class PaperConfigurations extends Configurations> SPIGOT_WORLD_CONFIG_CONTEXT_KEY = new ContextKey<>(new TypeToken>() {}, "spigot world config"); -+ */ // Plazma - Configurable Plazma - +- ++ // Plazma start - Configurable Plazma ++ */ public PaperConfigurations(final Path globalFolder) { -@@ -155,6 +157,7 @@ public class PaperConfigurations extends Configurations globalConfigClass() { ++ return GlobalConfiguration.class; ++ } ++ ++ @Override ++ protected String globalConfigFileName() { ++ return GLOBAL_CONFIG_FILE_NAME; ++ } ++ ++ @Override ++ protected NodePath[] removedGlobalPaths() { ++ return RemovedConfigurations.REMOVED_GLOBAL_PATHS; + } + ++ @Override ++ protected GlobalConfiguration getGlobalConfiguration() { ++ return GlobalConfiguration.get(); ++ } ++ ++ @Override ++ protected Class worldConfigClass() { ++ return WorldConfiguration.class; ++ } ++ ++ @Override ++ protected String defaultWorldConfigFileName() { ++ return WORLD_DEFAULTS_CONFIG_FILE_NAME; ++ } ++ ++ @Override ++ protected String worldConfigFileName() { ++ return WORLD_CONFIG_FILE_NAME; ++ } ++ ++ @Override ++ protected NodePath[] removedWorldPaths() { ++ return RemovedConfigurations.REMOVED_WORLD_PATHS; ++ } ++ ++ @Override ++ protected String worldDefaultHeader() { ++ return WORLD_DEFAULTS_HEADER; ++ } ++ ++ @Override ++ protected String buildWorldHeader(final ContextMap contextMap) { ++ return WORLD_HEADER.apply(contextMap); ++ } ++ ++ @Override ++ protected WorldConfiguration getWorldConfiguration(final ServerLevel level) { ++ return level.paperConfig(); ++ } ++ // Plazma end - Configurable Plazma ++ + @Override + protected int globalConfigVersion() { + return GlobalConfiguration.CURRENT_VERSION; +@@ -155,6 +213,7 @@ public class PaperConfigurations extends Configurations options +- .header(contextMap.require(WORLD_NAME).equals(WORLD_DEFAULTS) ? WORLD_DEFAULTS_HEADER : WORLD_HEADER.apply(contextMap)) + .serializers(serializers -> serializers + .register(new TypeToken>() {}, new FastutilMapSerializer.SomethingToPrimitive>(Reference2IntOpenHashMap::new, Integer.TYPE)) + .register(new TypeToken>() {}, new FastutilMapSerializer.SomethingToPrimitive>(Reference2LongOpenHashMap::new, Long.TYPE)) +@@ -251,11 +315,7 @@ public class PaperConfigurations extends Configurations WORLD_HEADER = map -> String.format(""" ++ private static final Function WORLD_HEADER = map -> """ + #### ENGLISH #### + This is world-specific Plazma configuration file for the world %s (%s). -+ This file may start empty, but can be filled with options to override world default configuration. ++ This file may start empty, but can be filled with options to override ++ world default configuration. + Some options may impact gameplay, so use with caution, + and make sure you know what each option does before configuring. + @@ -857,13 +1086,13 @@ index 0000000000000000000000000000000000000000..8a22550e19cc3ec00b1db85af5685b75 + + + #### 한국어 #### -+ 본 파일은 %s (%s) 월드 전용 Plazma 월드별 설정 파일입니다. -+ 이 파일은 비어있을 수 있지만, 월드 기본 설정을 덮어쓰기 위해 옵션을 추가할 수 있습니다. ++ 본 파일은 %s (%s) 월드 전용 Plazma 구성 파일입니다. ++ 이 파일은 초기에는 비어있지만, 월드 기본 설정을 덮어쓰기 위해 설정을 추가할 수 있습니다. + 일부 설정은 게임 플레이에 영향을 줄 수 있으므로, 주의해서 사용하시고, + 각 설정이 서버에 어떠한 작용을 하는지 숙지하고 사용하시기 바랍니다. + + 구성에 대한 설명은 공식 위키에서 찾을 수 있으며, -+ 만약 설정에 도움이 필요하거나, Plazma에 대 질문이 있으시다면, ++ 만약 설정에 도움이 필요하거나, Plazma에 대해 질문이 있으시다면, + 공식 Discord 서버에 접속하거나, GitHub 레포지토리에 이슈를 생성해주시기 바랍니다. + + @@ -871,23 +1100,85 @@ index 0000000000000000000000000000000000000000..8a22550e19cc3ec00b1db85af5685b75 + GitHub: https://github.com/PlazmaMC/Plazma + Wiki: https://github.com/PlazmaMC/Plazma/wiki + Discord: https://plazmamc.org/discord -+ """, map.require(WORLD_NAME), map.require(WORLD_KEY), map.require(WORLD_NAME), map.require(WORLD_KEY), -+ CONFIG_DIR, WORLD_DEFAULTS_CONFIG_FILE_NAME); ++ """.formatted( ++ map.require(WORLD_NAME), map.require(WORLD_KEY), ++ map.require(WORLD_NAME), map.require(WORLD_KEY), ++ CONFIG_DIR, WORLD_DEFAULTS_CONFIG_FILE_NAME ++ ); + + public PlazmaConfigurations(final Path globalFolder) { -+ super(globalFolder, GlobalConfiguration.class, WorldConfigurations.class, GLOBAL_CONFIG_FILE_NAME, WORLD_DEFAULTS_CONFIG_FILE_NAME, WORLD_CONFIG_FILE_NAME); ++ super(globalFolder); + } + -+ private static ConfigurationOptions defaultGlobalOptions(ConfigurationOptions options) { -+ return options.header(GLOBAL_HEADER).serializers(builder -> builder -+ .register(new PacketClassSerializer()) -+ .register(IntOr.Default.SERIALIZER) -+ ); ++ @Override ++ protected Class globalConfigClass() { ++ return GlobalConfiguration.class; ++ } ++ ++ @Override ++ protected String globalConfigFileName() { ++ return GLOBAL_CONFIG_FILE_NAME; ++ } ++ ++ @Override ++ protected GlobalConfiguration getGlobalConfiguration() { ++ return GlobalConfiguration.get(); ++ } ++ ++ @Override ++ protected int globalConfigVersion() { ++ return GlobalConfiguration.VERSION; ++ } ++ ++ @Override ++ protected NodePath[] removedGlobalPaths() { ++ return RemovedConfigurations.GLOBAL_PATHS; ++ } ++ ++ @Override ++ protected Class worldConfigClass() { ++ return WorldConfigurations.class; ++ } ++ ++ @Override ++ protected String defaultWorldConfigFileName() { ++ return WORLD_DEFAULTS_CONFIG_FILE_NAME; ++ } ++ ++ @Override ++ protected String worldConfigFileName() { ++ return WORLD_CONFIG_FILE_NAME; ++ } ++ ++ @Override ++ protected String worldDefaultHeader() { ++ return WORLD_DEFAULTS_HEADER; ++ } ++ ++ @Override ++ protected WorldConfigurations getWorldConfiguration(final ServerLevel level) { ++ return level.plazmaConfig(); ++ } ++ ++ @Override ++ protected int worldConfigVersion() { ++ return WorldConfigurations.VERSION; ++ } ++ ++ @Override ++ protected NodePath[] removedWorldPaths() { ++ return RemovedConfigurations.WORLD_PATHS; ++ } ++ ++ @Override ++ protected String buildWorldHeader(final ContextMap contextMap) { ++ return WORLD_HEADER.apply(contextMap); + } + + @Override + protected YamlConfigurationLoader.Builder createGlobalLoaderBuilder() { -+ return super.createGlobalLoaderBuilder().defaultOptions(PlazmaConfigurations::defaultGlobalOptions); ++ return super.createGlobalLoaderBuilder() ++ .defaultOptions(PlazmaConfigurations::defaultGlobalOptions); + } + + @Override @@ -898,120 +1189,22 @@ index 0000000000000000000000000000000000000000..8a22550e19cc3ec00b1db85af5685b75 + } + + @Override -+ protected void applyGlobalConfigTransformations(final ConfigurationNode node) throws ConfigurateException { -+ ConfigurationTransformation.Builder builder = ConfigurationTransformation.builder(); -+ -+ for (NodePath path : RemovedConfigurations.GLOBAL_PATHS) -+ builder.addAction(path, TransformAction.remove()); -+ -+ builder.build().apply(node); ++ protected Object createWorldConfigInstance(final ContextMap contextMap) { ++ return new WorldConfigurations(contextMap.require(WORLD_KEY)); + } + -+ private static FieldDiscoverer worldConfigDiscoverer(final ContextMap contextMap) { -+ final Map, Object> overrides = Map.of( -+ WorldConfigurations.class, new WorldConfigurations(contextMap.require(WORLD_KEY)) -+ ); -+ return new InnerClassFieldDiscoverer(overrides); -+ } -+ -+ @Override -+ protected ObjectMapper.Factory.Builder createWorldObjectMapperFactoryBuilder(final ContextMap contextMap) { -+ return super.createWorldObjectMapperFactoryBuilder(contextMap).addDiscoverer(worldConfigDiscoverer(contextMap)); -+ } -+ -+ @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)) -+ .serializers(serializers -> serializers -+ .register(new TypeToken<>() {}, new FastutilMapSerializer.SomethingToPrimitive>(Reference2IntOpenHashMap::new, Integer.TYPE)) -+ .register(new TypeToken<>() {}, new FastutilMapSerializer.SomethingToPrimitive>(Reference2LongOpenHashMap::new, Long.TYPE)) -+ .register(new TypeToken<>() {}, new TableSerializer()) -+ .register(StringRepresentableSerializer::isValidFor, new StringRepresentableSerializer()) -+ .register(IntOr.Default.SERIALIZER) -+ .register(IntOr.Disabled.SERIALIZER) -+ .register(DoubleOr.Default.SERIALIZER) -+ .register(BooleanOrDefault.SERIALIZER) -+ .register(Duration.SERIALIZER) -+ .register(DurationOrDisabled.SERIALIZER) -+ .register(EngineMode.SERIALIZER) -+ .register(NbtPathSerializer.SERIALIZER) -+ .register(FallbackValueSerializer.create(contextMap.require(SPIGOT_WORLD_CONFIG_CONTEXT_KEY).get(), MinecraftServer::getServer)) -+ .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 -+ public WorldConfigurations createWorldConfig(final ContextMap contextMap) { -+ final String levelName = contextMap.require(WORLD_NAME); -+ try { -+ return super.createWorldConfig(contextMap); -+ } catch (IOException exception) { -+ throw new RuntimeException("Could not create world configuration for " + levelName, exception); -+ } -+ } -+ -+ @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); -+ ConfigurationTransformation.Builder builder = ConfigurationTransformation.builder(); -+ -+ if (version.virtual()) { -+ LOGGER.warn("The world configuration file for " + world + " didn't have a version set, assuming latest"); -+ version.raw(WorldConfigurations.VERSION); -+ } -+ -+ for (NodePath path : RemovedConfigurations.WORLD_PATHS) -+ builder.addAction(path, TransformAction.remove()); -+ -+ builder.build().apply(node); -+ } -+ -+ public static PlazmaConfigurations setup(final Path configDir) { -+ try { -+ createDirectoriesSymlinkAware(configDir); -+ return new PlazmaConfigurations(configDir); -+ } catch (IOException e) { -+ throw new RuntimeException("Could not setup Plazma configuration files", e); -+ } -+ } -+ -+ public void reloadConfigurations(MinecraftServer server) { -+ try { -+ this.initializeGlobalConfiguration(reloader(this.globalConfigClass, GlobalConfiguration.get())); -+ this.initializeWorldDefaultsConfiguration(server.registryAccess()); -+ for (ServerLevel level : server.getAllLevels()) -+ this.createWorldConfig(createWorldContextMap(level), reloader(this.worldConfigClass, level.plazmaConfig())); -+ } catch (Exception e) { -+ throw new RuntimeException("Could not reload Plazma configuration files", e); -+ } ++ protected static ConfigurationOptions defaultGlobalOptions(final ConfigurationOptions options) { ++ return options.header(GLOBAL_HEADER); + } + + @VisibleForTesting + static ConfigurationNode createForTesting() { + ObjectMapper.Factory factory = defaultGlobalFactoryBuilder(ObjectMapper.factoryBuilder()).build(); + ConfigurationOptions options = defaultGlobalOptions(defaultOptions(ConfigurationOptions.defaults())) -+ .serializers(builder -> builder.register(type -> ConfigurationPart.class.isAssignableFrom(erase(type)), factory.asTypeSerializer())); ++ .serializers(builder -> builder.register(type -> ConfigurationPart.class.isAssignableFrom(erase(type)), factory.asTypeSerializer())); + return BasicConfigurationNode.root(options); + } + -+ @Override -+ protected int globalConfigVersion() { -+ return GlobalConfiguration.VERSION; -+ } -+ -+ @Override -+ protected int worldConfigVersion() { -+ return WorldConfigurations.VERSION; -+ } -+ + public static boolean optimize() { + return OPTIMIZE; + } @@ -1038,7 +1231,7 @@ index 0000000000000000000000000000000000000000..25c0f5d28107b45677aa7b19bc0d5238 +} diff --git a/src/main/java/org/plazmamc/plazma/configurations/WorldConfigurations.java b/src/main/java/org/plazmamc/plazma/configurations/WorldConfigurations.java new file mode 100644 -index 0000000000000000000000000000000000000000..842fb520a2d638aaa5bd0a7198190dbe3ecbe14c +index 0000000000000000000000000000000000000000..f2d3d51cb4b8fc7a5fd6db1a63289fff6d32a1ea --- /dev/null +++ b/src/main/java/org/plazmamc/plazma/configurations/WorldConfigurations.java @@ -0,0 +1,22 @@ @@ -1053,7 +1246,7 @@ index 0000000000000000000000000000000000000000..842fb520a2d638aaa5bd0a7198190dbe +public class WorldConfigurations extends ConfigurationPart { + + static final int VERSION = 2; -+ static final boolean OPTIMIZE = org.plazmamc.plazma.configurations.PlazmaConfigurations.optimize(); ++ static final boolean OPTIMIZE = PlazmaConfigurations.optimize(); + + private transient final ResourceLocation worldKey; + public WorldConfigurations(ResourceLocation worldKey) { diff --git a/patches/server/0029-Configurable-cave-lava-sea-level.patch b/patches/server/0029-Configurable-cave-lava-sea-level.patch index 8f0d4a9..5c5f4bd 100644 --- a/patches/server/0029-Configurable-cave-lava-sea-level.patch +++ b/patches/server/0029-Configurable-cave-lava-sea-level.patch @@ -26,7 +26,7 @@ index 98c7f695093acbcf9382a5f07a7a89e373709763..a85b1ebb4236f131b9be0104c4aa56f2 int i = settings.seaLevel(); Aquifer.FluidStatus aquifer_b1 = new Aquifer.FluidStatus(i, settings.defaultFluid()); diff --git a/src/main/java/org/plazmamc/plazma/configurations/GlobalConfiguration.java b/src/main/java/org/plazmamc/plazma/configurations/GlobalConfiguration.java -index 62d891f05b90b323f0282fe26665965a10c317e6..1bba896194316b7b1b2d5e9d5943b7034e1511bb 100644 +index 3e1d646ead7105f4955d47cb224f23ee4d9e3e69..7408401e7e9bd80c1e179c5eca994294f4c01950 100644 --- a/src/main/java/org/plazmamc/plazma/configurations/GlobalConfiguration.java +++ b/src/main/java/org/plazmamc/plazma/configurations/GlobalConfiguration.java @@ -35,6 +35,25 @@ public class GlobalConfiguration extends ConfigurationPart { @@ -45,7 +45,7 @@ index 62d891f05b90b323f0282fe26665965a10c317e6..1bba896194316b7b1b2d5e9d5943b703 + return net.minecraft.core.registries.BuiltInRegistries.BLOCK + .getOptional(new net.minecraft.resources.ResourceLocation(this.customSeaBlock)) + .orElseGet(() -> { -+ PlazmaConfigurations.LOGGER.warn("Invalid custom sea level block: " + this.customSeaBlock, ", defaulting to lava"); ++ PlazmaConfigurations.LOGGER.warn("Invalid custom sea level block: {}, defaulting to lava", this.customSeaBlock); + return net.minecraft.world.level.block.Blocks.LAVA; + }) + .defaultBlockState();