diff --git a/patches/server/0003-Config-and-command.patch b/patches/server/0003-Config-and-command.patch new file mode 100644 index 0000000..8c1bf90 --- /dev/null +++ b/patches/server/0003-Config-and-command.patch @@ -0,0 +1,281 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: nostalgic853 +Date: Thu, 20 Oct 2022 10:57:42 +0800 +Subject: [PATCH] Config and command + + +diff --git a/src/main/java/cc/keyimc/keyi/KeyiCommand.java b/src/main/java/cc/keyimc/keyi/KeyiCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5ec7a427abba42de2fdcb480586cc17e74bc5c52 +--- /dev/null ++++ b/src/main/java/cc/keyimc/keyi/KeyiCommand.java +@@ -0,0 +1,66 @@ ++package cc.keyimc.keyi; ++ ++import cc.keyimc.keyi.utils.TextUtil; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.ArrayList; ++import java.util.List; ++ ++public final class KeyiCommand extends Command { ++ ++ public KeyiCommand() { ++ super("keyi"); ++ this.description = "KeYi command"; ++ this.usageMessage = "/keyi help"; ++ this.setPermission("keyi.command"); ++ } ++ ++ @Override ++ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { ++ List feedback = new ArrayList<>(); ++ ++ if (args.length >= 1) { ++ feedback.add("reload"); ++ feedback.add("help"); ++ feedback.add("version"); ++ } ++ ++ return feedback; ++ } ++ ++ @Override ++ public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) { ++ if (args.length > 0) { ++ if (args[0].equalsIgnoreCase("help")) { ++ sender.sendMessage(TextUtil.deserialize("<#00f898>KeYi commands:")); ++ sender.sendMessage(TextUtil.deserialize("/keyi reload - reload KeYi config.")); ++ sender.sendMessage(TextUtil.deserialize("/keyi help - show this help message.")); ++ sender.sendMessage(TextUtil.deserialize("/keyi version - show server version information.")); ++ return true; ++ } ++ ++ if (args[0].equalsIgnoreCase("reload")) { ++ KeyiConfig.reload(); ++ sender.sendMessage(TextUtil.deserialize("<#00f898>Reload completed!")); ++ ++ var minecraftServer = MinecraftServer.getServer(); ++ minecraftServer.server.reloadCount++; ++ } ++ ++ if (args[0].equalsIgnoreCase("version")) { ++ Bukkit.dispatchCommand(sender, "bukkit:version"); ++ } ++ } ++ ++ return true; ++ } ++ ++ public static void init() { ++ MinecraftServer.getServer().server.getCommandMap().register("keyi", "KeYi", new KeyiCommand()); ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/cc/keyimc/keyi/KeyiConfig.java b/src/main/java/cc/keyimc/keyi/KeyiConfig.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bc9403d002ef24e71be67a962d099f5d73db9540 +--- /dev/null ++++ b/src/main/java/cc/keyimc/keyi/KeyiConfig.java +@@ -0,0 +1,135 @@ ++ ++package cc.keyimc.keyi; ++ ++import com.google.common.base.Throwables; ++import com.google.common.collect.ImmutableMap; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.Bukkit; ++import org.bukkit.configuration.ConfigurationSection; ++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.util.List; ++import java.util.Map; ++import java.util.logging.Level; ++ ++public final class KeyiConfig { ++ private static File CONFIG_FILE; ++ ++ public static YamlConfiguration config; ++ ++ public static int version; ++ static boolean verbose; ++ ++ public static void init(File configFile) { ++ CONFIG_FILE = configFile; ++ config = new YamlConfiguration(); ++ try { ++ config.load(CONFIG_FILE); ++ } catch (IOException ignore) { ++ } catch (InvalidConfigurationException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not load keyi.yml, please correct your syntax errors.", ex); ++ throw Throwables.propagate(ex); ++ } ++ config.options().copyDefaults(true); ++ verbose = getBoolean("verbose", false); ++ ++ version = getInt("version", 1); ++ set("version", 1); ++ ++ readConfig(KeyiConfig.class, null); ++ } ++ ++ protected static void log(String s) { ++ if (verbose) { ++ log(Level.INFO, s); ++ } ++ } ++ ++ protected static void log(Level level, String s) { ++ Bukkit.getLogger().log(level, s); ++ } ++ ++ 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); ++ } ++ } ++ } ++ } ++ ++ try { ++ config.save(CONFIG_FILE); ++ } catch (IOException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not save " + CONFIG_FILE, ex); ++ } ++ } ++ ++ private static void set(String path, Object val) { ++ config.addDefault(path, val); ++ config.set(path, val); ++ } ++ ++ private static String getString(String path, String def) { ++ config.addDefault(path, def); ++ return config.getString(path, config.getString(path)); ++ } ++ ++ 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 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)); ++ } ++ ++ static Map getMap(String path, Map def) { ++ if (def != null && config.getConfigurationSection(path) == null) { ++ config.addDefault(path, def); ++ return def; ++ } ++ return toMap(config.getConfigurationSection(path)); ++ } ++ ++ private static Map toMap(ConfigurationSection section) { ++ ImmutableMap.Builder builder = ImmutableMap.builder(); ++ if (section != null) { ++ for (String key : section.getKeys(false)) { ++ Object obj = section.get(key); ++ if (obj != null) { ++ builder.put(key, obj instanceof ConfigurationSection val ? toMap(val) : obj); ++ } ++ } ++ } ++ return builder.build(); ++ } ++ ++ public static void reload() { ++ KeyiConfig.init((File) MinecraftServer.getServer().options.valueOf("keyi-settings")); ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/cc/keyimc/keyi/utils/TextUtil.java b/src/main/java/cc/keyimc/keyi/utils/TextUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..510eea6066fb0743a9c561eb577de9d972551771 +--- /dev/null ++++ b/src/main/java/cc/keyimc/keyi/utils/TextUtil.java +@@ -0,0 +1,14 @@ ++package cc.keyimc.keyi.utils; ++ ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.minimessage.MiniMessage; ++import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; ++ ++public final class TextUtil { ++ private TextUtil() { ++ } ++ ++ public static Component deserialize(String str, TagResolver... tagResolvers) { ++ return MiniMessage.miniMessage().deserialize(str, tagResolvers); ++ } ++} +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index a029f51983bcfe49beab1359f282f0f957723ef2..ca0ddafe66dd5d02b1e96b1fc1c574490b68e6d4 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -239,6 +239,16 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + gg.pufferfish.pufferfish.PufferfishConfig.load(); // Pufferfish + gg.pufferfish.pufferfish.PufferfishCommand.init(); // Pufferfish + ++ // KeYi start - init config ++ try { ++ cc.keyimc.keyi.KeyiConfig.init((java.io.File) options.valueOf("keyi-settings")); ++ }catch (Exception e) { ++ LOGGER.error("Failed to load keyi.yml!", e); ++ } ++ // KeYi end ++ ++ cc.keyimc.keyi.KeyiCommand.init(); // KeYi - init command ++ + this.setPvpAllowed(dedicatedserverproperties.pvp); + this.setFlightAllowed(dedicatedserverproperties.allowFlight); + this.setMotd(dedicatedserverproperties.motd); +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 8a4c8701122edf2f29edbe97e4fa199da2744e9e..ebf774da1f2614c0ecb00cf9260ba5a5ca676cb2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -180,6 +180,14 @@ public class Main { + .describedAs("Yml file"); + // Purpur end + ++ // KeYi start ++ acceptsAll(asList("keyi", "keyi-settings"), "File for KeYi settings") ++ .withRequiredArg() ++ .ofType(File.class) ++ .defaultsTo(new File("keyi.yml")) ++ .describedAs("Yml file"); ++ // KeYi end ++ + // Paper start + acceptsAll(asList("server-name"), "Name of the server") + .withRequiredArg()