From 76583f75f44210b742345d241b5b5fa7e87b12d4 Mon Sep 17 00:00:00 2001 From: Telesphoreo Date: Wed, 8 May 2024 11:59:41 -0500 Subject: [PATCH] Create 0007-Add-Scissors-configuration-file-command.patch --- ...-Scissors-configuration-file-command.patch | 507 ++++++++++++++++++ 1 file changed, 507 insertions(+) create mode 100644 patches/server/0007-Add-Scissors-configuration-file-command.patch diff --git a/patches/server/0007-Add-Scissors-configuration-file-command.patch b/patches/server/0007-Add-Scissors-configuration-file-command.patch new file mode 100644 index 0000000..25d9965 --- /dev/null +++ b/patches/server/0007-Add-Scissors-configuration-file-command.patch @@ -0,0 +1,507 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Telesphoreo +Date: Wed, 8 May 2024 11:59:08 -0500 +Subject: [PATCH] Add Scissors configuration file & command + + +diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java +index 7620c72a4c243cbeea245203ce03a97cbfa7d922..a05a348c299a68a61fabcbdcc689a89a81d1301f 100644 +--- a/src/main/java/co/aikar/timings/TimingsExport.java ++++ b/src/main/java/co/aikar/timings/TimingsExport.java +@@ -25,6 +25,7 @@ package co.aikar.timings; + + import com.google.common.collect.Sets; + import io.papermc.paper.adventure.PaperAdventure; ++import me.totalfreedom.scissors.ScissorsConfig; + import net.kyori.adventure.text.event.ClickEvent; + import net.kyori.adventure.text.format.NamedTextColor; + import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +@@ -240,7 +241,8 @@ public class TimingsExport extends Thread { + parent.put("config", createObject( + pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)), + pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)), +- pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)) ++ pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)), ++ pair("scissors", mapAsJSON(ScissorsConfig.config, null)) // Scissors + )); + + new TimingsExport(listeners, parent, history).start(); +diff --git a/src/main/java/me/totalfreedom/scissors/ScissorsCommand.java b/src/main/java/me/totalfreedom/scissors/ScissorsCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..797677d892d83cf54d9a60af1e277b67ed3d6e95 +--- /dev/null ++++ b/src/main/java/me/totalfreedom/scissors/ScissorsCommand.java +@@ -0,0 +1,150 @@ ++package me.totalfreedom.scissors; ++ ++import com.google.common.base.Functions; ++import com.google.common.base.Joiner; ++import com.google.common.collect.ImmutableSet; ++import com.google.common.collect.Iterables; ++import com.google.common.collect.Lists; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++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.*; ++import java.util.stream.Collectors; ++ ++public class ScissorsCommand extends Command ++{ ++ ++ private static final String BASE_PERM = "bukkit.command.scissors."; ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("reload", "version").build(); ++ ++ public ScissorsCommand(String name) ++ { ++ super(name); ++ this.description = "Scissors related commands"; ++ this.usageMessage = "/scissors [" + Joiner.on(" | ").join(SUBCOMMANDS) + "]"; ++ this.setPermission("bukkit.command.scissors;" + Joiner.on(';').join(SUBCOMMANDS.stream().map(s -> BASE_PERM + s).collect(Collectors.toSet()))); ++ } ++ ++ private static boolean testPermission(CommandSender commandSender, String permission) ++ { ++ if (commandSender.hasPermission(BASE_PERM + permission) || commandSender.hasPermission("bukkit.command.scissors")) ++ return true; ++ commandSender.sendMessage(Bukkit.getPermissionMessage()); // Sorry, kashike ++ return false; ++ } ++ ++ // Code from Mojang - copyright them ++ public static List getListMatchingLast(CommandSender sender, String[] args, String... matches) ++ { ++ return getListMatchingLast(sender, args, Arrays.asList(matches)); ++ } ++ ++ public static boolean matches(String s, String s1) ++ { ++ return s1.regionMatches(true, 0, s, 0, s.length()); ++ } ++ ++ public static List getListMatchingLast(CommandSender sender, String[] strings, Collection collection) ++ { ++ String last = strings[strings.length - 1]; ++ ArrayList results = Lists.newArrayList(); ++ ++ if (!collection.isEmpty()) ++ { ++ Iterator iterator = Iterables.transform(collection, Functions.toStringFunction()).iterator(); ++ ++ while (iterator.hasNext()) ++ { ++ String s1 = (String) iterator.next(); ++ ++ if (matches(last, s1) && (sender.hasPermission(BASE_PERM + s1) || sender.hasPermission("bukkit.command.scissors"))) ++ { ++ results.add(s1); ++ } ++ } ++ ++ if (results.isEmpty()) ++ { ++ iterator = collection.iterator(); ++ ++ while (iterator.hasNext()) ++ { ++ Object object = iterator.next(); ++ ++ if (object instanceof ResourceLocation && matches(last, ((ResourceLocation) object).getPath())) ++ { ++ results.add(String.valueOf(object)); ++ } ++ } ++ } ++ } ++ ++ return results; ++ } ++ ++ @Override ++ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException ++ { ++ if (args.length <= 1) ++ return getListMatchingLast(sender, args, SUBCOMMANDS); ++ ++ return Collections.emptyList(); ++ } ++ // end copy stuff ++ ++ @Override ++ public boolean execute(CommandSender sender, String commandLabel, String[] args) ++ { ++ if (!testPermission(sender)) return true; ++ ++ if (args.length == 0) ++ { ++ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); ++ return false; ++ } ++ if (SUBCOMMANDS.contains(args[0].toLowerCase(Locale.ENGLISH))) ++ { ++ if (!testPermission(sender, args[0].toLowerCase(Locale.ENGLISH))) return true; ++ } ++ switch (args[0].toLowerCase(Locale.ENGLISH)) ++ { ++ case "reload": ++ doReload(sender); ++ break; ++ case "ver": ++ if (!testPermission(sender, "version")) ++ break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) ++ case "version": ++ Command ver = MinecraftServer.getServer().server.getCommandMap().getCommand("version"); ++ if (ver != null) ++ { ++ ver.execute(sender, commandLabel, new String[0]); ++ break; ++ } ++ // else - fall through to default ++ default: ++ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); ++ return false; ++ } ++ ++ return true; ++ } ++ ++ private void doReload(CommandSender sender) ++ { ++ 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(); ++ ScissorsConfig.init((File) console.options.valueOf("scissors-settings")); ++ console.server.reloadCount++; ++ ++ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Scissors config reload complete."); ++ } ++} +diff --git a/src/main/java/me/totalfreedom/scissors/ScissorsConfig.java b/src/main/java/me/totalfreedom/scissors/ScissorsConfig.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2de0a3d68c3834b9834ab359c823195f8d90ceb2 +--- /dev/null ++++ b/src/main/java/me/totalfreedom/scissors/ScissorsConfig.java +@@ -0,0 +1,225 @@ ++package me.totalfreedom.scissors; ++ ++ ++import com.google.common.base.Throwables; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.dedicated.DedicatedServer; ++import org.bukkit.Bukkit; ++import org.bukkit.command.Command; ++import org.bukkit.configuration.InvalidConfigurationException; ++import org.bukkit.configuration.file.YamlConfiguration; ++ ++import java.io.File; ++import java.io.IOException; ++import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++import java.util.logging.Level; ++import java.util.regex.Pattern; ++ ++// TODO - Migrate to new format ++public class ScissorsConfig ++{ ++ ++ private static final String HEADER = """ ++ This is the main configuration file for Scissors. ++ As you can see, there's tons to configure. Some options may impact gameplay, so use ++ with caution, and make sure you know what each option does before configuring. ++ ++ If you need help with the configuration or have any questions related to Scissors, ++ join us in our Discord. ++ ++ Discord: https://discord.com/invite/mtVQcHn58h ++ Website: https://scissors.gg/\s ++ Docs: https://javadoc.scissors.gg/1.20.1/\s ++ """; ++ private static final Pattern SPACE = Pattern.compile(" "); ++ private static final Pattern NOT_NUMERIC = Pattern.compile("[^-\\d.]"); ++ /*========================================================================*/ ++ public static YamlConfiguration config; ++ static int version; ++ /*========================================================================*/ ++ static Map commands; ++ private static File CONFIG_FILE; ++ ++ public static void init(File configFile) ++ { ++ final File configFolder = (File) DedicatedServer.getServer().options.valueOf("scissors-settings" + "-directory"); ++ final Path configFolderPath = configFolder.toPath(); ++ final Path oldConfigFilePath = configFile.toPath(); ++ final Path newConfigFilePath = configFolderPath.resolve(configFile.toPath()); ++ ++ if (configFile.exists()) ++ { ++ try ++ { ++ Files.move(oldConfigFilePath, newConfigFilePath); ++ } ++ catch (IOException e) ++ { ++ throw new RuntimeException("Error migrating configuration file to new directory!", e); ++ } ++ } ++ ++ CONFIG_FILE = newConfigFilePath.toFile(); ++ config = new YamlConfiguration(); ++ try ++ { ++ config.load(CONFIG_FILE); ++ } ++ catch (IOException ex) ++ { ++ } ++ catch (InvalidConfigurationException ex) ++ { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not load scissors.yml, please correct your syntax errors", ex); ++ throw Throwables.propagate(ex); ++ } ++ ++ commands = new HashMap<>(); ++ commands.put("me/totalfreedom/scissors", new ScissorsCommand("me/totalfreedom/scissors")); ++ ++ config.options().header(HEADER); ++ config.options().copyDefaults(true); ++ ++ version = getInt("config-version", 5); ++ set("config-version", 5); ++ readConfig(ScissorsConfig.class, null); ++ } ++ ++ protected static void logError(String s) ++ { ++ Bukkit.getLogger().severe(s); ++ } ++ ++ protected static void fatal(String s) ++ { ++ throw new RuntimeException("Fatal scissors.yml config error: " + s); ++ } ++ ++ public static void registerCommands() ++ { ++ for (Map.Entry entry : commands.entrySet()) ++ { ++ MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Scissors", entry.getValue()); ++ } ++ } ++ ++ static void readConfig(Class clazz, Object instance) ++ { ++ for (Method method : clazz.getDeclaredMethods()) ++ { ++ if (Modifier.isPrivate(method.getModifiers())) ++ { ++ if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) ++ { ++ try ++ { ++ method.setAccessible(true); ++ method.invoke(instance); ++ } ++ catch (InvocationTargetException ex) ++ { ++ throw Throwables.propagate(ex.getCause()); ++ } ++ catch (Exception ex) ++ { ++ Bukkit.getLogger().log(Level.SEVERE, "Error invoking " + method, ex); ++ } ++ } ++ } ++ } ++ saveConfig(); ++ } ++ ++ static void saveConfig() ++ { ++ try ++ { ++ config.save(CONFIG_FILE); ++ } ++ catch (IOException ex) ++ { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not save " + CONFIG_FILE, ex); ++ } ++ } ++ ++ public static boolean runCommandsInBooks = false; ++ ++ private static void runCommandsInBooks() ++ { ++ runCommandsInBooks = getBoolean("runCommandsInBooks", false); ++ } ++ ++ // people still may want them to bypass permissions for warps ++ public static boolean commandSignsBypassPermissions = false; ++ private static void commandSignsBypassPermissions() ++ { ++ commandSignsBypassPermissions = getBoolean("commandSignsBypassPermissions", false); ++ } ++ ++ public static boolean chatSignaturesEnabled = true; ++ private static void chatSignaturesEnabled() ++ { ++ chatSignaturesEnabled = getBoolean("chatSignaturesEnabled", true); ++ } ++ ++ public static boolean excludePlayersFromNbtComponents = false; ++ private static void excludePlayersFromNbtComponents() ++ { ++ excludePlayersFromNbtComponents = getBoolean("excludePlayersFromNbtComponents", false); ++ } ++ public static int componentDepthLimit = 128; ++ private static void componentDepthLimit() ++ { ++ componentDepthLimit = getInt("componentDepthLimit", 128); ++ } ++ ++ ++ private static void set(String path, Object val) ++ { ++ config.set(path, val); ++ } ++ ++ private static boolean getBoolean(String path, boolean def) ++ { ++ config.addDefault(path, def); ++ return config.getBoolean(path, config.getBoolean(path)); ++ } ++ ++ private static double getDouble(String path, double def) ++ { ++ config.addDefault(path, def); ++ return config.getDouble(path, config.getDouble(path)); ++ } ++ ++ private static float getFloat(String path, float def) ++ { ++ // TODO: Figure out why getFloat() always returns the default value. ++ return (float) getDouble(path, def); ++ } ++ ++ private static int getInt(String path, int def) ++ { ++ config.addDefault(path, def); ++ return config.getInt(path, config.getInt(path)); ++ } ++ ++ private static List getList(String path, T def) ++ { ++ config.addDefault(path, def); ++ return config.getList(path, config.getList(path)); ++ } ++ ++ private static String getString(String path, String def) ++ { ++ config.addDefault(path, def); ++ return config.getString(path, config.getString(path)); ++ } ++} ++ +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index 5443013060b62e3bfcc51cddca96d1c0bc59fe72..1decf99fc2e6b332137eb240210f9f4a9be01085 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -133,6 +133,7 @@ public class Main { + // Paper start - load config files early for access below if needed + org.bukkit.configuration.file.YamlConfiguration bukkitConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionset.valueOf("bukkit-settings")); + org.bukkit.configuration.file.YamlConfiguration spigotConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionset.valueOf("spigot-settings")); ++ org.bukkit.configuration.file.YamlConfiguration scissorsConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionset.valueOf("scissors-settings")); // Scissors - TODO Change this + // Paper end - load config files early for access below if needed + + if (optionset.has("initSettings")) { // CraftBukkit +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index eb4fc900164d1fb3a78653ae8bc42ea30323f5b7..aef57b0054ceed16b0e2b733263049527ccafb1d 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -235,6 +235,16 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now + io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // Paper - init PaperBrigadierProvider + ++ // Scissors start ++ try { ++ me.totalfreedom.scissors.ScissorsConfig.init((java.io.File) options.valueOf("scissors-settings")); ++ } catch (Exception e) { ++ DedicatedServer.LOGGER.error("Unable to load server configuration", e); ++ return false; ++ } ++ me.totalfreedom.scissors.ScissorsConfig.registerCommands(); ++ // Scissors end ++ + this.setPvpAllowed(dedicatedserverproperties.pvp); + this.setFlightAllowed(dedicatedserverproperties.allowFlight); + this.setMotd(dedicatedserverproperties.motd); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 180c16f303ae1aa2c2a9471b2c9cce70303668d4..57e82f87bc45b5c5c67aafe8fb4a0bb172c92270 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1053,6 +1053,7 @@ public final class CraftServer implements Server { + } + + org.spigotmc.SpigotConfig.init((File) this.console.options.valueOf("spigot-settings")); // Spigot ++ me.totalfreedom.scissors.ScissorsConfig.init(((File) console.options.valueOf("scissors-settings"))); // Scissors + this.console.paperConfigurations.reloadConfigs(this.console); + for (ServerLevel world : this.console.getAllLevels()) { + // world.serverLevelData.setDifficulty(config.difficulty); // Paper - per level difficulty +@@ -1084,6 +1085,7 @@ public final class CraftServer implements Server { + this.reloadData(); + org.spigotmc.SpigotConfig.registerCommands(); // Spigot + io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper ++ me.totalfreedom.scissors.ScissorsConfig.registerCommands(); // Scissors + this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); + this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); + +@@ -3048,6 +3050,14 @@ public final class CraftServer implements Server { + return CraftServer.this.console.paperConfigurations.createLegacyObject(CraftServer.this.console); + } + ++ // Scissors start ++ @Override ++ public YamlConfiguration getScissorsConfig() ++ { ++ return me.totalfreedom.scissors.ScissorsConfig.config; ++ } ++ // Scissors end ++ + @Override + public void restart() { + org.spigotmc.RestartCommand.restart(); +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index c988afa496d25314451435eedd64079a0d87cef0..cd5c409cb0025c668c324e59fe191133981b2373 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -168,6 +168,19 @@ public class Main { + .defaultsTo(new File("paper.yml")) + .describedAs("Yml file"); + ++ // Scissors start ++ acceptsAll(asList("scissors-dir", "scissors-settings-directory"), "Directory for Scissors settings") ++ .withRequiredArg() ++ .ofType(File.class) ++ .defaultsTo(new File(io.papermc.paper.configuration.PaperConfigurations.CONFIG_DIR)) ++ .describedAs("Config directory"); ++ acceptsAll(asList("scissors", "scissors-settings"), "File for Scissors settings") ++ .withRequiredArg() ++ .ofType(File.class) ++ .defaultsTo(new File("scissors.yml")) ++ .describedAs("YAML file"); ++ // Scissors end ++ + acceptsAll(asList("add-plugin", "add-extra-plugin-jar"), "Specify paths to extra plugin jars to be loaded in addition to those in the plugins folder. This argument can be specified multiple times, once for each extra plugin jar path.") + .withRequiredArg() + .ofType(File.class)