From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: MrPowerGamerBR Date: Sun, 22 Oct 2023 09:35:07 -0300 Subject: [PATCH] SparklyPaper config files diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java index 17a158ff6ce6520b69a5a0032ba4c05449dd0cf8..bb8975cd3d3b1c57f313ad31b5e767fa93ad8e13 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java @@ -235,6 +235,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper - setup /paper command this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics + // SparklyPaper start + try { + net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils.INSTANCE.init((java.io.File) options.valueOf("sparklypaper-settings")); + } catch (Exception e) { + DedicatedServer.LOGGER.error("Unable to load server configuration", e); + return false; + } + net.sparklypower.sparklypaper.SparklyPaperCommands.INSTANCE.registerCommands(this); + // SparklyPaper end com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now this.setPvpAllowed(dedicatedserverproperties.pvp); diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java index 2cc264f577fdd81d02783e0d6146bea9728789c7..8433caa61a973d81a5eedc44428926e999c21a03 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -174,6 +174,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl // Paper end - add paper world config public final com.destroystokyo.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray + public net.sparklypower.sparklypaper.configs.SparklyPaperConfig.SparklyPaperWorldConfig sparklyPaperConfig; // SparklyPaper public static BlockPos lastPhysicsProblem; // Spigot private org.spigotmc.TickLimiter entityLimiter; private org.spigotmc.TickLimiter tileLimiter; @@ -842,6 +843,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl // Paper end - getblock optimisations - cache world height/sections this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config + this.sparklyPaperConfig = net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils.INSTANCE.getWorldSettings(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // SparklyPaper this.generator = gen; this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env); diff --git a/src/main/java/net/sparklypower/sparklypaper/commands/SparklyPaperCommand.java b/src/main/java/net/sparklypower/sparklypaper/commands/SparklyPaperCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..bc0ec96f91f7c9ab9f9a865a50f69707fab8fd27 --- /dev/null +++ b/src/main/java/net/sparklypower/sparklypaper/commands/SparklyPaperCommand.java @@ -0,0 +1,65 @@ +package net.sparklypower.sparklypaper.commands; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; + +import java.io.File; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class SparklyPaperCommand extends Command { + public SparklyPaperCommand(String name) { + super(name); + this.description = "SparklyPaper related commands"; + this.usageMessage = "/sparklypaper [reload | version]"; + this.setPermission("bukkit.command.sparklypaper"); + } + + @Override + public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { + if (args.length == 1) { + return Stream.of("reload", "version") + .filter(arg -> arg.startsWith(args[0].toLowerCase())) + .collect(Collectors.toList()); + } + return Collections.emptyList(); + } + + @Override + public boolean execute(CommandSender sender, String commandLabel, String[] args) { + if (!testPermission(sender)) return true; + + if (args.length != 1) { + sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); + return false; + } + + if (args[0].equalsIgnoreCase("reload")) { + Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues."); + Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server."); + + MinecraftServer console = MinecraftServer.getServer(); + SparklyPaperConfigUtils.INSTANCE.init((File) console.options.valueOf("sparklypaper-settings")); + for (ServerLevel level : console.getAllLevels()) { + level.sparklyPaperConfig = SparklyPaperConfigUtils.INSTANCE.getWorldSettings(level.serverLevelData.getLevelName()); + } + console.server.reloadCount++; + + Command.broadcastCommandMessage(sender, ChatColor.GREEN + "SparklyPaper config reload complete."); + } else if (args[0].equalsIgnoreCase("version")) { + Command verCmd = org.bukkit.Bukkit.getServer().getCommandMap().getCommand("version"); + if (verCmd != null) { + return verCmd.execute(sender, commandLabel, new String[0]); + } + } + + return true; + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index ac8af406180bc680d46e8edc3da0fc2e5211345a..29f01accd1cf8de9f97de8533a3a6299dfc80417 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -111,6 +111,7 @@ import net.minecraft.world.level.storage.PlayerDataStorage; import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.validation.ContentValidationException; import net.minecraft.world.phys.Vec3; +import net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils; import org.bukkit.BanList; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -1086,6 +1087,7 @@ public final class CraftServer implements Server { org.spigotmc.SpigotConfig.init((File) this.console.options.valueOf("spigot-settings")); // Spigot this.console.paperConfigurations.reloadConfigs(this.console); + net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils.INSTANCE.init((File) console.options.valueOf("sparklypaper-settings")); // SparklyPaper for (ServerLevel world : this.console.getAllLevels()) { // world.serverLevelData.setDifficulty(config.difficulty); // Paper - per level difficulty world.setSpawnSettings(world.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && config.spawnMonsters); // Paper - per level difficulty (from MinecraftServer#setDifficulty(ServerLevel, Difficulty, boolean)) @@ -1101,6 +1103,7 @@ public final class CraftServer implements Server { } } world.spigotConfig.init(); // Spigot + world.sparklyPaperConfig = SparklyPaperConfigUtils.INSTANCE.getWorldSettings(world.serverLevelData.getLevelName()); // SparklyPaper } Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper @@ -1118,6 +1121,7 @@ public final class CraftServer implements Server { org.spigotmc.SpigotConfig.registerCommands(); // Spigot io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper this.spark.registerCommandBeforePlugins(this); // Paper - spark + net.sparklypower.sparklypaper.SparklyPaperCommands.INSTANCE.registerCommands(this.console); // SparklyPaper this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java index be0d38544395a9b3befb898bb961f34e32fe9509..522efbfaedb20fe3650c6ebe3c1678ee5c0f236a 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -176,6 +176,14 @@ public class Main { .describedAs("Jar file"); // Paper end + // SparklyPaper Start + acceptsAll(asList("sparklypaper", "sparklypaper-settings"), "File for SparklyPaper settings") + .withRequiredArg() + .ofType(File.class) + .defaultsTo(new File("sparklypaper.yml")) + .describedAs("Yml file"); + // SparklyPaper end + // Paper start acceptsAll(asList("server-name"), "Name of the server") .withRequiredArg() diff --git a/src/main/kotlin/net/sparklypower/sparklypaper/SparklyPaperCommands.kt b/src/main/kotlin/net/sparklypower/sparklypaper/SparklyPaperCommands.kt new file mode 100644 index 0000000000000000000000000000000000000000..614e64ce6bf5bb7fab5758250927a0d3949d0917 --- /dev/null +++ b/src/main/kotlin/net/sparklypower/sparklypaper/SparklyPaperCommands.kt @@ -0,0 +1,22 @@ +package net.sparklypower.sparklypaper + +import net.minecraft.server.MinecraftServer +import net.sparklypower.sparklypaper.commands.SparklyPaperCommand +import org.bukkit.command.Command +import org.checkerframework.checker.nullness.qual.NonNull +import org.checkerframework.framework.qual.DefaultQualifier + +@DefaultQualifier(NonNull::class) +object SparklyPaperCommands { + private val COMMANDS = mapOf( + "sparklypaper" to SparklyPaperCommand("sparklypaper") + ) + + fun registerCommands(server: MinecraftServer) { + COMMANDS.forEach { (s: String, command: Command) -> + server.server.commandMap.register( + s, "SparklyPaper", command + ) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/net/sparklypower/sparklypaper/configs/SparklyPaperConfig.kt b/src/main/kotlin/net/sparklypower/sparklypaper/configs/SparklyPaperConfig.kt new file mode 100644 index 0000000000000000000000000000000000000000..f633fe54c176c4e6ec46e54078f8485efadf0fce --- /dev/null +++ b/src/main/kotlin/net/sparklypower/sparklypaper/configs/SparklyPaperConfig.kt @@ -0,0 +1,50 @@ +package net.sparklypower.sparklypaper.configs + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +class SparklyPaperConfig( + @SerialName("config-version") + override val configVersion: Int, + @SerialName("parallel-world-ticking") + val parallelWorldTicking: ParallelWorldTicking, + @SerialName("world-settings") + val worldSettings: Map +) : UpgradeableConfig { + override fun isNewest() = true + + override fun upgradeToNext() = error("This config is already the newest version!") + + @Serializable + class ParallelWorldTicking( + val threads: Int + ) + + @Serializable + class SparklyPaperWorldConfig( + @SerialName("skip-map-item-data-updates-if-map-does-not-have-craftmaprenderer") + val skipMapItemDataUpdatesIfMapDoesNotHaveCraftMapRenderer: Boolean, + @SerialName("blazingly-simple-farm-checks") + val blazinglySimpleFarmChecks: BlazinglySimpleFarmChecks, + @SerialName("ticks-per") + val ticksPer: TicksPer, + ) { + @Serializable + data class BlazinglySimpleFarmChecks( + val enabled: Boolean, + @SerialName("default-growth-speed") + val defaultGrowthSpeed: Float, + @SerialName("moist-growth-speed") + val moistGrowthSpeed: Float, + @SerialName("skip-middle-aging-stages-for-crops") + val skipMiddleAgingStagesForCrops: Boolean + ) + + @Serializable + data class TicksPer( + @SerialName("hopper-cooldown-when-target-container-is-full") + val hopperCooldownWhenTargetContainerIsFull: Int + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/net/sparklypower/sparklypaper/configs/SparklyPaperConfigUtils.kt b/src/main/kotlin/net/sparklypower/sparklypaper/configs/SparklyPaperConfigUtils.kt new file mode 100644 index 0000000000000000000000000000000000000000..072b5811acf9ecc58e3bba7f74dc0dcf8556e848 --- /dev/null +++ b/src/main/kotlin/net/sparklypower/sparklypaper/configs/SparklyPaperConfigUtils.kt @@ -0,0 +1,93 @@ +package net.sparklypower.sparklypaper.configs + +import com.charleskorn.kaml.* +import com.google.common.base.Throwables +import kotlinx.serialization.SerializationException +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString +import net.sparklypower.sparklypaper.configs.previous.SparklyPaperConfigV1 +import org.bukkit.Bukkit +import java.io.File +import java.util.logging.Level + +object SparklyPaperConfigUtils { + private const val CURRENT_CONFIG_VERSION = 2 + val yaml = Yaml( + configuration = YamlConfiguration( + strictMode = false + ) + ) + val deserializationStrategiesForVersions = mapOf( + 1 to SparklyPaperConfigV1.serializer(), + CURRENT_CONFIG_VERSION to SparklyPaperConfig.serializer() + ) + + lateinit var config: SparklyPaperConfig + + fun init(configFile: File) { + // Write default config if the file doesn't exist + if (!configFile.exists()) { + configFile.writeText( + yaml.encodeToString( + SparklyPaperConfig( + CURRENT_CONFIG_VERSION, + SparklyPaperConfig.ParallelWorldTicking( + threads = 8 + ), + mapOf( + "default" to SparklyPaperConfig.SparklyPaperWorldConfig( + skipMapItemDataUpdatesIfMapDoesNotHaveCraftMapRenderer = true, + blazinglySimpleFarmChecks = SparklyPaperConfig.SparklyPaperWorldConfig.BlazinglySimpleFarmChecks( + enabled = false, + defaultGrowthSpeed = 1.0f, + moistGrowthSpeed = 5.0f, + skipMiddleAgingStagesForCrops = true + ), + SparklyPaperConfig.SparklyPaperWorldConfig.TicksPer( + hopperCooldownWhenTargetContainerIsFull = 0 + ) + ) + ) + ) + ) + ) + } + + val loadedConfig = try { + // Read the version file from the config before attempting to parse + val yamlNode = yaml.parseToYamlNode(configFile.readText()) + var configVersion = yamlNode.yamlMap.getScalar("config-version")?.toInt() ?: 1 // The first config version didn't have the "config-version" key + + if (configVersion != CURRENT_CONFIG_VERSION) { + var upgradedVersion: UpgradeableConfig? = null + + while (configVersion != CURRENT_CONFIG_VERSION) { + Bukkit.getLogger().log(Level.INFO, "Attempting to upgrade SparklyPaper Config from version $configVersion to the next version...") + + val upgradeableConfig = yaml.decodeFromYamlNode(deserializationStrategiesForVersions[configVersion]!!, yamlNode) + if (!upgradeableConfig.isNewest()) { + upgradedVersion = upgradeableConfig.upgradeToNext() + + Bukkit.getLogger().log(Level.INFO, "Upgraded SparklyPaper Config from version $configVersion to ${upgradedVersion.configVersion}") + configVersion = upgradedVersion.configVersion + } + } + + upgradedVersion as SparklyPaperConfig + } else { + yaml.decodeFromYamlNode(SparklyPaperConfig.serializer(), yamlNode) + } + } catch (e: SerializationException) { + Bukkit.getLogger().log(Level.SEVERE, "Could not load sparklypaper.yml, please correct your syntax errors", e) + throw Throwables.propagate(e) + } + // Rewrite the config file to remove old fields and stuff + // TODO: Maybe handle this in another way? This feels kinda bad + configFile.writeText(yaml.encodeToString(loadedConfig)) + config = loadedConfig + } + + fun getWorldSettings(levelName: String): SparklyPaperConfig.SparklyPaperWorldConfig { + return config.worldSettings[levelName] ?: config.worldSettings["default"] ?: error("Missing default world-settings in sparklypaper.yml!") + } +} \ No newline at end of file diff --git a/src/main/kotlin/net/sparklypower/sparklypaper/configs/UpgradeableConfig.kt b/src/main/kotlin/net/sparklypower/sparklypaper/configs/UpgradeableConfig.kt new file mode 100644 index 0000000000000000000000000000000000000000..e6de89ef69bd492a9e9facaa189e260678e2c6e6 --- /dev/null +++ b/src/main/kotlin/net/sparklypower/sparklypaper/configs/UpgradeableConfig.kt @@ -0,0 +1,7 @@ +package net.sparklypower.sparklypaper.configs + +interface UpgradeableConfig { + abstract val configVersion: Int + fun isNewest(): Boolean + fun upgradeToNext(): UpgradeableConfig +} \ No newline at end of file diff --git a/src/main/kotlin/net/sparklypower/sparklypaper/configs/previous/SparklyPaperConfigV1.kt b/src/main/kotlin/net/sparklypower/sparklypaper/configs/previous/SparklyPaperConfigV1.kt new file mode 100644 index 0000000000000000000000000000000000000000..fe86a557388cea29dfad8ba5e3990e3272cf0c55 --- /dev/null +++ b/src/main/kotlin/net/sparklypower/sparklypaper/configs/previous/SparklyPaperConfigV1.kt @@ -0,0 +1,65 @@ +package net.sparklypower.sparklypaper.configs.previous + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import net.sparklypower.sparklypaper.configs.SparklyPaperConfig +import net.sparklypower.sparklypaper.configs.UpgradeableConfig + +@Serializable +class SparklyPaperConfigV1( + @SerialName("parallel-world-ticking") + val parallelWorldTicking: ParallelWorldTicking, + @SerialName("world-settings") + val worldSettings: Map +) : UpgradeableConfig { + override val configVersion = 1 + + override fun isNewest() = false + + override fun upgradeToNext(): UpgradeableConfig { + return SparklyPaperConfig( + 2, + SparklyPaperConfig.ParallelWorldTicking( + this.parallelWorldTicking.threads + ), + worldSettings.mapValues { + SparklyPaperConfig.SparklyPaperWorldConfig( + it.value.skipMapItemDataUpdatesIfMapDoesNotHaveCraftMapRenderer, + SparklyPaperConfig.SparklyPaperWorldConfig.BlazinglySimpleFarmChecks( + it.value.blazinglySimpleFarmChecks.enabled, + it.value.blazinglySimpleFarmChecks.defaultGrowthSpeed, + it.value.blazinglySimpleFarmChecks.moistGrowthSpeed, + it.value.blazinglySimpleFarmChecks.skipMiddleAgingStagesForCrops, + ), + SparklyPaperConfig.SparklyPaperWorldConfig.TicksPer( + 0 + ) + ) + } + ) + } + + @Serializable + class ParallelWorldTicking( + val threads: Int + ) + + @Serializable + class SparklyPaperWorldConfig( + @SerialName("skip-map-item-data-updates-if-map-does-not-have-craftmaprenderer") + val skipMapItemDataUpdatesIfMapDoesNotHaveCraftMapRenderer: Boolean, + @SerialName("blazingly-simple-farm-checks") + val blazinglySimpleFarmChecks: BlazinglySimpleFarmChecks + ) { + @Serializable + data class BlazinglySimpleFarmChecks( + val enabled: Boolean, + @SerialName("default-growth-speed") + val defaultGrowthSpeed: Float, + @SerialName("moist-growth-speed") + val moistGrowthSpeed: Float, + @SerialName("skip-middle-aging-stages-for-crops") + val skipMiddleAgingStagesForCrops: Boolean + ) + } +} \ No newline at end of file