Implemented config save and reload
Always caching config value if it hasn't been cached
This commit is contained in:
parent
7289385a33
commit
25b9caa903
8 changed files with 77 additions and 20 deletions
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4">
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||||
<output url="file://$MODULE_DIR$/target/classes" />
|
<output url="file://$MODULE_DIR$/target/classes" />
|
||||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package buttondevteam.core;
|
package buttondevteam.core;
|
||||||
|
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
|
import buttondevteam.lib.architecture.ButtonPlugin;
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.architecture.Component;
|
||||||
import buttondevteam.lib.chat.Command2;
|
import buttondevteam.lib.chat.Command2;
|
||||||
import buttondevteam.lib.chat.Command2.Subcommand;
|
import buttondevteam.lib.chat.Command2.Subcommand;
|
||||||
|
@ -24,7 +25,10 @@ public class ComponentCommand extends ICommand2MC {
|
||||||
|
|
||||||
@Subcommand
|
@Subcommand
|
||||||
public boolean enable(CommandSender sender, Plugin plugin, String component) {
|
public boolean enable(CommandSender sender, Plugin plugin, String component) {
|
||||||
plugin.reloadConfig(); //Reload config so the new config values are read - All changes are saved to disk on disable
|
if (plugin instanceof ButtonPlugin)
|
||||||
|
((ButtonPlugin) plugin).justReload();
|
||||||
|
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);
|
return enable_disable(sender, plugin, component, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,10 @@ public final class ComponentManager {
|
||||||
/**
|
/**
|
||||||
* Unregister all components of a plugin that are enabled - called on {@link ButtonPlugin} disable
|
* Unregister all components of a plugin that are enabled - called on {@link ButtonPlugin} disable
|
||||||
*/
|
*/
|
||||||
public static void unregComponents(ButtonPlugin plugin) {
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T extends ButtonPlugin> void unregComponents(T plugin) {
|
||||||
while (!plugin.getComponentStack().empty()) //Unregister in reverse order
|
while (!plugin.getComponentStack().empty()) //Unregister in reverse order
|
||||||
Component.unregisterComponent(plugin, plugin.getComponentStack().pop()); //Components are pushed on register
|
Component.unregisterComponent(plugin, (Component<T>) plugin.getComponentStack().pop()); //Components are pushed on register
|
||||||
componentsEnabled = false;
|
componentsEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package buttondevteam.core;
|
||||||
|
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
@CommandClass
|
||||||
|
public class ThorpeCommand extends ICommand2MC {
|
||||||
|
@Command2.Subcommand //TODO: Main permissions (groups) like 'mod'
|
||||||
|
public void reload(CommandSender sender) {
|
||||||
|
MainPlugin.Instance.reloadConfig();
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,10 +20,10 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
||||||
@Getter(AccessLevel.PROTECTED)
|
@Getter(AccessLevel.PROTECTED)
|
||||||
private IHaveConfig data; //TODO
|
private IHaveConfig data; //TODO
|
||||||
/**
|
/**
|
||||||
* Used to unregister components in the right order
|
* Used to unregister components in the right order - and to reload configs
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
private Stack<Component> componentStack = new Stack<>();
|
private Stack<Component<?>> componentStack = new Stack<>();
|
||||||
|
|
||||||
protected abstract void pluginEnable();
|
protected abstract void pluginEnable();
|
||||||
|
|
||||||
|
@ -40,9 +40,7 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onEnable() {
|
public final void onEnable() {
|
||||||
var section = super.getConfig().getConfigurationSection("global");
|
loadConfig();
|
||||||
if (section == null) section = super.getConfig().createSection("global");
|
|
||||||
iConfig = new IHaveConfig(section, this::saveConfig);
|
|
||||||
try {
|
try {
|
||||||
pluginEnable();
|
pluginEnable();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -50,6 +48,12 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadConfig() {
|
||||||
|
var section = super.getConfig().getConfigurationSection("global");
|
||||||
|
if (section == null) section = super.getConfig().createSection("global");
|
||||||
|
iConfig = new IHaveConfig(section, this::saveConfig);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onDisable() {
|
public final void onDisable() {
|
||||||
try {
|
try {
|
||||||
|
@ -63,4 +67,19 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
||||||
TBMCCoreAPI.SendException("Error while disabling plugin " + getName() + "!", e);
|
TBMCCoreAPI.SendException("Error while disabling plugin " + getName() + "!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reloadConfig() {
|
||||||
|
justReload();
|
||||||
|
loadConfig();
|
||||||
|
componentStack.forEach(c -> Component.updateConfig(this, c));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void justReload() {
|
||||||
|
if (ConfigData.saveNow(getConfig())) {
|
||||||
|
getLogger().warning("Saved pending configuration changes to the file, didn't reload (try again).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
super.reloadConfig();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,7 @@ public abstract class Component<TP extends JavaPlugin> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void updateConfig(JavaPlugin plugin, Component component) {
|
public static void updateConfig(JavaPlugin plugin, Component component) {
|
||||||
if (plugin.getConfig() != null) { //Production
|
if (plugin.getConfig() != null) { //Production
|
||||||
var compconf = plugin.getConfig().getConfigurationSection("components");
|
var compconf = plugin.getConfig().getConfigurationSection("components");
|
||||||
if (compconf == null) compconf = plugin.getConfig().createSection("components");
|
if (compconf == null) compconf = plugin.getConfig().createSection("components");
|
||||||
|
@ -237,10 +237,10 @@ public abstract class Component<TP extends JavaPlugin> {
|
||||||
var cs=c.getConfigurationSection(key);
|
var cs=c.getConfigurationSection(key);
|
||||||
if(cs==null) cs=c.createSection(key);
|
if(cs==null) cs=c.createSection(key);
|
||||||
val res = cs.getValues(false).entrySet().stream().filter(e -> e.getValue() instanceof ConfigurationSection)
|
val res = cs.getValues(false).entrySet().stream().filter(e -> e.getValue() instanceof ConfigurationSection)
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, kv -> new IHaveConfig((ConfigurationSection) kv.getValue())));
|
.collect(Collectors.toMap(Map.Entry::getKey, kv -> new IHaveConfig((ConfigurationSection) kv.getValue(), getPlugin()::saveConfig)));
|
||||||
if (res.size() == 0) {
|
if (res.size() == 0) {
|
||||||
for (val entry : defaultProvider.entrySet()) {
|
for (val entry : defaultProvider.entrySet()) {
|
||||||
val conf = new IHaveConfig(cs.createSection(entry.getKey()));
|
val conf = new IHaveConfig(cs.createSection(entry.getKey()), getPlugin()::saveConfig);
|
||||||
entry.getValue().accept(conf);
|
entry.getValue().accept(conf);
|
||||||
res.put(entry.getKey(), conf);
|
res.put(entry.getKey(), conf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,12 @@ package buttondevteam.lib.architecture;
|
||||||
|
|
||||||
import buttondevteam.core.MainPlugin;
|
import buttondevteam.core.MainPlugin;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.configuration.Configuration;
|
import org.bukkit.configuration.Configuration;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
|
@ -23,7 +23,7 @@ import java.util.function.Function;
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
||||||
//@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
//@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
||||||
public class ConfigData<T> {
|
public class ConfigData<T> {
|
||||||
private static final HashMap<Configuration, BukkitTask> saveTasks= new HashMap<>();
|
private static final HashMap<Configuration, SaveTask> saveTasks = new HashMap<>();
|
||||||
/**
|
/**
|
||||||
* May be null for testing
|
* May be null for testing
|
||||||
*/
|
*/
|
||||||
|
@ -45,8 +45,12 @@ public class ConfigData<T> {
|
||||||
* The config value should not change outside this instance
|
* The config value should not change outside this instance
|
||||||
*/
|
*/
|
||||||
private T value;
|
private T value;
|
||||||
|
/**
|
||||||
|
* Whether the default value is saved in the yaml
|
||||||
|
*/
|
||||||
private boolean saved = false;
|
private boolean saved = false;
|
||||||
|
|
||||||
|
//This constructor is needed because it sets the getter and setter
|
||||||
public ConfigData(ConfigurationSection config, String path, T def, Object primitiveDef, Function<Object, T> getter, Function<T, Object> setter, Runnable saveAction) {
|
public ConfigData(ConfigurationSection config, String path, T def, Object primitiveDef, Function<Object, T> getter, Function<T, Object> setter, Runnable saveAction) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
|
@ -88,9 +92,9 @@ public class ConfigData<T> {
|
||||||
else if (def instanceof Double)
|
else if (def instanceof Double)
|
||||||
val = ((Number) val).doubleValue();
|
val = ((Number) val).doubleValue();
|
||||||
}
|
}
|
||||||
if (val instanceof List && def.getClass().isArray())
|
if (val instanceof List && def != null && def.getClass().isArray())
|
||||||
val = ((List<T>) val).toArray((T[]) Array.newInstance(def.getClass().getComponentType(), 0));
|
val = ((List<T>) val).toArray((T[]) Array.newInstance(def.getClass().getComponentType(), 0));
|
||||||
return (T) val;
|
return value = (T) val; //Always cache, if not cached yet
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(T value) {
|
public void set(T value) {
|
||||||
|
@ -102,15 +106,32 @@ public class ConfigData<T> {
|
||||||
config.set(path, val);
|
config.set(path, val);
|
||||||
if(!saveTasks.containsKey(config.getRoot())) {
|
if(!saveTasks.containsKey(config.getRoot())) {
|
||||||
synchronized (saveTasks) {
|
synchronized (saveTasks) {
|
||||||
saveTasks.put(config.getRoot(), Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.Instance, () -> {
|
saveTasks.put(config.getRoot(), new SaveTask(Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.Instance, () -> {
|
||||||
synchronized (saveTasks) {
|
synchronized (saveTasks) {
|
||||||
saveTasks.remove(config.getRoot());
|
saveTasks.remove(config.getRoot());
|
||||||
saveAction.run();
|
saveAction.run();
|
||||||
}
|
}
|
||||||
}, 100));
|
}, 100), saveAction));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
private static class SaveTask {
|
||||||
|
BukkitTask task;
|
||||||
|
Runnable saveAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,6 @@
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.21" level="project" />
|
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.21" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.21" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.21" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT" level="project" />
|
<orderEntry type="library" name="Maven: org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT" level="project" />
|
||||||
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
|
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
|
||||||
<orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
|
<orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
|
||||||
|
|
Loading…
Reference in a new issue