From cecd8df9910be3ab3302d611c5e9de4c66dd314b Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Tue, 10 Dec 2019 01:47:52 +0100 Subject: [PATCH] Global config, config reload error check, fixes TODO: Config load error check, remove Towny dep #83 --- BuildConfigUpdater/BuildConfigUpdater.iml | 2 -- .../buttondevteam/core/ComponentCommand.java | 9 ++++-- .../java/buttondevteam/core/MainPlugin.java | 10 +++++++ .../lib/architecture/ButtonPlugin.java | 24 ++++++++++------ .../lib/architecture/Component.java | 4 +-- .../lib/architecture/ConfigData.java | 28 ++++++++++++++----- .../java/buttondevteam/lib/chat/Command2.java | 11 ++++++++ .../buttonproc/ConfigProcessor.java | 7 ++++- .../buttondevteam/buttonproc}/HasConfig.java | 3 +- 9 files changed, 73 insertions(+), 25 deletions(-) rename {ButtonCore/src/main/java/buttondevteam/lib/architecture => ButtonProcessor/src/main/java/buttondevteam/buttonproc}/HasConfig.java (82%) diff --git a/BuildConfigUpdater/BuildConfigUpdater.iml b/BuildConfigUpdater/BuildConfigUpdater.iml index 74e6815..67aa057 100644 --- a/BuildConfigUpdater/BuildConfigUpdater.iml +++ b/BuildConfigUpdater/BuildConfigUpdater.iml @@ -18,8 +18,6 @@ - - diff --git a/ButtonCore/src/main/java/buttondevteam/core/ComponentCommand.java b/ButtonCore/src/main/java/buttondevteam/core/ComponentCommand.java index 4e99610..55fbf6f 100644 --- a/ButtonCore/src/main/java/buttondevteam/core/ComponentCommand.java +++ b/ButtonCore/src/main/java/buttondevteam/core/ComponentCommand.java @@ -28,9 +28,12 @@ public class ComponentCommand extends ICommand2MC { "Temporarily enables a component. If you want to permanently enable a component, change it's 'enabled' config option.\"" }) public boolean enable(CommandSender sender, Plugin plugin, String component) { - if (plugin instanceof ButtonPlugin) - ((ButtonPlugin) plugin).justReload(); - else + if (plugin instanceof ButtonPlugin) { + if (!((ButtonPlugin) plugin).justReload()) { + sender.sendMessage("§cCouldn't reload config, check console."); + return true; + } + } else plugin.reloadConfig(); //Reload config so the new config values are read - All changes are saved to disk on disable return enable_disable(sender, plugin, component, true); } diff --git a/ButtonCore/src/main/java/buttondevteam/core/MainPlugin.java b/ButtonCore/src/main/java/buttondevteam/core/MainPlugin.java index 0b3eacc..dfb50ba 100755 --- a/ButtonCore/src/main/java/buttondevteam/core/MainPlugin.java +++ b/ButtonCore/src/main/java/buttondevteam/core/MainPlugin.java @@ -61,15 +61,25 @@ public class MainPlugin extends ButtonPlugin { @Setter private boolean chatHandlerEnabled = true; + /** + * Sets whether the plugin should write a list of installed plugins in a txt file. + * It can be useful if some other software needs to know the plugins. + */ private ConfigData writePluginList() { return getIConfig().getData("writePluginList", false); } + /** + * The chat format to use for messages from other platforms if Chroma-Chat is not installed. + */ ConfigData chatFormat() { return getIConfig().getData("chatFormat", "[{origin}|" + "{channel}] <{name}> {message}"); } + /** + * Print some debug information. + */ public ConfigData test() { return getIConfig().getData("test", false); } diff --git a/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java b/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java index d32fa13..6a18977 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java @@ -1,5 +1,6 @@ package buttondevteam.lib.architecture; +import buttondevteam.buttonproc.HasConfig; import buttondevteam.core.ComponentManager; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.chat.Command2MC; @@ -19,7 +20,7 @@ import java.util.Arrays; import java.util.Optional; import java.util.Stack; -@HasConfig +@HasConfig(global = true) public abstract class ButtonPlugin extends JavaPlugin { @Getter private static Command2MC command2MC = new Command2MC(); @@ -72,7 +73,8 @@ public abstract class ButtonPlugin extends JavaPlugin { pluginPreDisable(); ComponentManager.unregComponents(this); pluginDisable(); - saveConfig(); + if (ConfigData.saveNow(getConfig())) + getLogger().info("Saved configuration changes."); iConfig = null; //Clearing the hashmap is not enough, we need to update the section as well TBMCChatAPI.RemoveCommands(this); } catch (Exception e) { @@ -94,27 +96,31 @@ public abstract class ButtonPlugin extends JavaPlugin { public boolean justReload() { if (yaml != null && ConfigData.saveNow(getConfig())) { - getLogger().warning("Saved pending configuration changes to the file, didn't reload (try again)."); + getLogger().warning("Saved pending configuration changes to the file, didn't reload. Apply your changes again."); return false; } - yaml = new CommentedConfiguration(new File(getDataFolder(), "config.yml")); - yaml.load(); + var file = new File(getDataFolder(), "config.yml"); + var yaml = new CommentedConfiguration(file); + if (file.exists() && !yaml.load()) { + getLogger().warning("Failed to load config! Check for syntax errors."); + return false; + } + this.yaml = yaml; var res = getTextResource("configHelp.yml"); if (res == null) return true; var yc = YamlConfiguration.loadConfiguration(res); for (var kv : yc.getValues(true).entrySet()) if (kv.getValue() instanceof String) - yaml.addComment(kv.getKey(), - Arrays.stream(((String) kv.getValue()).split("\n")) - .map(str -> "# " + str.trim()).toArray(String[]::new)); + yaml.addComment(kv.getKey(), Arrays.stream(((String) kv.getValue()).split("\n")) + .map(str -> "# " + str.trim()).toArray(String[]::new)); return true; } @Override public FileConfiguration getConfig() { if (yaml == null) - justReload(); + justReload(); //TODO: If it fails to load, it'll probably throw an NPE return yaml; } diff --git a/ButtonCore/src/main/java/buttondevteam/lib/architecture/Component.java b/ButtonCore/src/main/java/buttondevteam/lib/architecture/Component.java index 582102f..c4d34d3 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/architecture/Component.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/architecture/Component.java @@ -1,5 +1,6 @@ package buttondevteam.lib.architecture; +import buttondevteam.buttonproc.HasConfig; import buttondevteam.core.ComponentManager; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.architecture.exceptions.UnregisteredComponentException; @@ -22,7 +23,7 @@ import java.util.stream.Collectors; /** * Configuration is based on class name */ -@HasConfig //Used for obtaining javadoc +@HasConfig(global = false) //Used for obtaining javadoc public abstract class Component { private static HashMap, Component> components = new HashMap<>(); @@ -141,7 +142,6 @@ public abstract class Component { //System.out.println("Done enabling "+component.getClassName()); } else { component.disable(); - component.plugin.saveConfig(); TBMCChatAPI.RemoveCommands(component); } } diff --git a/ButtonCore/src/main/java/buttondevteam/lib/architecture/ConfigData.java b/ButtonCore/src/main/java/buttondevteam/lib/architecture/ConfigData.java index c9f0887..b750d15 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/architecture/ConfigData.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/architecture/ConfigData.java @@ -125,17 +125,29 @@ public class ConfigData { } private void setInternal(Object val) { + /*//if (path.contains("Channel")) { + System.out.println("Setting value: " + val); + System.out.println("For path: " + path); + if(path.contains("tc.enabled")) + new Exception("Why does this get set on a reload?").printStackTrace();*/ config.set(path, val); if (!saveTasks.containsKey(config.getRoot())) { + /*//if (path.contains("Channel")) + System.out.println("No save task found, adding new one");*/ synchronized (saveTasks) { saveTasks.put(config.getRoot(), new SaveTask(Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.Instance, () -> { + /*//if (path.contains("Channel")) + System.out.println("Executing save task...");*/ synchronized (saveTasks) { saveTasks.remove(config.getRoot()); saveAction.run(); } + /*//if (path.contains("Channel")) + System.out.println("Save task done");*/ }, 100), saveAction)); } - } + } /*else //if (path.contains("Channel")) - The answer is... The chat plugin goes through the chat channels on command preprocess + System.out.println("Found a save task");*/ } @AllArgsConstructor @@ -145,12 +157,14 @@ public class ConfigData { } public static boolean saveNow(Configuration config) { - SaveTask st = saveTasks.get(config); - if (st != null) { - st.task.cancel(); - saveTasks.remove(config); - st.saveAction.run(); - return true; + synchronized (saveTasks) { + SaveTask st = saveTasks.get(config); + if (st != null) { + st.task.cancel(); + saveTasks.remove(config); + st.saveAction.run(); + return true; + } } return false; } diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2.java index 858e228..2538c63 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2.java @@ -144,6 +144,17 @@ public abstract class Command2 } //Needed because permission checking may load the (perhaps offline) sender's file which is disallowed on the main thread + + /** + * Handles a command asynchronously + * + * @param sender The command sender + * @param commandline The command line the sender sent + * @param sd The subcommand data + * @param subcommand The subcommand text + * @param sync Whether the command was originally sync + * @throws Exception If something's not right + */ public void handleCommandAsync(TP sender, String commandline, SubcommandData sd, String subcommand, boolean sync) throws Exception { if (sd.method == null || sd.command == null) { //Main command not registered, but we have subcommands sender.sendMessage(sd.helpText); diff --git a/ButtonProcessor/src/main/java/buttondevteam/buttonproc/ConfigProcessor.java b/ButtonProcessor/src/main/java/buttondevteam/buttonproc/ConfigProcessor.java index 6d82808..4225e12 100644 --- a/ButtonProcessor/src/main/java/buttondevteam/buttonproc/ConfigProcessor.java +++ b/ButtonProcessor/src/main/java/buttondevteam/buttonproc/ConfigProcessor.java @@ -34,7 +34,12 @@ public class ConfigProcessor { public void process(Element targetcl) { if (targetcl.getModifiers().contains(Modifier.ABSTRACT)) return; - final String path = "components." + targetcl.getSimpleName(); + HasConfig hasConfig = targetcl.getAnnotation(HasConfig.class); + if (hasConfig == null) { + System.out.println("That's not our HasConfig annotation..."); + return; + } + final String path = hasConfig.global() ? "global" : "components." + targetcl.getSimpleName(); File file = new File(fo.toUri()); try { if (file.exists()) diff --git a/ButtonCore/src/main/java/buttondevteam/lib/architecture/HasConfig.java b/ButtonProcessor/src/main/java/buttondevteam/buttonproc/HasConfig.java similarity index 82% rename from ButtonCore/src/main/java/buttondevteam/lib/architecture/HasConfig.java rename to ButtonProcessor/src/main/java/buttondevteam/buttonproc/HasConfig.java index 8e1e63a..7ffdbc1 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/architecture/HasConfig.java +++ b/ButtonProcessor/src/main/java/buttondevteam/buttonproc/HasConfig.java @@ -1,4 +1,4 @@ -package buttondevteam.lib.architecture; +package buttondevteam.buttonproc; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; @@ -10,4 +10,5 @@ import java.lang.annotation.Target; @Target(ElementType.TYPE) @Inherited public @interface HasConfig { + boolean global(); }