callable) {
+ super(chartId);
+ this.callable = callable;
+ }
+
+ @Override
+ protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
+ int value = callable.call();
+ if (value == 0) {
+ // Null = skip the chart
+ return null;
+ }
+ return new JsonObjectBuilder().appendField("value", value).build();
+ }
+ }
+
+ /**
+ * An extremely simple JSON builder.
+ *
+ * While this class is neither feature-rich nor the most performant one, it's sufficient enough
+ * for its use-case.
+ */
+ public static class JsonObjectBuilder {
+
+ private StringBuilder builder = new StringBuilder();
+
+ private boolean hasAtLeastOneField = false;
+
+ public JsonObjectBuilder() {
+ builder.append("{");
+ }
+
+ /**
+ * Appends a null field to the JSON.
+ *
+ * @param key The key of the field.
+ * @return A reference to this object.
+ */
+ public JsonObjectBuilder appendNull(String key) {
+ appendFieldUnescaped(key, "null");
+ return this;
+ }
+
+ /**
+ * Appends a string field to the JSON.
+ *
+ * @param key The key of the field.
+ * @param value The value of the field.
+ * @return A reference to this object.
+ */
+ public JsonObjectBuilder appendField(String key, String value) {
+ if (value == null) {
+ throw new IllegalArgumentException("JSON value must not be null");
+ }
+ appendFieldUnescaped(key, "\"" + escape(value) + "\"");
+ return this;
+ }
+
+ /**
+ * Appends an integer field to the JSON.
+ *
+ * @param key The key of the field.
+ * @param value The value of the field.
+ * @return A reference to this object.
+ */
+ public JsonObjectBuilder appendField(String key, int value) {
+ appendFieldUnescaped(key, String.valueOf(value));
+ return this;
+ }
+
+ /**
+ * Appends an object to the JSON.
+ *
+ * @param key The key of the field.
+ * @param object The object.
+ * @return A reference to this object.
+ */
+ public JsonObjectBuilder appendField(String key, JsonObject object) {
+ if (object == null) {
+ throw new IllegalArgumentException("JSON object must not be null");
+ }
+ appendFieldUnescaped(key, object.toString());
+ return this;
+ }
+
+ /**
+ * Appends a string array to the JSON.
+ *
+ * @param key The key of the field.
+ * @param values The string array.
+ * @return A reference to this object.
+ */
+ public JsonObjectBuilder appendField(String key, String[] values) {
+ if (values == null) {
+ throw new IllegalArgumentException("JSON values must not be null");
+ }
+ String escapedValues =
+ Arrays.stream(values)
+ .map(value -> "\"" + escape(value) + "\"")
+ .collect(Collectors.joining(","));
+ appendFieldUnescaped(key, "[" + escapedValues + "]");
+ return this;
+ }
+
+ /**
+ * Appends an integer array to the JSON.
+ *
+ * @param key The key of the field.
+ * @param values The integer array.
+ * @return A reference to this object.
+ */
+ public JsonObjectBuilder appendField(String key, int[] values) {
+ if (values == null) {
+ throw new IllegalArgumentException("JSON values must not be null");
+ }
+ String escapedValues =
+ Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(","));
+ appendFieldUnescaped(key, "[" + escapedValues + "]");
+ return this;
+ }
+
+ /**
+ * Appends an object array to the JSON.
+ *
+ * @param key The key of the field.
+ * @param values The integer array.
+ * @return A reference to this object.
+ */
+ public JsonObjectBuilder appendField(String key, JsonObject[] values) {
+ if (values == null) {
+ throw new IllegalArgumentException("JSON values must not be null");
+ }
+ String escapedValues =
+ Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(","));
+ appendFieldUnescaped(key, "[" + escapedValues + "]");
+ return this;
+ }
+
+ /**
+ * Appends a field to the object.
+ *
+ * @param key The key of the field.
+ * @param escapedValue The escaped value of the field.
+ */
+ private void appendFieldUnescaped(String key, String escapedValue) {
+ if (builder == null) {
+ throw new IllegalStateException("JSON has already been built");
+ }
+ if (key == null) {
+ throw new IllegalArgumentException("JSON key must not be null");
+ }
+ if (hasAtLeastOneField) {
+ builder.append(",");
+ }
+ builder.append("\"").append(escape(key)).append("\":").append(escapedValue);
+ hasAtLeastOneField = true;
+ }
+
+ /**
+ * Builds the JSON string and invalidates this builder.
+ *
+ * @return The built JSON string.
+ */
+ public JsonObject build() {
+ if (builder == null) {
+ throw new IllegalStateException("JSON has already been built");
+ }
+ JsonObject object = new JsonObject(builder.append("}").toString());
+ builder = null;
+ return object;
+ }
+
+ /**
+ * Escapes the given string like stated in https://www.ietf.org/rfc/rfc4627.txt.
+ *
+ *
This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'.
+ * Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as "\n").
+ *
+ * @param value The value to escape.
+ * @return The escaped value.
+ */
+ private static String escape(String value) {
+ final StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+ if (c == '"') {
+ builder.append("\\\"");
+ } else if (c == '\\') {
+ builder.append("\\\\");
+ } else if (c <= '\u000F') {
+ builder.append("\\u000").append(Integer.toHexString(c));
+ } else if (c <= '\u001F') {
+ builder.append("\\u00").append(Integer.toHexString(c));
+ } else {
+ builder.append(c);
+ }
+ }
+ return builder.toString();
+ }
+
+ /**
+ * A super simple representation of a JSON object.
+ *
+ *
This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not
+ * allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String,
+ * JsonObject)}.
+ */
+ public static class JsonObject {
+
+ private final String value;
+
+ private JsonObject(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+ }
+ }
+}
diff --git a/src/main/java/site/deercloud/liteworldedit/Notification.java b/src/main/java/cn/lunadeer/liteworldedit/Notification.java
similarity index 90%
rename from src/main/java/site/deercloud/liteworldedit/Notification.java
rename to src/main/java/cn/lunadeer/liteworldedit/Notification.java
index cbdb722..af177b0 100644
--- a/src/main/java/site/deercloud/liteworldedit/Notification.java
+++ b/src/main/java/cn/lunadeer/liteworldedit/Notification.java
@@ -1,4 +1,4 @@
-package site.deercloud.liteworldedit;
+package cn.lunadeer.liteworldedit;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.Style;
@@ -7,8 +7,6 @@ import net.kyori.adventure.title.Title;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
-import static site.deercloud.liteworldedit.LoggerX.debug;
-
public class Notification {
private static final Style i_style = Style.style(TextColor.color(139, 255, 123));
private static final Style w_style = Style.style(TextColor.color(255, 185, 69));
@@ -43,19 +41,19 @@ public class Notification {
public static void info(Player player, Component msg) {
player.sendMessage(Component.text(prefix, i_style).append(msg));
if (LiteWorldEdit.config.isDebug())
- debug("来自玩家[ " + player.getName() + " ] 的提示 | " + msg);
+ LoggerX.debug("来自玩家[ " + player.getName() + " ] 的提示 | " + msg);
}
public static void warn(Player player, Component msg) {
player.sendMessage(Component.text(prefix, w_style).append(msg));
if (LiteWorldEdit.config.isDebug())
- debug("来自玩家[ " + player.getName() + " ] 的警告 | " + msg);
+ LoggerX.debug("来自玩家[ " + player.getName() + " ] 的警告 | " + msg);
}
public static void error(Player player, Component msg) {
player.sendMessage(Component.text(prefix, e_style).append(msg));
if (LiteWorldEdit.config.isDebug())
- debug("来自玩家[ " + player.getName() + " ] 的报错 | " + msg);
+ LoggerX.debug("来自玩家[ " + player.getName() + " ] 的报错 | " + msg);
}
public static void info(CommandSender player, Component msg) {
diff --git a/src/main/java/site/deercloud/liteworldedit/SchedulerUtil.java b/src/main/java/cn/lunadeer/liteworldedit/SchedulerUtil.java
similarity index 96%
rename from src/main/java/site/deercloud/liteworldedit/SchedulerUtil.java
rename to src/main/java/cn/lunadeer/liteworldedit/SchedulerUtil.java
index 0f9f493..6c7f49a 100644
--- a/src/main/java/site/deercloud/liteworldedit/SchedulerUtil.java
+++ b/src/main/java/cn/lunadeer/liteworldedit/SchedulerUtil.java
@@ -1,4 +1,4 @@
-package site.deercloud.liteworldedit;
+package cn.lunadeer.liteworldedit;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
diff --git a/src/main/java/site/deercloud/liteworldedit/Task.java b/src/main/java/cn/lunadeer/liteworldedit/Task.java
similarity index 92%
rename from src/main/java/site/deercloud/liteworldedit/Task.java
rename to src/main/java/cn/lunadeer/liteworldedit/Task.java
index cfe1433..9a46f12 100644
--- a/src/main/java/site/deercloud/liteworldedit/Task.java
+++ b/src/main/java/cn/lunadeer/liteworldedit/Task.java
@@ -1,8 +1,8 @@
-package site.deercloud.liteworldedit;
+package cn.lunadeer.liteworldedit;
+import cn.lunadeer.liteworldedit.Jobs.Job;
+import cn.lunadeer.liteworldedit.Jobs.JobErrCode;
import org.bukkit.entity.Player;
-import site.deercloud.liteworldedit.Jobs.Job;
-import site.deercloud.liteworldedit.Jobs.JobErrCode;
public class Task implements Runnable {
/**
diff --git a/src/main/java/site/deercloud/liteworldedit/XPlayer.java b/src/main/java/cn/lunadeer/liteworldedit/XPlayer.java
similarity index 86%
rename from src/main/java/site/deercloud/liteworldedit/XPlayer.java
rename to src/main/java/cn/lunadeer/liteworldedit/XPlayer.java
index fe945d1..54440ce 100644
--- a/src/main/java/site/deercloud/liteworldedit/XPlayer.java
+++ b/src/main/java/cn/lunadeer/liteworldedit/XPlayer.java
@@ -1,14 +1,14 @@
-package site.deercloud.liteworldedit;
+package cn.lunadeer.liteworldedit;
+import cn.lunadeer.liteworldedit.Jobs.Job;
+import cn.lunadeer.liteworldedit.Managers.JobQueue;
+import cn.lunadeer.liteworldedit.Managers.Point;
import org.bukkit.entity.Player;
-import site.deercloud.liteworldedit.Jobs.Job;
-import site.deercloud.liteworldedit.Managers.JobQueue;
-import site.deercloud.liteworldedit.Managers.Point;
import java.util.HashMap;
import java.util.Map;
-import static site.deercloud.liteworldedit.SchedulerUtil.runAtFixedRateEntity;
+import static cn.lunadeer.liteworldedit.SchedulerUtil.runAtFixedRateEntity;
public class XPlayer {
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index 4fd863d..d6c5334 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -8,4 +8,6 @@ Multiplier: 1
DropItems: false
+bStats: true
+
Debug: false
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 1a1e146..c3f52e1 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -1,12 +1,12 @@
name: LiteWorldEdit
version: '${project.version}'
-main: site.deercloud.liteworldedit.LiteWorldEdit
+main: cn.lunadeer.liteworldedit.LiteWorldEdit
api-version: 1.14
prefix: LWE
load: STARTUP
authors: [ Luming ]
description: 生存用简易创世神。
-website: https://blog.deercloud.site
+website: https://ssl.lunadeer.cn:14448/project-2/
folia-supported: true
commands:
LiteWorldEdit: