diff --git a/common/pom.xml b/common/pom.xml
index 496229e..bee12ad 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -5,7 +5,7 @@
mineconfiguration-parent
cc.carm.lib
- 2.8.9
+ 2.9.1
4.0.0
diff --git a/common/src/main/java/cc/carm/lib/mineconfiguration/common/value/PreparedMessage.java b/common/src/main/java/cc/carm/lib/mineconfiguration/common/value/PreparedMessage.java
index 628385c..d40ceb8 100644
--- a/common/src/main/java/cc/carm/lib/mineconfiguration/common/value/PreparedMessage.java
+++ b/common/src/main/java/cc/carm/lib/mineconfiguration/common/value/PreparedMessage.java
@@ -37,7 +37,7 @@ public class PreparedMessage {
*
* @param receivers 消息的接收者们
*/
- public void to(@NotNull Iterable receivers) {
+ public void to(@NotNull Iterable extends R> receivers) {
receivers.forEach(this::to);
}
diff --git a/platform/bukkit/pom.xml b/platform/bukkit/pom.xml
index 122506e..6645e45 100644
--- a/platform/bukkit/pom.xml
+++ b/platform/bukkit/pom.xml
@@ -5,7 +5,7 @@
mineconfiguration-parent
cc.carm.lib
- 2.8.9
+ 2.9.1
../../pom.xml
4.0.0
diff --git a/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/data/NotifyConfig.java b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/data/NotifyConfig.java
new file mode 100644
index 0000000..976f420
--- /dev/null
+++ b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/data/NotifyConfig.java
@@ -0,0 +1,51 @@
+package cc.carm.lib.mineconfiguration.bukkit.data;
+
+import cc.carm.lib.mineconfiguration.bukkit.value.notify.ConfiguredNotify;
+import cc.carm.lib.mineconfiguration.bukkit.value.notify.NotifyType;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+import java.util.regex.Matcher;
+
+public class NotifyConfig, M> {
+
+ public static @Nullable NotifyConfig, ?> deserialize(@NotNull String config) {
+ // parse config with config_format
+ Matcher matcher = NotifyType.CONFIG_FORMAT.matcher(config.trim());
+ if (!matcher.matches()) return of("MESSAGE", null, config);
+ else return of(matcher.group("type"), matcher.group("param"), matcher.group("content"));
+ }
+
+ public static @Nullable NotifyConfig, ?> of(@NotNull String key, @Nullable String param, @Nullable String content) {
+ NotifyType> type = ConfiguredNotify.getType(key);
+ if (type == null) return null;
+ return NotifyConfig.of(type, param, content);
+ }
+
+ public static , M> NotifyConfig of(@NotNull T type, @Nullable String param, @Nullable String content) {
+ return new NotifyConfig<>(type, type.parseMeta(param, content));
+ }
+
+ public static , M> NotifyConfig of(@NotNull T type, @Nullable M meta) {
+ return new NotifyConfig<>(type, meta);
+ }
+
+ protected final @NotNull T type;
+ protected final @Nullable M meta;
+
+ public NotifyConfig(@NotNull T type, @Nullable M meta) {
+ this.type = type;
+ this.meta = meta;
+ }
+
+ public void execute(@NotNull Player player, @NotNull Map placeholders) {
+ type.execute(player, meta, placeholders);
+ }
+
+ public String serialize() {
+ return type.serializeConfig(meta);
+ }
+
+}
diff --git a/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/data/TitleConfig.java b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/data/TitleConfig.java
index 6f44bd0..b6d88d8 100644
--- a/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/data/TitleConfig.java
+++ b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/data/TitleConfig.java
@@ -58,6 +58,30 @@ public class TitleConfig {
this.fadeOut = fadeOut;
}
+ public int getFadeIn() {
+ return fadeIn;
+ }
+
+ public int getFadeOut() {
+ return fadeOut;
+ }
+
+ public int getStay() {
+ return stay;
+ }
+
+ public boolean isStandardTime() {
+ return this.fadeIn == 10 && this.stay == 60 && this.fadeOut == 10;
+ }
+
+ public @Nullable TextConfig getLine1() {
+ return line1;
+ }
+
+ public @Nullable TextConfig getLine2() {
+ return line2;
+ }
+
public void send(@NotNull Player player,
@NotNull Map placeholders,
@Nullable ConfiguredTitle.TitleConsumer sendConsumer) {
diff --git a/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/utils/PlaceholderAPIHelper.java b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/utils/PlaceholderAPIHelper.java
index 95233cb..06886c8 100644
--- a/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/utils/PlaceholderAPIHelper.java
+++ b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/utils/PlaceholderAPIHelper.java
@@ -7,6 +7,9 @@ import java.util.List;
public class PlaceholderAPIHelper {
+ private PlaceholderAPIHelper() {
+ }
+
public static String parseMessages(Player player, String message) {
try {
return PlaceholderAPI.setPlaceholders(player, message);
diff --git a/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/utils/TextParser.java b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/utils/TextParser.java
index cb5801c..30b29eb 100644
--- a/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/utils/TextParser.java
+++ b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/utils/TextParser.java
@@ -15,6 +15,9 @@ import java.util.stream.Collectors;
public class TextParser {
+ private TextParser() {
+ }
+
@Contract("_,!null,_->!null")
public static @Nullable String parseText(@Nullable CommandSender sender, @Nullable String message, @NotNull Map placeholders) {
if (message == null) return null;
diff --git a/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/ConfiguredNotify.java b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/ConfiguredNotify.java
new file mode 100644
index 0000000..c63ce22
--- /dev/null
+++ b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/ConfiguredNotify.java
@@ -0,0 +1,60 @@
+package cc.carm.lib.mineconfiguration.bukkit.value.notify;
+
+import cc.carm.lib.configuration.core.value.ValueManifest;
+import cc.carm.lib.configuration.core.value.type.ConfiguredList;
+import cc.carm.lib.mineconfiguration.bukkit.data.NotifyConfig;
+import cc.carm.lib.mineconfiguration.bukkit.value.notify.type.SoundNotify;
+import cc.carm.lib.mineconfiguration.bukkit.value.notify.type.StringNotify;
+import cc.carm.lib.mineconfiguration.bukkit.value.notify.type.TitleNotify;
+import cc.carm.lib.mineconfiguration.common.utils.ParamsUtils;
+import com.cryptomorin.xseries.messages.ActionBar;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+
+@SuppressWarnings("rawtypes")
+public class ConfiguredNotify extends ConfiguredList {
+
+ public static final Set> TYPES = new HashSet<>();
+
+ static {
+ TYPES.add(StringNotify.of("MESSAGE", Player::sendMessage, content -> Optional.ofNullable(content).orElse(" ")));
+ TYPES.add(StringNotify.of("MSG", Player::sendMessage));
+ TYPES.add(StringNotify.of("ACTIONBAR", ActionBar::sendActionBar));
+ TYPES.add(new TitleNotify("TITLE"));
+ TYPES.add(new SoundNotify("SOUND"));
+ }
+
+ public static NotifyType> getType(@NotNull String key) {
+ return TYPES.stream().filter(type -> type.key.equals(key)).findFirst().orElse(null);
+ }
+
+ protected final @NotNull String[] params;
+
+ public ConfiguredNotify(@NotNull ValueManifest> manifest, @NotNull String[] params) {
+ super(manifest, NotifyConfig.class, obj -> Objects.requireNonNull(NotifyConfig.deserialize(String.valueOf(obj))), NotifyConfig::serialize);
+ this.params = params;
+ }
+
+ public String[] getParams() {
+ return params;
+ }
+
+ public @NotNull PreparedNotify prepare(@NotNull String... values) {
+ return new PreparedNotify(getNotNull(), ParamsUtils.buildParams(getParams(), values));
+ }
+
+ public void send(@NotNull Player player, @NotNull String... values) {
+ prepare(values).to(player);
+ }
+
+ public void send(@NotNull Iterable extends Player> players, @NotNull String... values) {
+ prepare(values).to(players);
+ }
+
+ public void sendAll(@NotNull String... values) {
+ prepare(values).toAll();
+ }
+
+}
diff --git a/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/NotifyType.java b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/NotifyType.java
new file mode 100644
index 0000000..95b332a
--- /dev/null
+++ b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/NotifyType.java
@@ -0,0 +1,65 @@
+package cc.carm.lib.mineconfiguration.bukkit.value.notify;
+
+import cc.carm.lib.mineconfiguration.bukkit.utils.TextParser;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+import java.util.regex.Pattern;
+
+public abstract class NotifyType {
+
+ // Notify config format: [TYPE(@PARAM)] CONTENTS...
+ public static final @NotNull Pattern CONFIG_FORMAT = Pattern.compile("^\\[(?[^@\\]]+)(@(?[^]]+))?] (?.*)$");
+
+ protected final @NotNull String key;
+ protected final @NotNull Class metaClass;
+
+ protected NotifyType(@NotNull String key, @NotNull Class metaClass) {
+ this.key = key;
+ this.metaClass = metaClass;
+ }
+
+ public @NotNull String getKey() {
+ return key;
+ }
+
+ public @NotNull Class getMetaClass() {
+ return metaClass;
+ }
+
+ /**
+ * Parse metadata from string.
+ *
e.g. "[TYPE-KEY@PARAM] CONTENTS..."
+ *
+ * @param param The param of the notify config.
+ * @param content The content of the notify config.
+ * @return The parsed metadata.
+ */
+ public abstract @Nullable M parseMeta(@Nullable String param, @Nullable String content);
+
+ /**
+ * Serialize the metadata to singleton string to storage on configs.
+ *
+ * @param meta The parsed metadata.
+ * @return The serialized string.
+ */
+ public abstract @NotNull String serializeConfig(@Nullable M meta);
+
+ /**
+ * Execute the notify content to specific player.
+ *
+ * @param player The player who receive the notification.
+ * @param meta The parsed metadata.
+ */
+ public abstract void execute(@NotNull Player player, @Nullable M meta, @NotNull Map placeholders);
+
+ @Contract("_, _, null -> null; _, _, !null -> !null")
+ protected String setPlaceholders(@NotNull Player player, @Nullable String content,
+ @NotNull Map placeholders) {
+ return TextParser.parseText(player, content, placeholders);
+ }
+
+}
diff --git a/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/PreparedNotify.java b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/PreparedNotify.java
new file mode 100644
index 0000000..be8ea1c
--- /dev/null
+++ b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/PreparedNotify.java
@@ -0,0 +1,46 @@
+package cc.carm.lib.mineconfiguration.bukkit.value.notify;
+
+import cc.carm.lib.mineconfiguration.bukkit.data.NotifyConfig;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.Map;
+
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class PreparedNotify {
+
+ protected final @NotNull List notifications;
+ protected final @NotNull Map placeholders;
+
+ protected PreparedNotify(@NotNull List notifications, @NotNull Map placeholders) {
+ this.notifications = notifications;
+ this.placeholders = placeholders;
+ }
+
+
+ /**
+ * 向某位接收者发送消息
+ *
+ * @param receiver 消息的接收者
+ */
+ public void to(@NotNull Player receiver) {
+ notifications.forEach(config -> config.execute(receiver, placeholders));
+ }
+
+ /**
+ * 向某位接收者发送消息
+ *
+ * @param receivers 消息的接收者们
+ */
+ public void to(@NotNull Iterable extends Player> receivers) {
+ receivers.forEach(this::to);
+ }
+
+ public void toAll() {
+ to(Bukkit.getOnlinePlayers());
+ }
+
+
+}
diff --git a/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/type/SoundNotify.java b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/type/SoundNotify.java
new file mode 100644
index 0000000..8b5dc93
--- /dev/null
+++ b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/type/SoundNotify.java
@@ -0,0 +1,48 @@
+package cc.carm.lib.mineconfiguration.bukkit.value.notify.type;
+
+import cc.carm.lib.mineconfiguration.bukkit.data.SoundConfig;
+import cc.carm.lib.mineconfiguration.bukkit.value.notify.NotifyType;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+
+public class SoundNotify extends NotifyType {
+
+ public SoundNotify(@NotNull String key) {
+ super(key, SoundConfig.class);
+ }
+
+ @Override
+ public @Nullable SoundConfig parseMeta(@Nullable String param, @Nullable String content) {
+ if (content == null) return null;
+
+ String[] args = content.split(",");
+ try {
+ return new SoundConfig(content,
+ (args.length >= 1) ? Float.parseFloat(args[0]) : 1,
+ (args.length >= 2) ? Float.parseFloat(args[1]) : 1
+ );
+ } catch (Exception exception) {
+ return null;
+ }
+ }
+
+ @Override
+ public @NotNull String serializeConfig(@Nullable SoundConfig meta) {
+ if (meta == null) return "[" + key + "] ";
+
+ if (meta.getVolume() == 1 && meta.getPitch() == 1) {
+ return "[" + key + "] " + meta.getTypeName();
+ } else {
+ return "[" + key + "@" + +meta.getVolume() + "," + meta.getPitch() + "] " + meta.getTypeName();
+ }
+ }
+
+ @Override
+ public void execute(@NotNull Player player, @Nullable SoundConfig meta, @NotNull Map placeholders) {
+ if (meta != null) meta.playTo(player);
+ }
+
+}
diff --git a/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/type/StringNotify.java b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/type/StringNotify.java
new file mode 100644
index 0000000..9e0bebb
--- /dev/null
+++ b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/type/StringNotify.java
@@ -0,0 +1,52 @@
+package cc.carm.lib.mineconfiguration.bukkit.value.notify.type;
+
+import cc.carm.lib.mineconfiguration.bukkit.value.notify.NotifyType;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.function.UnaryOperator;
+
+public abstract class StringNotify extends NotifyType {
+
+ public static StringNotify of(String key, BiConsumer consumer) {
+ return of(key, consumer, (content) -> "[" + key + "] " + (content == null ? " " : content));
+ }
+
+ public static StringNotify of(String key,
+ BiConsumer consumer,
+ UnaryOperator serializer) {
+ return new StringNotify(key) {
+ @Override
+ public @NotNull String serializeConfig(@Nullable String meta) {
+ return serializer.apply(meta);
+ }
+
+ @Override
+ public void send(@NotNull Player player, @NotNull String parsedContent) {
+ consumer.accept(player, parsedContent);
+ }
+ };
+ }
+
+
+ protected StringNotify(String key) {
+ super(key, String.class);
+ }
+
+ public abstract void send(@NotNull Player player, @NotNull String parsedContent);
+
+ @Override
+ public @Nullable String parseMeta(@Nullable String param, @Nullable String content) {
+ return content;
+ }
+
+ @Override
+ public void execute(@NotNull Player player, @Nullable String content, @NotNull Map placeholders) {
+ if (content == null) return;
+ send(player, setPlaceholders(player, content, placeholders));
+ }
+
+}
diff --git a/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/type/TitleNotify.java b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/type/TitleNotify.java
new file mode 100644
index 0000000..b8f1428
--- /dev/null
+++ b/platform/bukkit/src/main/java/cc/carm/lib/mineconfiguration/bukkit/value/notify/type/TitleNotify.java
@@ -0,0 +1,61 @@
+package cc.carm.lib.mineconfiguration.bukkit.value.notify.type;
+
+import cc.carm.lib.mineconfiguration.bukkit.data.TitleConfig;
+import cc.carm.lib.mineconfiguration.bukkit.value.notify.NotifyType;
+import com.cryptomorin.xseries.messages.Titles;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+
+public class TitleNotify extends NotifyType {
+
+ //Title param format fadeIn,Stay,FadeOut
+ public static final String PARAM_FORMAT = "(?\\d+),(?\\d+),(?\\d+)";
+
+ public TitleNotify(String key) {
+ super(key, TitleConfig.class);
+ }
+
+ @Override
+ public @Nullable TitleConfig parseMeta(@Nullable String param, @Nullable String content) {
+ if (content == null) return null;
+ String[] lines = content.split("\\{n}");
+ if (param == null) {
+ return TitleConfig.of(content, null);
+ } else {
+ String[] params = param.split(",");
+ if (params.length == 3) {
+ try {
+ return TitleConfig.of(content, null,
+ Integer.parseInt(params[0]),
+ Integer.parseInt(params[1]),
+ Integer.parseInt(params[2]));
+ } catch (Exception ex) {
+ return TitleConfig.of(content, null);
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public @NotNull String serializeConfig(@Nullable TitleConfig meta) {
+ if (meta == null || (meta.getLine1() == null && meta.getLine2() == null)) return "[" + key + "] ";
+
+ String line1 = meta.getLine1() == null ? "" : meta.getLine1().getMessage();
+ String line2 = meta.getLine2() == null ? "" : meta.getLine2().getMessage();
+
+ if (meta.isStandardTime()) {
+ return "[" + key + "] " + line1 + "{n}" + line1;
+ } else
+ return "[" + key + "@" + meta.getFadeIn() + "," + meta.getStay() + "," + meta.getFadeOut() + "] " + line1 + "{n}" + line1;
+ }
+
+ @Override
+ public void execute(@NotNull Player player, @Nullable TitleConfig meta, @NotNull Map placeholders) {
+ if (meta != null) meta.send(player, placeholders, Titles::sendTitle);
+ }
+
+}
diff --git a/platform/bungee/pom.xml b/platform/bungee/pom.xml
index a95e917..1ae739d 100644
--- a/platform/bungee/pom.xml
+++ b/platform/bungee/pom.xml
@@ -5,7 +5,7 @@
mineconfiguration-parent
cc.carm.lib
- 2.8.9
+ 2.9.1
../../pom.xml
4.0.0
diff --git a/pom.xml b/pom.xml
index f2c82b6..bbd5749 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,14 +10,14 @@
UTF-8
UTF-8
- 3.8.1
+ 3.9.1
1.5.11
1.0.1
cc.carm.lib
mineconfiguration-parent
- 2.8.9
+ 2.9.1
pom
common