diff --git a/BuildConfigUpdater/BuildConfigUpdater.iml b/BuildConfigUpdater/BuildConfigUpdater.iml
index 04dfdc0..74e6815 100644
--- a/BuildConfigUpdater/BuildConfigUpdater.iml
+++ b/BuildConfigUpdater/BuildConfigUpdater.iml
@@ -19,6 +19,7 @@
+
diff --git a/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTP.java b/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTP.java
index 755a32a..6b44848 100644
--- a/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTP.java
+++ b/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTP.java
@@ -8,6 +8,8 @@ import org.bukkit.*;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
+import java.util.logging.Logger;
+
// @formatter:off
@SuppressWarnings("FieldCanBeLocal")@CommandClass
public class RandomTP extends TBMCCommandBase
@@ -53,15 +55,15 @@ public class RandomTP extends TBMCCommandBase
public void onEnable(Component component)
{
- System.out.println("Adding command");
TBMCChatAPI.AddCommand(component, this);
- System.out.println("Getting world");
world = Bukkit.getWorld("World");
- System.out.println("Getting border");
border = world.getWorldBorder();
- System.out.println("Getting new location");
- System.out.println("Success: "+newLocation()); //TODO: It takes 10-30 seconds to find a location (newLocation() was there)
+ Logger logger = component.getPlugin().getLogger();
+ logger.info("Getting new location");
+ if(border.getSize() > 100000)
+ logger.warning("World border is wide, it may take a minute...");
+ logger.info("Success: "+newLocation());
}
/*================================================================================================*/
diff --git a/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTPComponent.java b/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTPComponent.java
index 0f1fb5e..a31bef9 100644
--- a/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTPComponent.java
+++ b/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTPComponent.java
@@ -6,6 +6,7 @@ import buttondevteam.lib.architecture.Component;
/**
* Teleport player to random location within world border.
* Every five players teleport to the same general area, and then a new general area is randomly selected for the next five players.
+ * Author: github.com/iiegit
*/
public class RandomTPComponent extends Component {
@Override
diff --git a/ButtonCore/src/main/java/buttondevteam/core/component/spawn/SpawnComponent.java b/ButtonCore/src/main/java/buttondevteam/core/component/spawn/SpawnComponent.java
index 2dab750..7ad07aa 100644
--- a/ButtonCore/src/main/java/buttondevteam/core/component/spawn/SpawnComponent.java
+++ b/ButtonCore/src/main/java/buttondevteam/core/component/spawn/SpawnComponent.java
@@ -20,6 +20,9 @@ import org.bukkit.plugin.messaging.PluginMessageListener;
import java.io.*;
import java.math.BigDecimal;
+/**
+ * Provides a /spawn command that works with BungeeCord. Make sure to set up on each server.
+ */
public class SpawnComponent extends Component implements PluginMessageListener {
@Override
protected void enable() {
@@ -72,7 +75,7 @@ public class SpawnComponent extends Component implements PluginMessa
}
/**
- * Set to empty if this server is the target.
+ * The BungeeCord server that has the spawn. Set to empty if this server is the target.
*/
private ConfigData targetServer() {
return getConfig().getData("targetServer", "");
diff --git a/ButtonCore/src/main/java/buttondevteam/core/component/votifier/VotifierComponent.java b/ButtonCore/src/main/java/buttondevteam/core/component/votifier/VotifierComponent.java
index 94ffe55..3eff08d 100644
--- a/ButtonCore/src/main/java/buttondevteam/core/component/votifier/VotifierComponent.java
+++ b/ButtonCore/src/main/java/buttondevteam/core/component/votifier/VotifierComponent.java
@@ -39,11 +39,11 @@ public class VotifierComponent extends Component {
getPlugin().getLogger().info("Vote: " + vote);
org.bukkit.OfflinePlayer op = Bukkit.getOfflinePlayer(vote.getUsername());
Player p = Bukkit.getPlayer(vote.getUsername());
- if (op != null) {
+ /*if (op != null) {
economy.depositPlayer(op, rewardAmount().get());
}
if (p != null) {
p.sendMessage("§bThanks for voting! $50 was added to your account.");
- }
+ }*/
}
}
diff --git a/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java b/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java
index d22f192..d32fa13 100644
--- a/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java
+++ b/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java
@@ -6,12 +6,16 @@ import buttondevteam.lib.chat.Command2MC;
import buttondevteam.lib.chat.TBMCChatAPI;
import lombok.AccessLevel;
import lombok.Getter;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
+import java.io.File;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.util.Arrays;
import java.util.Optional;
import java.util.Stack;
@@ -21,14 +25,15 @@ public abstract class ButtonPlugin extends JavaPlugin {
private static Command2MC command2MC = new Command2MC();
@Getter(AccessLevel.PROTECTED)
private IHaveConfig iConfig;
+ private CommentedConfiguration yaml;
@Getter(AccessLevel.PROTECTED)
private IHaveConfig data; //TODO
- private boolean loaded = false;
/**
* Used to unregister components in the right order - and to reload configs
*/
@Getter
private Stack> componentStack = new Stack<>();
+ ;
protected abstract void pluginEnable();
@@ -56,8 +61,8 @@ public abstract class ButtonPlugin extends JavaPlugin {
}
private void loadConfig() {
- var section = super.getConfig().getConfigurationSection("global");
- if (section == null) section = super.getConfig().createSection("global");
+ var section = getConfig().getConfigurationSection("global");
+ if (section == null) section = getConfig().createSection("global");
iConfig = new IHaveConfig(section, this::saveConfig);
}
@@ -88,15 +93,37 @@ public abstract class ButtonPlugin extends JavaPlugin {
}
public boolean justReload() {
- if (loaded && ConfigData.saveNow(getConfig())) {
+ if (yaml != null && ConfigData.saveNow(getConfig())) {
getLogger().warning("Saved pending configuration changes to the file, didn't reload (try again).");
return false;
}
- super.reloadConfig();
- loaded = true; //Needed because for the first time it uses reloadConfig() to load it
+ yaml = new CommentedConfiguration(new File(getDataFolder(), "config.yml"));
+ yaml.load();
+ 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));
return true;
}
+ @Override
+ public FileConfiguration getConfig() {
+ if (yaml == null)
+ justReload();
+ return yaml;
+ }
+
+ @Override
+ public void saveConfig() {
+ if (yaml != null)
+ yaml.save();
+ }
+
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ConfigOpts {
diff --git a/ButtonCore/src/main/java/buttondevteam/lib/architecture/CommentedConfiguration.java b/ButtonCore/src/main/java/buttondevteam/lib/architecture/CommentedConfiguration.java
new file mode 100644
index 0000000..f7351ff
--- /dev/null
+++ b/ButtonCore/src/main/java/buttondevteam/lib/architecture/CommentedConfiguration.java
@@ -0,0 +1,227 @@
+package buttondevteam.lib.architecture;
+
+import com.palmergames.util.FileMgmt;
+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.util.HashMap;
+
+/**
+ * A copy of Towny's CommentedConfiguration: https://github.com/TownyAdvanced/Towny/blob/master/src/com/palmergames/bukkit/config/CommentedConfiguration.java
+ *
+ * @author dumptruckman & Articdive
+ */
+public class CommentedConfiguration extends YamlConfiguration { //TODO: Remove FileMgmt dependency
+ 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() {
+
+ 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 = FileMgmt.convertFileToString(file).split("[" + System.getProperty("line.separator") + "]");
+
+ // 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"), ""));
+ }
+ FileMgmt.stringToFile(newContents.toString(), file);
+ }
+ }
+
+ /**
+ * 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/ButtonCore/src/main/java/buttondevteam/lib/architecture/ConfigData.java b/ButtonCore/src/main/java/buttondevteam/lib/architecture/ConfigData.java
index 32221ad..c9f0887 100644
--- a/ButtonCore/src/main/java/buttondevteam/lib/architecture/ConfigData.java
+++ b/ButtonCore/src/main/java/buttondevteam/lib/architecture/ConfigData.java
@@ -83,8 +83,8 @@ public class ConfigData {
Object val;
if (config == null || !config.isSet(path)) { //Call set() if config == null
val = primitiveDef;
- if (def == null && config != null) //In Discord's case def may be null
- setInternal(primitiveDef);
+ if ((def == null || this instanceof 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
} else
diff --git a/ButtonProcessor/src/main/java/buttondevteam/buttonproc/ConfigProcessor.java b/ButtonProcessor/src/main/java/buttondevteam/buttonproc/ConfigProcessor.java
index c06169a..6d82808 100644
--- a/ButtonProcessor/src/main/java/buttondevteam/buttonproc/ConfigProcessor.java
+++ b/ButtonProcessor/src/main/java/buttondevteam/buttonproc/ConfigProcessor.java
@@ -1,5 +1,8 @@
package buttondevteam.buttonproc;
+import org.bukkit.configuration.InvalidConfigurationException;
+import org.bukkit.configuration.file.YamlConfiguration;
+
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
@@ -10,29 +13,35 @@ import javax.lang.model.type.TypeMirror;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
import java.io.File;
-import java.io.FileWriter;
import java.io.IOException;
public class ConfigProcessor {
private final ProcessingEnvironment procEnv;
- private final FileWriter sw;
+ private final YamlConfiguration yc = new YamlConfiguration();
+ private final FileObject fo;
public ConfigProcessor(ProcessingEnvironment procEnv) {
+ FileObject fo1;
this.procEnv = procEnv;
- FileWriter sw = null;
try {
- FileObject file = procEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", "configHelp.md");
- sw = new FileWriter(new File(file.toUri()));
- System.out.println(file.toUri());
+ fo1 = procEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", "configHelp.yml");
} catch (IOException e) {
e.printStackTrace();
+ fo1 = null;
}
- this.sw = sw;
+ this.fo = fo1;
}
public void process(Element targetcl) {
if (targetcl.getModifiers().contains(Modifier.ABSTRACT)) return;
final String path = "components." + targetcl.getSimpleName();
+ File file = new File(fo.toUri());
+ try {
+ if (file.exists())
+ yc.load(file);
+ } catch (IOException | InvalidConfigurationException e) {
+ e.printStackTrace();
+ }
for (Element e : targetcl.getEnclosedElements()) {
/*System.out.println("Element: "+e);
System.out.println("Type: "+e.getClass()+" - "+e.getKind());
@@ -49,30 +58,18 @@ public class ConfigProcessor {
String doc = procEnv.getElementUtils().getDocComment(e);
if (doc == null) continue;
System.out.println("DOC: " + doc);
- try {
- sw.append(path).append(".").append(String.valueOf(e.getSimpleName())).append(System.lineSeparator()).append(System.lineSeparator());
- sw.append(doc.trim()).append(System.lineSeparator()).append(System.lineSeparator());
- } catch (IOException e1) {
- e1.printStackTrace();
- }
+ yc.set(path + "." + e.getSimpleName(), doc.trim());
}
String javadoc = procEnv.getElementUtils().getDocComment(targetcl);
+ if (javadoc != null) {
+ System.out.println("JAVADOC");
+ System.out.println(javadoc.trim());
+ yc.set(path, javadoc.trim());
+ }
try {
- if (javadoc != null) {
- System.out.println("JAVADOC");
- System.out.println(javadoc.trim());
- sw.append(path).append(System.lineSeparator()).append(System.lineSeparator());
- sw.append(javadoc).append(System.lineSeparator()).append(System.lineSeparator());
- }
- sw.flush();
+ yc.save(file);
} catch (IOException e) {
e.printStackTrace();
}
}
-
- @Override
- protected void finalize() throws Throwable {
- sw.close();
- super.finalize();
- }
}