feat: add example mine config, &#RRGGBB color support, up to 100 selection points
This commit is contained in:
parent
0f2735f171
commit
f2be6d6ece
6 changed files with 445 additions and 28 deletions
|
|
@ -17,32 +17,17 @@ public final class RegionConfigLoader {
|
|||
|
||||
/**
|
||||
* Parses region configuration from YAML.
|
||||
* Supports up to 100 selection points (50 regions).
|
||||
*/
|
||||
public RegionConfig parse(YamlConfiguration yaml) {
|
||||
List<Location> selections = new ArrayList<>();
|
||||
|
||||
// Try new format first
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
String key = "region.selection." + i;
|
||||
if (yaml.contains(key)) {
|
||||
String locStr = yaml.getString(key);
|
||||
if (locStr != null && !locStr.isBlank()) {
|
||||
selections.add(parseLocation(locStr));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Try new format first (region.selection.X)
|
||||
selections.addAll(parseSelections(yaml, "region.selection.", 100));
|
||||
|
||||
// Legacy fallback
|
||||
// Legacy fallback (selection.X)
|
||||
if (selections.isEmpty()) {
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
String key = "selection." + i;
|
||||
if (yaml.contains(key)) {
|
||||
String locStr = yaml.getString(key);
|
||||
if (locStr != null && !locStr.isBlank()) {
|
||||
selections.add(parseLocation(locStr));
|
||||
}
|
||||
}
|
||||
}
|
||||
selections.addAll(parseSelections(yaml, "selection.", 100));
|
||||
}
|
||||
|
||||
if (selections.size() < 2) {
|
||||
|
|
@ -52,6 +37,43 @@ public final class RegionConfigLoader {
|
|||
return RegionConfig.fromSelections(selections);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses selection points from YAML with given prefix.
|
||||
* Supports indexed format: prefix.1, prefix.2, etc.
|
||||
*/
|
||||
private List<Location> parseSelections(YamlConfiguration yaml, String prefix, int maxPoints) {
|
||||
List<Location> selections = new ArrayList<>();
|
||||
|
||||
for (int i = 1; i <= maxPoints; i++) {
|
||||
String key = prefix + i;
|
||||
if (yaml.contains(key)) {
|
||||
String locStr = yaml.getString(key);
|
||||
if (locStr != null && !locStr.isBlank()) {
|
||||
try {
|
||||
selections.add(parseLocation(locStr));
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Skip invalid locations but continue parsing
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Stop at first missing index (assuming sequential)
|
||||
// But check at least a few more for gaps
|
||||
if (i > 20) {
|
||||
boolean hasMore = false;
|
||||
for (int j = i + 1; j <= Math.min(i + 5, maxPoints); j++) {
|
||||
if (yaml.contains(prefix + j)) {
|
||||
hasMore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasMore) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return selections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves region configuration to YAML.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package dev.loki.lomines.data.config.ui;
|
||||
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import dev.loki.lomines.util.format.ColorUtils;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.Objects;
|
||||
|
|
@ -36,6 +36,7 @@ public record UIConfig(
|
|||
/**
|
||||
* Parses the action bar format with placeholders.
|
||||
* Placeholders: {mine}, {percent}, {time}, {blocks}, {total}
|
||||
* Supports colors: &#RRGGBB, &a..&f, <color>
|
||||
*/
|
||||
public Component formatActionBar(String mineName, double percent, String timeStr, int blocks, int total) {
|
||||
String parsed = actionBarFormat
|
||||
|
|
@ -45,7 +46,7 @@ public record UIConfig(
|
|||
.replace("{blocks}", String.valueOf(blocks))
|
||||
.replace("{total}", String.valueOf(total));
|
||||
|
||||
return MiniMessage.miniMessage().deserialize(parsed);
|
||||
return ColorUtils.format(parsed);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import dev.loki.lomines.core.mine.Mine;
|
|||
import dev.loki.lomines.data.config.ui.HologramConfig;
|
||||
import dev.loki.lomines.integration.hologram.provider.DecentHologramsProvider;
|
||||
import dev.loki.lomines.integration.hologram.provider.HolographicDisplaysProvider;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import dev.loki.lomines.util.format.ColorUtils;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.*;
|
||||
|
|
@ -144,7 +144,6 @@ public final class HologramManager {
|
|||
|
||||
private List<String> formatLines(List<String> format, Mine mine) {
|
||||
List<String> result = new ArrayList<>();
|
||||
MiniMessage miniMessage = MiniMessage.miniMessage();
|
||||
|
||||
for (String line : format) {
|
||||
String formatted = line
|
||||
|
|
@ -153,7 +152,8 @@ public final class HologramManager {
|
|||
.replace("{bar}", createProgressBar(mine.getPercentFilled()))
|
||||
.replace("{time}", formatResetTime(mine));
|
||||
|
||||
result.add(formatted);
|
||||
// Convert &#RRGGBB and &codes to legacy for hologram plugins
|
||||
result.add(ColorUtils.toLegacy(formatted));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -163,12 +163,12 @@ public final class HologramManager {
|
|||
int filled = (int) Math.round(percent / 10.0);
|
||||
int empty = 10 - filled;
|
||||
|
||||
// Use &#RRGGBB format which works with most hologram plugins
|
||||
StringBuilder bar = new StringBuilder();
|
||||
bar.append("<green>");
|
||||
bar.append("�FF00"); // Green for filled
|
||||
bar.append("█".repeat(Math.max(0, filled)));
|
||||
bar.append("<gray>");
|
||||
bar.append("󅒐"); // Gray for empty
|
||||
bar.append("░".repeat(Math.max(0, empty)));
|
||||
bar.append("</gray></green>");
|
||||
|
||||
return bar.toString();
|
||||
}
|
||||
|
|
|
|||
207
src/main/java/dev/loki/lomines/util/format/ColorUtils.java
Normal file
207
src/main/java/dev/loki/lomines/util/format/ColorUtils.java
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
package dev.loki.lomines.util.format;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Utility for converting color formats.
|
||||
* Supports: &#RRGGBB (HEX), &x&R&R&G&G&B&B (Bukkit HEX), MiniMessage
|
||||
*/
|
||||
public final class ColorUtils {
|
||||
|
||||
private static final Pattern HEX_PATTERN = Pattern.compile("&#([0-9A-Fa-f]{6})");
|
||||
private static final Pattern LEGACY_HEX_PATTERN = Pattern.compile("&x([&0-9A-Fa-f]){12}");
|
||||
|
||||
private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage();
|
||||
private static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.builder()
|
||||
.hexColors()
|
||||
.useUnusualXRepeatedCharacterHexFormat()
|
||||
.build();
|
||||
|
||||
private ColorUtils() {
|
||||
// Utility class
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string with color codes to a Component.
|
||||
* Supports:
|
||||
* - &#RRGGBB - HEX colors
|
||||
* - &x&R&R&G&G&B&B - Legacy Bukkit HEX
|
||||
* - &a, &b, ... - Legacy colors
|
||||
* - <color>, <#RRGGBB> - MiniMessage (pass-through)
|
||||
*/
|
||||
public static Component format(String text) {
|
||||
if (text == null || text.isEmpty()) {
|
||||
return Component.empty();
|
||||
}
|
||||
|
||||
// Check if it's already MiniMessage format
|
||||
if (text.contains("<") && text.contains(">")) {
|
||||
try {
|
||||
return MINI_MESSAGE.deserialize(text);
|
||||
} catch (Exception e) {
|
||||
// Fall through to legacy conversion
|
||||
}
|
||||
}
|
||||
|
||||
// Convert &#RRGGBB to MiniMessage <#RRGGBB>
|
||||
String miniMessageText = convertHexToMiniMessage(text);
|
||||
|
||||
// Convert legacy &x format if present
|
||||
miniMessageText = convertLegacyHexToMiniMessage(miniMessageText);
|
||||
|
||||
// Convert remaining legacy codes (&a, &l, etc.) to MiniMessage
|
||||
miniMessageText = convertLegacyToMiniMessage(miniMessageText);
|
||||
|
||||
try {
|
||||
return MINI_MESSAGE.deserialize(miniMessageText);
|
||||
} catch (Exception e) {
|
||||
// Fallback: use legacy serializer
|
||||
return LEGACY_SERIALIZER.deserialize(text);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts &#RRGGBB to <#RRGGBB> for MiniMessage.
|
||||
*/
|
||||
private static String convertHexToMiniMessage(String text) {
|
||||
Matcher matcher = HEX_PATTERN.matcher(text);
|
||||
StringBuffer result = new StringBuffer();
|
||||
|
||||
while (matcher.find()) {
|
||||
String hex = matcher.group(1);
|
||||
matcher.appendReplacement(result, "<#" + hex + ">");
|
||||
}
|
||||
matcher.appendTail(result);
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts &x&R&R&G&G&B&B to <#RRGGBB> for MiniMessage.
|
||||
*/
|
||||
private static String convertLegacyHexToMiniMessage(String text) {
|
||||
if (!text.contains("&x")) {
|
||||
return text;
|
||||
}
|
||||
|
||||
// Pattern for &x&R&R&G&G&B&B
|
||||
Pattern bukkitHex = Pattern.compile("&x(&[0-9A-Fa-f])(&[0-9A-Fa-f])(&[0-9A-Fa-f])(&[0-9A-Fa-f])(&[0-9A-Fa-f])(&[0-9A-Fa-f])");
|
||||
Matcher matcher = bukkitHex.matcher(text);
|
||||
StringBuffer result = new StringBuffer();
|
||||
|
||||
while (matcher.find()) {
|
||||
String r1 = matcher.group(1).substring(1);
|
||||
String r2 = matcher.group(2).substring(1);
|
||||
String g1 = matcher.group(3).substring(1);
|
||||
String g2 = matcher.group(4).substring(1);
|
||||
String b1 = matcher.group(5).substring(1);
|
||||
String b2 = matcher.group(6).substring(1);
|
||||
String hex = r1 + r2 + g1 + g2 + b1 + b2;
|
||||
matcher.appendReplacement(result, "<#" + hex + ">");
|
||||
}
|
||||
matcher.appendTail(result);
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts legacy & codes to MiniMessage tags.
|
||||
*/
|
||||
private static String convertLegacyToMiniMessage(String text) {
|
||||
return text
|
||||
.replace("&0", "<black>")
|
||||
.replace("&1", "<dark_blue>")
|
||||
.replace("&2", "<dark_green>")
|
||||
.replace("&3", "<dark_aqua>")
|
||||
.replace("&4", "<dark_red>")
|
||||
.replace("&5", "<dark_purple>")
|
||||
.replace("&6", "<gold>")
|
||||
.replace("&7", "<gray>")
|
||||
.replace("&8", "<dark_gray>")
|
||||
.replace("&9", "<blue>")
|
||||
.replace("&a", "<green>")
|
||||
.replace("&b", "<aqua>")
|
||||
.replace("&c", "<red>")
|
||||
.replace("&d", "<light_purple>")
|
||||
.replace("&e", "<yellow>")
|
||||
.replace("&f", "<white>")
|
||||
.replace("&k", "<obfuscated>")
|
||||
.replace("&l", "<bold>")
|
||||
.replace("&m", "<strikethrough>")
|
||||
.replace("&n", "<underlined>")
|
||||
.replace("&o", "<italic>")
|
||||
.replace("&r", "<reset>");
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips all color codes from text.
|
||||
*/
|
||||
public static String stripColors(String text) {
|
||||
if (text == null || text.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
return text.replaceAll("&#[0-9A-Fa-f]{6}", "")
|
||||
.replaceAll("&[0-9A-Fa-fk-orK-OR]", "")
|
||||
.replaceAll("<[^>]+>", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts to legacy color format (&a, &c, &x&R&R&G&G&B&B).
|
||||
* Useful for plugins that don't support MiniMessage.
|
||||
*/
|
||||
public static String toLegacy(String text) {
|
||||
if (text == null || text.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
String result = text;
|
||||
|
||||
// Convert MiniMessage <#RRGGBB> to &x&R&R&G&G&B&B
|
||||
Pattern hexTag = Pattern.compile("<#([0-9A-Fa-f]{6})>");
|
||||
Matcher hexMatcher = hexTag.matcher(result);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while (hexMatcher.find()) {
|
||||
String hex = hexMatcher.group(1);
|
||||
StringBuilder legacy = new StringBuilder("&x");
|
||||
for (char c : hex.toCharArray()) {
|
||||
legacy.append("&").append(c);
|
||||
}
|
||||
hexMatcher.appendReplacement(sb, legacy.toString());
|
||||
}
|
||||
hexMatcher.appendTail(sb);
|
||||
result = sb.toString();
|
||||
|
||||
// Convert MiniMessage named colors to legacy
|
||||
result = result
|
||||
.replace("<black>", "&0")
|
||||
.replace("<dark_blue>", "&1")
|
||||
.replace("<dark_green>", "&2")
|
||||
.replace("<dark_aqua>", "&3")
|
||||
.replace("<dark_red>", "&4")
|
||||
.replace("<dark_purple>", "&5")
|
||||
.replace("<gold>", "&6")
|
||||
.replace("<gray>", "&7")
|
||||
.replace("<dark_gray>", "&8")
|
||||
.replace("<blue>", "&9")
|
||||
.replace("<green>", "&a")
|
||||
.replace("<aqua>", "&b")
|
||||
.replace("<red>", "&c")
|
||||
.replace("<light_purple>", "&d")
|
||||
.replace("<yellow>", "&e")
|
||||
.replace("<white>", "&f")
|
||||
.replace("<obfuscated>", "&k")
|
||||
.replace("<bold>", "&l")
|
||||
.replace("<strikethrough>", "&m")
|
||||
.replace("<underlined>", "&n")
|
||||
.replace("<italic>", "&o")
|
||||
.replace("<reset>", "&r");
|
||||
|
||||
// &#RRGGBB is already in a good format for most plugins
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue