mirror of
https://github.com/rockyhawk64/CommandPanels.git
synced 2025-11-18 07:14:17 +01:00
Compare commits
2 Commits
41b15385c0
...
4aa87cc88a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4aa87cc88a | ||
|
|
21f5cd2ccd |
@ -74,8 +74,6 @@ public class CommandPanels extends JavaPlugin {
|
||||
addPermission("commandpanels.command.open", PermissionDefault.OP);
|
||||
addPermission("commandpanels.command.open.other", PermissionDefault.OP);
|
||||
addPermission("commandpanels.command.help", PermissionDefault.TRUE);
|
||||
// REMOVE AFTER CONVERTER IS REMOVED
|
||||
addPermission("commandpanels.command.convert", PermissionDefault.OP);
|
||||
}
|
||||
|
||||
private void addPermission(String name, PermissionDefault defaultValue) {
|
||||
|
||||
@ -1,243 +0,0 @@
|
||||
package me.rockyhawk.commandpanels;
|
||||
|
||||
import me.rockyhawk.commandpanels.formatter.language.Message;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
public class Converter {
|
||||
private final Context ctx;
|
||||
|
||||
public Converter(Context ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
// CONVERTER For CommandPanels v3 to v4
|
||||
// Will be removed at some point when v4 is further adopted
|
||||
// Does not include 1:! conversions as the two configs are incompatible in many ways
|
||||
|
||||
public void convertPanels(CommandSender sender) {
|
||||
File oldPanelsDir = new File(ctx.plugin.getDataFolder(), "old_panels"); // e.g. plugins/CommandPanels/old_panels
|
||||
if (!oldPanelsDir.exists()) {
|
||||
ctx.text.sendError(sender, Message.CONVERT_PANEL_CONFIG);
|
||||
ctx.text.sendError(sender, Message.CONVERT_OLD_DIR_NOT_FOUND, oldPanelsDir.getPath());
|
||||
return;
|
||||
}
|
||||
|
||||
File[] files = oldPanelsDir.listFiles((dir, name) -> name.endsWith(".yml"));
|
||||
if (files == null || files.length == 0) {
|
||||
ctx.text.sendInfo(sender, Message.CONVERT_NO_OLD_FILES);
|
||||
return;
|
||||
}
|
||||
|
||||
for (File file : files) {
|
||||
try {
|
||||
YamlConfiguration oldConfig = YamlConfiguration.loadConfiguration(file);
|
||||
ConfigurationSection panelsSection = oldConfig.getConfigurationSection("panels");
|
||||
|
||||
if (panelsSection == null) {
|
||||
ctx.text.sendError(sender, Message.CONVERT_NO_PANELS_SECTION, file.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
for (String panelName : panelsSection.getKeys(false)) {
|
||||
ConfigurationSection oldPanel = panelsSection.getConfigurationSection(panelName);
|
||||
if (oldPanel == null) continue;
|
||||
|
||||
Map<String, Object> newPanel = convertPanel(panelName, oldPanel);
|
||||
|
||||
File outFile = new File(ctx.plugin.folder, panelName + ".yml");
|
||||
YamlConfiguration newYaml = new YamlConfiguration();
|
||||
for (Map.Entry<String, Object> entry : newPanel.entrySet()) {
|
||||
newYaml.set(entry.getKey(), entry.getValue());
|
||||
}
|
||||
newYaml.save(outFile);
|
||||
|
||||
ctx.text.sendInfo(sender, Message.CONVERT_SUCCESS, panelName, outFile.getName());
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ctx.text.sendError(sender, Message.CONVERT_FILE_FAILED, file.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> convertPanel(String panelName, ConfigurationSection oldPanel) {
|
||||
Map<String, Object> newPanel = new LinkedHashMap<>();
|
||||
|
||||
newPanel.put("title", oldPanel.getString("title", "&fPanel"));
|
||||
newPanel.put("type", "inventory"); // hardcoded type unless we detect others
|
||||
newPanel.put("rows", oldPanel.getInt("rows", 6));
|
||||
|
||||
// Commands from "commands" and "commands-on-open"
|
||||
List<String> openCommands = oldPanel.getStringList("commands-on-open");
|
||||
List<String> baseCommands = oldPanel.getStringList("commands");
|
||||
String newOpenCommand = null;
|
||||
|
||||
if (!baseCommands.isEmpty()) {
|
||||
newOpenCommand = baseCommands.getFirst(); // Only use the first base command
|
||||
}
|
||||
|
||||
List<String> newOpenCommands = new ArrayList<>(openCommands); // Add commands
|
||||
|
||||
newPanel.put("command", newOpenCommand);
|
||||
newPanel.put("commands", newOpenCommands);
|
||||
|
||||
// Create layout and items map
|
||||
Map<String, List<String>> layout = new LinkedHashMap<>();
|
||||
Map<String, Object> items = new LinkedHashMap<>();
|
||||
|
||||
// Add custom items (named reusable entries)
|
||||
if (oldPanel.isConfigurationSection("custom-item")) {
|
||||
ConfigurationSection customItems = oldPanel.getConfigurationSection("custom-item");
|
||||
if (customItems != null) {
|
||||
for (String itemKey : customItems.getKeys(false)) {
|
||||
items.put(itemKey, convertItem(customItems.getConfigurationSection(itemKey)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert item slots to layout
|
||||
ConfigurationSection itemSection = oldPanel.getConfigurationSection("item");
|
||||
if (itemSection != null) {
|
||||
for (String slotKey : itemSection.getKeys(false)) {
|
||||
ConfigurationSection itemConfig = itemSection.getConfigurationSection(slotKey);
|
||||
|
||||
String itemId = panelName + "_slot_" + slotKey;
|
||||
Map<String, Object> convertedItem = convertItem(itemConfig);
|
||||
|
||||
if (itemConfig != null && (itemConfig.contains("commands") || hasNestedConditions(itemConfig))) {
|
||||
// Move commands into 'actions'
|
||||
List<String> cmds = itemConfig.getStringList("commands");
|
||||
if (!cmds.isEmpty()) {
|
||||
Map<String, Object> leftClick = new HashMap<>();
|
||||
List<String> cmdList = new ArrayList<>();
|
||||
for (String cmd : cmds) {
|
||||
// Do command tag convert attempts
|
||||
cmdList.add(commandTagConverter(cmd));
|
||||
}
|
||||
leftClick.put("commands", cmdList);
|
||||
convertedItem.put("actions", leftClick);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle nested "has0", "has1" logic
|
||||
List<Map<String, Object>> logicVariants = extractConditionVariants(itemConfig);
|
||||
if (!logicVariants.isEmpty()) {
|
||||
// Add base item as default (without conditions)
|
||||
items.put(itemId + "_base", convertedItem);
|
||||
layout.put(slotKey, new ArrayList<>(Collections.singletonList(itemId + "_base")));
|
||||
|
||||
int i = 0;
|
||||
for (Map<String, Object> variant : logicVariants) {
|
||||
String variantId = itemId + "_cond_" + i;
|
||||
items.put(variantId, variant);
|
||||
layout.get(slotKey).addFirst(variantId); // priority first
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
items.put(itemId, convertedItem);
|
||||
layout.put(slotKey, new ArrayList<>(Collections.singletonList(itemId)));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(oldPanel.contains("empty")){
|
||||
layout.put("fill", new ArrayList<>(Collections.singletonList("empty_item")));
|
||||
items.put("empty_item.material", oldPanel.getString("empty"));
|
||||
}
|
||||
|
||||
newPanel.put("layout", layout);
|
||||
newPanel.put("items", items);
|
||||
|
||||
return newPanel;
|
||||
}
|
||||
|
||||
private Map<String, Object> convertItem(ConfigurationSection itemConfig) {
|
||||
Map<String, Object> item = new LinkedHashMap<>();
|
||||
|
||||
if (itemConfig == null) return item;
|
||||
|
||||
for (String key : itemConfig.getKeys(false)) {
|
||||
Object value = itemConfig.get(key);
|
||||
|
||||
switch (key) {
|
||||
case "commands":
|
||||
// Handled separately in layout
|
||||
break;
|
||||
case "name":
|
||||
case "material":
|
||||
case "lore":
|
||||
case "enchanted":
|
||||
case "damage":
|
||||
case "stack":
|
||||
case "leatherarmor":
|
||||
item.put(key, value);
|
||||
break;
|
||||
default:
|
||||
if (!key.startsWith("has")) {
|
||||
item.put(key, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
private String commandTagConverter(String command){
|
||||
command = command.replace("server=", "[server]");
|
||||
command = command.replace("open=", "[open]");
|
||||
command = command.replace("cpc", "[close]");
|
||||
command = command.replace("console=", "[console]");
|
||||
command = command.replace("refresh", "[refresh]");
|
||||
command = command.replace("data=", "[data]");
|
||||
command = command.replace("msg=", "[msg]");
|
||||
command = command.replace("teleport=", "[teleport]");
|
||||
return command;
|
||||
}
|
||||
|
||||
private boolean hasNestedConditions(ConfigurationSection itemConfig) {
|
||||
for (String key : itemConfig.getKeys(false)) {
|
||||
if (key.startsWith("has")) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> extractConditionVariants(ConfigurationSection itemConfig) {
|
||||
List<Map<String, Object>> variants = new ArrayList<>();
|
||||
|
||||
for (String key : itemConfig.getKeys(false)) {
|
||||
if (key.startsWith("has")) {
|
||||
ConfigurationSection conditionSection = itemConfig.getConfigurationSection(key);
|
||||
if (conditionSection == null) continue;
|
||||
|
||||
Map<String, Object> variant = convertItem(conditionSection);
|
||||
|
||||
String conditions = "";
|
||||
for (String subKey : conditionSection.getKeys(false)) {
|
||||
if (subKey.startsWith("compare")) {
|
||||
int index = Integer.parseInt(subKey.substring(7));
|
||||
String valueKey = "value" + index;
|
||||
if (conditionSection.contains(valueKey)) {
|
||||
String compare = conditionSection.getString(subKey);
|
||||
String value = conditionSection.getString(valueKey);
|
||||
conditions = compare + " $EQUALS " + value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!conditions.isEmpty()) {
|
||||
variant.put("conditions", conditions);
|
||||
}
|
||||
|
||||
variants.add(variant);
|
||||
}
|
||||
}
|
||||
|
||||
return variants;
|
||||
}
|
||||
}
|
||||
@ -14,7 +14,6 @@ import me.rockyhawk.commandpanels.session.dialog.components.DialogButton;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickCallback;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
|
||||
@ -27,7 +27,6 @@ public class MainCommand implements BasicCommand {
|
||||
register(new HelpCommand());
|
||||
register(new VersionCommand());
|
||||
register(new DataCommand());
|
||||
register(new ConvertCommand());
|
||||
}
|
||||
|
||||
private void register(SubCommand subCommand) {
|
||||
|
||||
@ -41,10 +41,6 @@ public class TabComplete {
|
||||
if (sender.hasPermission("commandpanels.command.data")) {
|
||||
output.add("data");
|
||||
}
|
||||
// REMOVE AFTER CONVERTER IS REMOVED
|
||||
if (sender.hasPermission("commandpanels.command.convert")) {
|
||||
output.add("convert");
|
||||
}
|
||||
}
|
||||
|
||||
if (args.length == 2) {
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
package me.rockyhawk.commandpanels.commands.subcommands;
|
||||
|
||||
import me.rockyhawk.commandpanels.Context;
|
||||
import me.rockyhawk.commandpanels.Converter;
|
||||
import me.rockyhawk.commandpanels.commands.SubCommand;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class ConvertCommand implements SubCommand {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "convert";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermission() {
|
||||
return "commandpanels.command.convert";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(Context ctx, CommandSender sender, String[] args) {
|
||||
Converter converter = new Converter(ctx);
|
||||
converter.convertPanels(sender);
|
||||
ctx.fileHandler.reloadPanels();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -45,11 +45,6 @@ public class HelpCommand implements SubCommand {
|
||||
ctx.text.sendHelp(sender, Message.HELP_HELP_COMMAND, Message.HELP_HELP_DESCRIPTION);
|
||||
}
|
||||
|
||||
// REMOVE AFTER CONVERTER IS REMOVED
|
||||
if (sender.hasPermission("commandpanels.command.convert")) {
|
||||
ctx.text.sendHelp(sender, Message.HELP_CONVERT_COMMAND, Message.HELP_CONVERT_DESCRIPTION);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,14 +10,6 @@ public enum Message {
|
||||
COMMAND_UNKNOWN_SUBCOMMAND("Unknown subcommand. Use /pa help."),
|
||||
COMMAND_SUBCOMMAND_HELP("Use /pa help for a list of subcommands."),
|
||||
|
||||
// Converter
|
||||
CONVERT_PANEL_CONFIG("Converts v3 -> v4 Panel config layouts"),
|
||||
CONVERT_OLD_DIR_NOT_FOUND("Old panels directory not found: {0}"),
|
||||
CONVERT_NO_PANELS_SECTION("No panels section in file: {0}"),
|
||||
CONVERT_FILE_FAILED("Failed to convert file: {0}"),
|
||||
CONVERT_NO_OLD_FILES("No old panel files found."),
|
||||
CONVERT_SUCCESS("Converted panel: {0} -> {1}"),
|
||||
|
||||
// FileHandler / DataLoader / GenerateManager
|
||||
FILE_CREATE_PANELS_FAIL("Failed to create panels folder!"),
|
||||
FILE_CREATE_EXAMPLE_FAIL("Could not create example panels!"),
|
||||
@ -117,8 +109,6 @@ public enum Message {
|
||||
HELP_VERSION_DESCRIPTION("Gets the plugin version"),
|
||||
HELP_HELP_COMMAND("/pa help"),
|
||||
HELP_HELP_DESCRIPTION("Shows this help menu"),
|
||||
HELP_CONVERT_COMMAND("/pa convert"),
|
||||
HELP_CONVERT_DESCRIPTION("Converts basic layout from v3 to v4 panels (not plug and play)"),
|
||||
|
||||
// Misc
|
||||
DIALOG_NO_BUTTONS("Dialog needs at least one button"),
|
||||
|
||||
@ -97,7 +97,12 @@ public class TextFormatter {
|
||||
@NotNull
|
||||
public String parseTextToString(Player player, String input) {
|
||||
Component component = parseTextToComponent(player, input);
|
||||
return LegacyComponentSerializer.legacySection().serialize(component);
|
||||
// Preserve RGB when serializing to legacy
|
||||
return LegacyComponentSerializer.builder()
|
||||
.hexColors() // enable hex serialization
|
||||
.useUnusualXRepeatedCharacterHexFormat() // §x§R§R§G§G§B§B form
|
||||
.build()
|
||||
.serialize(component);
|
||||
}
|
||||
|
||||
public String applyPlaceholders(Player player, String input) {
|
||||
@ -125,42 +130,75 @@ public class TextFormatter {
|
||||
}
|
||||
|
||||
/**
|
||||
* For compatibility with legacy codes
|
||||
* This will convert anything legacy to MiniMessage
|
||||
* Once converted, everything will be parsed as pure MiniMessage text
|
||||
* Below includes compatibility with legacy codes
|
||||
* Handles:
|
||||
* - Mojang RGB form: §x§R§R§G§G§B§B (and &x&R&R&G&G&B&B)
|
||||
* - Simple hex: &#[0-9a-f]{6} or §#[0-9a-f]{6}
|
||||
* - Simple legacy codes: &a, §l, etc.
|
||||
*/
|
||||
private String convertLegacyToMiniMessage(String input) {
|
||||
if (input == null) return "";
|
||||
|
||||
// Replace hex colors
|
||||
Matcher hexMatcher = LEGACY_HEX.matcher(input);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
String processed = input;
|
||||
|
||||
// Replace Mojang "§x§R§R§G§G§B§B" (or &x...) with MiniMessage <#RRGGBB>
|
||||
Matcher mojangMatcher = MOJANG_HEX.matcher(processed);
|
||||
StringBuilder mmSB = new StringBuilder();
|
||||
while (mojangMatcher.find()) {
|
||||
String hex =
|
||||
(mojangMatcher.group(1) +
|
||||
mojangMatcher.group(2) +
|
||||
mojangMatcher.group(3) +
|
||||
mojangMatcher.group(4) +
|
||||
mojangMatcher.group(5) +
|
||||
mojangMatcher.group(6)).toLowerCase();
|
||||
mojangMatcher.appendReplacement(mmSB, Matcher.quoteReplacement("<#" + hex + ">"));
|
||||
}
|
||||
mojangMatcher.appendTail(mmSB);
|
||||
processed = mmSB.toString();
|
||||
|
||||
// Replace &#[0-9a-f]{6} / §#[0-9a-f]{6} with <#RRGGBB>
|
||||
Matcher hexMatcher = LEGACY_HASH_HEX.matcher(processed);
|
||||
StringBuilder sb1 = new StringBuilder();
|
||||
while (hexMatcher.find()) {
|
||||
String hex = hexMatcher.group(1);
|
||||
hexMatcher.appendReplacement(sb, "<#" + hex + ">");
|
||||
String hex = hexMatcher.group(1).toLowerCase();
|
||||
hexMatcher.appendReplacement(sb1, Matcher.quoteReplacement("<#" + hex + ">"));
|
||||
}
|
||||
hexMatcher.appendTail(sb);
|
||||
hexMatcher.appendTail(sb1);
|
||||
processed = sb1.toString();
|
||||
|
||||
String processed = sb.toString();
|
||||
|
||||
// Replace simple codes
|
||||
// Replace simple legacy codes (&a, §l, etc.) with MiniMessage tags
|
||||
Matcher simpleMatcher = LEGACY_SIMPLE.matcher(processed);
|
||||
sb = new StringBuffer();
|
||||
StringBuilder sb2 = new StringBuilder();
|
||||
while (simpleMatcher.find()) {
|
||||
char code = simpleMatcher.group(1).toLowerCase().charAt(0);
|
||||
char code = Character.toLowerCase(simpleMatcher.group(1).charAt(0));
|
||||
String replacement = COLOR_MAP.getOrDefault(code, "reset");
|
||||
simpleMatcher.appendReplacement(sb, "<" + replacement + ">");
|
||||
simpleMatcher.appendReplacement(sb2, Matcher.quoteReplacement("<" + replacement + ">"));
|
||||
}
|
||||
simpleMatcher.appendTail(sb);
|
||||
simpleMatcher.appendTail(sb2);
|
||||
|
||||
return sb.toString();
|
||||
return sb2.toString();
|
||||
}
|
||||
|
||||
// Patterns for legacy color codes for compatibility
|
||||
private final Pattern LEGACY_HEX = Pattern.compile("(?i)[&§]#([0-9a-f]{6})"); // & or § followed by hex
|
||||
private final Pattern LEGACY_SIMPLE = Pattern.compile("(?i)[&§]([0-9a-fk-or])"); // single-char codes
|
||||
// Patterns for legacy color codes
|
||||
// Mojang RGB: §x§R§R§G§G§B§B or &x&R&R&G&G&B&B
|
||||
private final Pattern MOJANG_HEX = Pattern.compile(
|
||||
"(?i)[&§]x" +
|
||||
"[&§]([0-9a-f])" +
|
||||
"[&§]([0-9a-f])" +
|
||||
"[&§]([0-9a-f])" +
|
||||
"[&§]([0-9a-f])" +
|
||||
"[&§]([0-9a-f])" +
|
||||
"[&§]([0-9a-f])"
|
||||
);
|
||||
|
||||
// Map of legacy codes for compatibility
|
||||
// Pattern for legacy simple hex &#[0-9a-f]{6} or §#[0-9a-f]{6}
|
||||
private final Pattern LEGACY_HASH_HEX = Pattern.compile("(?i)[&§]#([0-9a-f]{6})");
|
||||
|
||||
// Single-char legacy codes
|
||||
private final Pattern LEGACY_SIMPLE = Pattern.compile("(?i)[&§]([0-9a-fk-or])");
|
||||
|
||||
// Map of legacy codes -> MiniMessage tags
|
||||
private final java.util.Map<Character, String> COLOR_MAP = java.util.Map.ofEntries(
|
||||
java.util.Map.entry('0', "black"),
|
||||
java.util.Map.entry('1', "dark_blue"),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user