diff --git a/Chroma-Core/pom.xml b/Chroma-Core/pom.xml
index 1a3e21d..219be89 100755
--- a/Chroma-Core/pom.xml
+++ b/Chroma-Core/pom.xml
@@ -169,7 +169,7 @@
org.spigotmcspigot-api
- 1.12.2-R0.1-SNAPSHOT
+ 1.18.1-R0.1-SNAPSHOTprovided
diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.kt b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.kt
index dafa73e..8673bde 100644
--- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.kt
+++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.kt
@@ -18,7 +18,7 @@ import java.util.function.Consumer
@HasConfig(global = true)
abstract class ButtonPlugin : JavaPlugin() {
protected val iConfig = IHaveConfig { saveConfig() }
- private var yaml: CommentedConfiguration? = null
+ private var yaml: YamlConfiguration? = null
protected val data //TODO
: IHaveConfig? = null
@@ -39,7 +39,7 @@ abstract class ButtonPlugin : JavaPlugin() {
*/
protected fun pluginPreDisable() {}
override fun onEnable() {
- if (!loadConfig()) {
+ if (!reloadIConfig()) {
logger.warning("Please fix the issues and restart the server to load the plugin.")
return
}
@@ -52,12 +52,12 @@ abstract class ButtonPlugin : JavaPlugin() {
IHaveConfig.pregenConfig(this, null)
}
- private fun loadConfig(): Boolean {
- val config = config ?: return false
+ private fun reloadIConfig(): Boolean {
+ val config = config
var section = config.getConfigurationSection("global")
if (section == null) section = config.createSection("global")
iConfig.reset(section)
- return true
+ return configLoaded // If loading fails, getConfig() returns a temporary instance
}
override fun onDisable() {
@@ -78,7 +78,7 @@ abstract class ButtonPlugin : JavaPlugin() {
fun tryReloadConfig(): Boolean {
if (!justReload()) return false
- loadConfig()
+ reloadIConfig()
componentStack.forEach(Consumer { c: Component<*>? -> updateConfig(this, c!!) })
return true
}
@@ -89,7 +89,7 @@ abstract class ButtonPlugin : JavaPlugin() {
return false
}
val file = File(dataFolder, "config.yml")
- val yaml = CommentedConfiguration(file)
+ val yaml = YamlConfiguration()
if (file.exists()) {
try {
yaml.load(file)
@@ -102,16 +102,17 @@ abstract class ButtonPlugin : JavaPlugin() {
e.printStackTrace()
return false
}
+ this.yaml = yaml
+ } else {
+ return false
}
- this.yaml = yaml
val res = getTextResource("configHelp.yml") ?: return true
val yc = YamlConfiguration.loadConfiguration(res)
- for ((key, value) in yc.getValues(true)) if (value is String) yaml.addComment(key.replace(
- ".generalDescriptionInsteadOfAConfig",
- ""
- ),
- *value.split("\n").map { str -> "# " + str.trim { it <= ' ' } }.toTypedArray()
- )
+ for ((key, value) in yc.getValues(true))
+ if (value is String) yaml.setComments(
+ key.replace(".generalDescriptionInsteadOfAConfig", ""),
+ value.split("\n").map { str -> "# " + str.trim { it <= ' ' } }
+ )
return true
}
@@ -121,13 +122,11 @@ abstract class ButtonPlugin : JavaPlugin() {
}
override fun saveConfig() {
- try {
- if (yaml != null) yaml!!.save()
- } catch (e: Exception) {
- TBMCCoreAPI.SendException("Failed to save config", e, this)
- }
+ if (configLoaded) super.saveConfig()
}
+ val configLoaded get() = yaml != null
+
/**
* Registers command and sets its plugin.
*
diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/CommentedConfiguration.java b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/CommentedConfiguration.java
deleted file mode 100644
index d3ee07a..0000000
--- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/CommentedConfiguration.java
+++ /dev/null
@@ -1,229 +0,0 @@
-package buttondevteam.lib.architecture;
-
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.configuration.file.YamlConstructor;
-import org.bukkit.configuration.file.YamlRepresenter;
-import org.yaml.snakeyaml.DumperOptions;
-import org.yaml.snakeyaml.Yaml;
-import org.yaml.snakeyaml.representer.Representer;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.util.HashMap;
-
-/**
- * A copy of Towny's CommentedConfiguration: https://github.com/TownyAdvanced/Towny/blob/master/src/com/palmergames/bukkit/config/CommentedConfiguration.java
- * Modified to remove dependency on the FileMgmt class
- *
- * @author dumptruckman & Articdive
- */
-public class CommentedConfiguration extends YamlConfiguration {
- private HashMap comments;
- private File file;
-
- private final DumperOptions yamlOptions = new DumperOptions();
- private final Representer yamlRepresenter = new YamlRepresenter();
- private final Yaml yaml = new Yaml(new YamlConstructor(), yamlRepresenter, yamlOptions);
-
- public CommentedConfiguration(File file) {
-
- super();
- comments = new HashMap<>();
- this.file = file;
- }
-
- public boolean load() {
-
- boolean loaded = true;
-
- try {
- this.load(file);
- } catch (InvalidConfigurationException | IOException e) {
- loaded = false;
- }
-
- return loaded;
- }
-
- public void save() throws IOException {
-
- boolean saved = true;
-
- // Save the config just like normal
- try {
- this.save(file);
-
- } catch (Exception e) {
- saved = false;
- }
-
- // if there's comments to add and it saved fine, we need to add comments
- if (!comments.isEmpty() && saved) {
- // String array of each line in the config file
- String[] yamlContents = Files.readAllLines(file.toPath()).toArray(new String[0]);
-
- // This will hold the newly formatted line
- StringBuilder newContents = new StringBuilder();
- // This holds the current path the lines are at in the config
- String currentPath = "";
- // This flags if the line is a node or unknown text.
- boolean node;
- // The depth of the path. (number of words separated by periods - 1)
- int depth = 0;
-
- // Loop through the config lines
- for (String line : yamlContents) {
- // If the line is a node (and not something like a list value)
- if (line.contains(": ") || (line.length() > 1 && line.charAt(line.length() - 1) == ':')) {
-
- // This is a node so flag it as one
- node = true;
-
- // Grab the index of the end of the node name
- int index;
- index = line.indexOf(": ");
- if (index < 0) {
- index = line.length() - 1;
- }
- // If currentPath is empty, store the node name as the currentPath. (this is only on the first iteration, i think)
- if (currentPath.isEmpty()) {
- currentPath = line.substring(0, index);
- } else {
- // Calculate the whitespace preceding the node name
- int whiteSpace = 0;
- for (int n = 0; n < line.length(); n++) {
- if (line.charAt(n) == ' ') {
- whiteSpace++;
- } else {
- break;
- }
- }
- // Find out if the current depth (whitespace * 2) is greater/lesser/equal to the previous depth
- if (whiteSpace / 2 > depth) {
- // Path is deeper. Add a . and the node name
- currentPath += "." + line.substring(whiteSpace, index);
- depth++;
- } else if (whiteSpace / 2 < depth) {
- // Path is shallower, calculate current depth from whitespace (whitespace / 2) and subtract that many levels from the currentPath
- int newDepth = whiteSpace / 2;
- for (int i = 0; i < depth - newDepth; i++) {
- currentPath = currentPath.replace(currentPath.substring(currentPath.lastIndexOf(".")), "");
- }
- // Grab the index of the final period
- int lastIndex = currentPath.lastIndexOf(".");
- if (lastIndex < 0) {
- // if there isn't a final period, set the current path to nothing because we're at root
- currentPath = "";
- } else {
- // If there is a final period, replace everything after it with nothing
- currentPath = currentPath.replace(currentPath.substring(currentPath.lastIndexOf(".")), "");
- currentPath += ".";
- }
- // Add the new node name to the path
- currentPath += line.substring(whiteSpace, index);
- // Reset the depth
- depth = newDepth;
- } else {
- // Path is same depth, replace the last path node name to the current node name
- int lastIndex = currentPath.lastIndexOf(".");
- if (lastIndex < 0) {
- // if there isn't a final period, set the current path to nothing because we're at root
- currentPath = "";
- } else {
- // If there is a final period, replace everything after it with nothing
- currentPath = currentPath.replace(currentPath.substring(currentPath.lastIndexOf(".")), "");
- currentPath += ".";
- }
- //currentPath = currentPath.replace(currentPath.substring(currentPath.lastIndexOf(".")), "");
- currentPath += line.substring(whiteSpace, index);
-
- }
-
- }
-
- } else {
- node = false;
- }
-
- if (node) {
- // If there's a comment for the current path, retrieve it and flag that path as already commented
- String comment = comments.get(currentPath);
-
- if (comment != null) {
- // Add the comment to the beginning of the current line
- line = comment + System.getProperty("line.separator") + line + System.getProperty("line.separator");
- } else {
- // Add a new line as it is a node, but has no comment
- line += System.getProperty("line.separator");
- }
- }
- // Add the (modified) line to the total config String
- if (!node) {
- newContents.append(line).append(System.getProperty("line.separator"));
- } else {
- newContents.append(line);
- }
- }
-
- /*
- * Due to a Bukkit Bug with the Configuration
- * we just need to remove any extra comments at the start of a file.
- */
- while (newContents.toString().startsWith(" " + System.getProperty("line.separator"))) {
- newContents = new StringBuilder(newContents.toString().replaceFirst(" " + System.getProperty("line.separator"), ""));
- }
- Files.write(file.toPath(), newContents.toString().getBytes(StandardCharsets.UTF_8));
- }
- }
-
- /**
- * Adds a comment just before the specified path. The comment can be
- * multiple lines. An empty string will indicate a blank line.
- *
- * @param path Configuration path to add comment.
- * @param commentLines Comments to add. One String per line.
- */
- public void addComment(String path, String... commentLines) {
-
- StringBuilder commentstring = new StringBuilder();
- StringBuilder leadingSpaces = new StringBuilder();
- for (int n = 0; n < path.length(); n++) {
- if (path.charAt(n) == '.') {
- leadingSpaces.append(" ");
- }
- }
- for (String line : commentLines) {
- if (!line.isEmpty()) {
- line = leadingSpaces + line;
- } else {
- line = " ";
- }
- if (commentstring.length() > 0) {
- commentstring.append(System.getProperty("line.separator"));
- }
- commentstring.append(line);
- }
- comments.put(path, commentstring.toString());
- }
-
- @Override
- public String saveToString() {
- yamlOptions.setIndent(options().indent());
- yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
- yamlOptions.setWidth(10000);
- yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
-
-
- String dump = yaml.dump(getValues(false));
-
-
- if (dump.equals(BLANK_CONFIG)) {
- dump = "";
- }
-
- return dump;
- }
-}
diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt
index 20a72e7..0bfa5d8 100644
--- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt
+++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt
@@ -6,7 +6,6 @@ import lombok.*
import org.bukkit.Bukkit
import org.bukkit.configuration.Configuration
import org.bukkit.scheduler.BukkitTask
-import java.util.function.BiFunction
import java.util.function.Function
/**
@@ -21,10 +20,10 @@ open class ConfigData internal constructor(
val path: String,
def: T?,
primitiveDef: Any?,
- private val getter: Function?,
- private val setter: Function?
+ private val getter: Function,
+ private val setter: Function
) {
- private val def: Any?
+ private val pdef: Any?
/**
* The config value should not change outside this instance
@@ -32,9 +31,8 @@ open class ConfigData internal constructor(
private var value: T? = null
init {
- this.def = primitiveDef ?: def?.let { setter?.apply(it) }
+ this.pdef = primitiveDef ?: def?.let { setter.apply(it) }
?: throw IllegalArgumentException("Either def or primitiveDef must be set. A getter and setter must be present when using primitiveDef.")
- require(getter == null == (setter == null)) { "Both setters and getters must be present (or none if def is primitive)." }
get() //Generate config automatically
}
@@ -50,67 +48,46 @@ open class ConfigData internal constructor(
if (value != null) return value //Speed things up
val config = config?.config
var `val`: Any?
- if (config == null || !config.isSet(path)) { //Call set() if config == null
- `val` = primitiveDef // TODO: primitiveDef --> def, def --> getter(primitiveDef)
- if ((def == null || this is ReadOnlyConfigData<*>) && config != null) //In Discord's case def may be null
- setInternal(primitiveDef) //If read-only then we still need to save the default value so it can be set
- else set(def) //Save default value - def is always set
+ if (config == null || !config.isSet(path)) {
+ `val` = pdef
+ setInternal(pdef) // Save default value even if read-only
} else `val` = config.get(path) //config==null: testing
if (`val` == null) //If it's set to null explicitly
- `val` = primitiveDef
- val convert = BiFunction { _val: Any?, _def: Any? ->
- if (_def is Number) //If we expect a number
- _val = if (_val is Number) ChromaUtils.convertNumber(
- _val as Number?,
- _def.javaClass as Class
- ) else _def //If we didn't get a number, return default (which is a number)
- else if (_val is List<*> && _def != null && _def.javaClass.isArray) _val = (_val as List).toArray(
- java.lang.reflect.Array.newInstance(
- _def.javaClass.componentType,
- 0
- ) as Array
- )
- _val
- }
- if (getter != null) {
- `val` = convert.apply(`val`, primitiveDef)
- var hmm: T? = getter.apply(`val`)
- if (hmm == null) hmm = def //Set if the getter returned null
- return hmm
- }
- `val` = convert.apply(`val`, def)
- return `val` as T?. also {
- value = it //Always cache, if not cached yet
+ `val` = pdef
+ fun convert(_val: Any?, _pdef: Any?): Any? {
+ return if (_pdef is Number) //If we expect a number
+ if (_val is Number)
+ ChromaUtils.convertNumber(_val as Number?, _pdef.javaClass as Class)
+ else _pdef //If we didn't get a number, return default (which is a number)
+ else if (_val is List<*> && _pdef != null && _pdef.javaClass.isArray)
+ _val.toTypedArray()
+ else _val
}
+ return getter.apply(convert(`val`, pdef)).also { value = it }
}
fun set(value: T?) {
if (this is ReadOnlyConfigData<*>) return //Safety for Discord channel/role data
- val `val`: Any?
- `val` = if (setter != null && value != null) setter.apply(value) else value
- if (config!!.getConfig() != null) setInternal(`val`)
+ val `val` = value?.let { setter.apply(value) }
+ setInternal(`val`)
this.value = value
}
private fun setInternal(`val`: Any?) {
- config!!.getConfig().set(path, `val`)
+ if (config == null) return
+ config.config.set(path, `val`)
signalChange(config)
}
- @AllArgsConstructor
- private class SaveTask {
- var task: BukkitTask? = null
- var saveAction: Runnable? = null
- }
+ private class SaveTask(val task: BukkitTask, val saveAction: Runnable)
- @RequiredArgsConstructor(access = AccessLevel.PACKAGE)
- class ConfigDataBuilder {
- private val config: IHaveConfig? = null
- private val path: String? = null
+ class ConfigDataBuilder internal constructor(private val config: IHaveConfig, private val path: String) {
private var def: T? = null
private var primitiveDef: Any? = null
- private var getter: Function? = null
- private var setter: Function? = null
+
+ @Suppress("UNCHECKED_CAST")
+ private var getter: Function = Function { it as T }
+ private var setter: Function = Function { it }
/**
* The default value to use, as used in code. If not a primitive type, use the [.getter] and [.setter] methods.
@@ -145,7 +122,7 @@ open class ConfigData internal constructor(
* @param getter A function that receives the primitive type and returns the runtime type
* @return This builder
*/
- fun getter(getter: Function?): ConfigDataBuilder {
+ fun getter(getter: Function): ConfigDataBuilder {
this.getter = getter
return this
}
@@ -157,7 +134,7 @@ open class ConfigData internal constructor(
* @param setter A function that receives the runtime type and returns the primitive type
* @return This builder
*/
- fun setter(setter: Function?): ConfigDataBuilder {
+ fun setter(setter: Function): ConfigDataBuilder {
this.setter = setter
return this
}
@@ -167,9 +144,9 @@ open class ConfigData internal constructor(
*
* @return A ConfigData instance.
*/
- fun build(): ConfigData {
+ fun build(): ConfigData {
val config = ConfigData(config, path, def, primitiveDef, getter, setter)
- this.config!!.onConfigBuild(config)
+ this.config.onConfigBuild(config)
return config
}
@@ -178,26 +155,26 @@ open class ConfigData internal constructor(
*
* @return A ReadOnlyConfigData instance.
*/
- fun buildReadOnly(): ReadOnlyConfigData {
+ fun buildReadOnly(): ReadOnlyConfigData {
val config = ReadOnlyConfigData(config, path, def, primitiveDef, getter, setter)
- this.config!!.onConfigBuild(config)
+ this.config.onConfigBuild(config)
return config
}
override fun toString(): String {
- return "ConfigData.ConfigDataBuilder(config=" + config + ", path=" + path + ", def=" + def + ", primitiveDef=" + primitiveDef + ", getter=" + getter + ", setter=" + setter + ")"
+ return "ConfigData.ConfigDataBuilder(config=$config, path=$path, def=$def, primitiveDef=$primitiveDef, getter=$getter, setter=$setter)"
}
}
companion object {
private val saveTasks = HashMap()
- fun signalChange(config: IHaveConfig?) {
- val cc = config!!.getConfig()
+ fun signalChange(config: IHaveConfig) {
+ val cc = config.config
val sa = config.saveAction
- if (!saveTasks.containsKey(cc.getRoot())) {
+ if (!saveTasks.containsKey(cc.root)) {
synchronized(saveTasks) {
saveTasks.put(
- cc.getRoot(),
+ cc.root,
SaveTask(Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.Instance, {
synchronized(
saveTasks
@@ -216,16 +193,16 @@ open class ConfigData internal constructor(
synchronized(saveTasks) {
val st = saveTasks[config]
if (st != null) {
- st.task!!.cancel()
+ st.task.cancel()
saveTasks.remove(config)
- st.saveAction!!.run()
+ st.saveAction.run()
return true
}
}
return false
}
- fun builder(config: IHaveConfig?, path: String?): ConfigDataBuilder {
+ fun builder(config: IHaveConfig, path: String): ConfigDataBuilder {
return ConfigDataBuilder(config, path)
}
}
diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ReadOnlyConfigData.kt b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ReadOnlyConfigData.kt
index fcc2b6e..9fb4bd6 100644
--- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ReadOnlyConfigData.kt
+++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ReadOnlyConfigData.kt
@@ -1,13 +1,12 @@
-package buttondevteam.lib.architecture;
+package buttondevteam.lib.architecture
-import java.util.function.Function;
+import java.util.function.Function
-public class ReadOnlyConfigData extends ConfigData {
- ReadOnlyConfigData(IHaveConfig config, String path, T def, Object primitiveDef, Function