From f6364ac36b206b806c297c87900481cbbbbbf190 Mon Sep 17 00:00:00 2001 From: Coldsmile_7 Date: Tue, 14 Apr 2026 06:01:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=AE=A1=E7=90=86=E5=91=98?= =?UTF-8?q?=E8=8F=9C=E5=8D=95:=E4=BB=8Econfig.yml=E8=AF=BB=E5=8F=96?= =?UTF-8?q?=E9=85=8D=E7=BD=AE,=E6=B7=BB=E5=8A=A0=E6=9D=83=E9=99=90?= =?UTF-8?q?=E8=BF=87=E6=BB=A4=E7=9A=84Tab=E8=A1=A5=E5=85=A8,=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=BB=A3=E7=A0=81=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/infstar/essentialsC/EssentialsC.java | 9 +- .../cn/infstar/essentialsC/LangManager.java | 24 +++ .../commands/AdminMenuCommand.java | 147 +++++++------- .../essentialsC/commands/HelpCommand.java | 185 +++++++++++++++++- src/main/resources/config.yml | 52 ++++- src/main/resources/lang/en_US.yml | 11 +- src/main/resources/lang/zh_CN.yml | 12 +- src/main/resources/paper-plugin.yml | 4 + 8 files changed, 357 insertions(+), 87 deletions(-) diff --git a/src/main/java/cn/infstar/essentialsC/EssentialsC.java b/src/main/java/cn/infstar/essentialsC/EssentialsC.java index c5f0652..55d82fe 100644 --- a/src/main/java/cn/infstar/essentialsC/EssentialsC.java +++ b/src/main/java/cn/infstar/essentialsC/EssentialsC.java @@ -57,7 +57,6 @@ public final class EssentialsC extends JavaPlugin { registerCommand(commandMap, "heal", new HealCommand()); registerCommand(commandMap, "vanish", new VanishCommand()); registerCommand(commandMap, "seen", new SeenCommand()); - registerCommand(commandMap, "admin", new AdminMenuCommand()); registerCommand(commandMap, "feed", new FeedCommand()); registerCommand(commandMap, "repair", new RepairCommand()); registerCommand(commandMap, "essentialsc", new HelpCommand()); @@ -75,6 +74,14 @@ public final class EssentialsC extends JavaPlugin { public boolean execute(CommandSender sender, String commandLabel, String[] args) { return executor.onCommand(sender, this, commandLabel, args); } + + @Override + public java.util.List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException { + if (executor instanceof org.bukkit.command.TabCompleter) { + return ((org.bukkit.command.TabCompleter) executor).onTabComplete(sender, this, alias, args); + } + return super.tabComplete(sender, alias, args); + } }; // 为 essentialsc 命令添加简化别名 diff --git a/src/main/java/cn/infstar/essentialsC/LangManager.java b/src/main/java/cn/infstar/essentialsC/LangManager.java index 3d590b5..6978b5a 100644 --- a/src/main/java/cn/infstar/essentialsC/LangManager.java +++ b/src/main/java/cn/infstar/essentialsC/LangManager.java @@ -82,6 +82,13 @@ public class LangManager { } } + /** + * 获取插件前缀 + */ + public String getPrefix() { + return translateColorCodes(langFile.getString("prefix", "&6[EssentialsC] &r")); + } + /** * 获取翻译文本 */ @@ -104,6 +111,23 @@ public class LangManager { return value; } + /** + * 获取字符串列表(用于 Lore 等多行文本) + */ + public java.util.List getStringList(String path) { + java.util.List values = langFile.getStringList(path); + if (values.isEmpty()) { + // 如果找不到,返回包含错误信息的列表 + return java.util.Arrays.asList("&cMissing translation: " + path); + } + // 翻译颜色代码 + java.util.List translated = new java.util.ArrayList<>(); + for (String value : values) { + translated.add(translateColorCodes(value)); + } + return translated; + } + /** * 重新加载配置和语言 */ diff --git a/src/main/java/cn/infstar/essentialsC/commands/AdminMenuCommand.java b/src/main/java/cn/infstar/essentialsC/commands/AdminMenuCommand.java index 7955f68..5f3a5d4 100644 --- a/src/main/java/cn/infstar/essentialsC/commands/AdminMenuCommand.java +++ b/src/main/java/cn/infstar/essentialsC/commands/AdminMenuCommand.java @@ -1,5 +1,6 @@ package cn.infstar.essentialsC.commands; +import cn.infstar.essentialsC.EssentialsC; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -29,32 +30,36 @@ public class AdminMenuCommand extends BaseCommand implements Listener { } private void openMenu(Player player) { - String title = getLang().getString("admin-menu-title"); - Inventory menu = Bukkit.createInventory(null, MENU_SIZE, title); + String title = plugin.getConfig().getString("admin-menu.title", "&6EssentialsC 管理菜单"); + Inventory menu = Bukkit.createInventory(null, MENU_SIZE, translateColor(title)); - // 时间控制 - addItem(menu, 10, Material.CLOCK, getLang().getString("admin-time-control"), - Arrays.asList("§7左键: 设为白天", "§7右键: 设为夜晚")); - addItem(menu, 11, Material.SUNFLOWER, getLang().getString("admin-weather-control"), - Arrays.asList("§7左键: 晴天", "§7右键: 雨天")); + // 从配置中读取所有物品 + var itemsConfig = plugin.getConfig().getConfigurationSection("admin-menu.items"); + if (itemsConfig == null) return; - // 状态恢复 - addItem(menu, 13, Material.GOLDEN_APPLE, getLang().getString("admin-heal-self"), - Arrays.asList("§7补满生命值和饱食度")); - addItem(menu, 14, Material.BREAD, getLang().getString("admin-feed-self"), - Arrays.asList("§7补满饱食度")); - addItem(menu, 15, Material.ANVIL, getLang().getString("admin-repair-hand"), - Arrays.asList("§7修复当前手持物品")); - - // 管理员功能 - addItem(menu, 21, Material.ENDER_PEARL, getLang().getString("admin-vanish"), - Arrays.asList("§7点击切换隐身状态")); - addItem(menu, 22, Material.BOOK, getLang().getString("admin-reload"), - Arrays.asList("§7重新加载配置文件")); + for (String key : itemsConfig.getKeys(false)) { + var section = itemsConfig.getConfigurationSection(key); + if (section == null) continue; + + int slot = section.getInt("slot"); + Material material = Material.matchMaterial(section.getString("material", "STONE")); + if (material == null) material = Material.STONE; + + String name = translateColor(section.getString("name", "&fItem")); + java.util.List lore = section.getStringList("lore").stream() + .map(this::translateColor) + .collect(java.util.stream.Collectors.toList()); + + addItem(menu, slot, material, name, lore); + } player.openInventory(menu); } + private String translateColor(String text) { + return text.replace("&", "§"); + } + private void addItem(Inventory inv, int slot, Material material, String name, java.util.List lore) { ItemStack item = new ItemStack(material); ItemMeta meta = item.getItemMeta(); @@ -68,61 +73,71 @@ public class AdminMenuCommand extends BaseCommand implements Listener { @EventHandler public void onMenuClick(InventoryClickEvent event) { - String title = getLang().getString("admin-menu-title"); - if (!event.getView().getTitle().equals(title)) return; + // 检查是否是管理员菜单 + String configTitle = translateColor(plugin.getConfig().getString("admin-menu.title", "&6EssentialsC 管理菜单")); + if (!event.getView().getTitle().equals(configTitle)) return; if (!(event.getWhoClicked() instanceof Player player)) return; + // 取消事件,防止拿出物品 event.setCancelled(true); + ItemStack clicked = event.getCurrentItem(); if (clicked == null || !clicked.hasItemMeta()) return; - String name = clicked.getItemMeta().getDisplayName(); - String timeControl = getLang().getString("admin-time-control"); - String weatherControl = getLang().getString("admin-weather-control"); - String healSelf = getLang().getString("admin-heal-self"); - String feedSelf = getLang().getString("admin-feed-self"); - String repairHand = getLang().getString("admin-repair-hand"); - String vanish = getLang().getString("admin-vanish"); - String reload = getLang().getString("admin-reload"); + String displayName = clicked.getItemMeta().getDisplayName(); - switch (name) { - case String t when t.equals(timeControl) -> { - if (event.isLeftClick()) player.getWorld().setTime(1000); - else player.getWorld().setTime(13000); - player.sendMessage(getLang().getString("admin-time-set")); - } - case String w when w.equals(weatherControl) -> { - if (event.isLeftClick()) player.getWorld().setStorm(false); - else player.getWorld().setStorm(true); - player.sendMessage(getLang().getString("admin-weather-set")); - } - case String h when h.equals(healSelf) -> { - player.setHealth(player.getMaxHealth()); - player.setFoodLevel(20); - player.sendMessage(getLang().getString("admin-heal-success")); - } - case String f when f.equals(feedSelf) -> { - player.setFoodLevel(20); - player.setSaturation(20f); - player.sendMessage(getLang().getString("admin-feed-success")); - } - case String r when r.equals(repairHand) -> { - var item = player.getInventory().getItemInMainHand(); - if (item.getItemMeta() instanceof org.bukkit.inventory.meta.Damageable d) { - d.setDamage(0); - item.setItemMeta((org.bukkit.inventory.meta.ItemMeta) d); - player.sendMessage(getLang().getString("admin-repair-success")); + // 从配置中读取所有物品配置,通过名称匹配 + var itemsConfig = plugin.getConfig().getConfigurationSection("admin-menu.items"); + if (itemsConfig == null) return; + + for (String key : itemsConfig.getKeys(false)) { + var section = itemsConfig.getConfigurationSection(key); + if (section == null) continue; + + String itemName = translateColor(section.getString("name", "")); + if (!displayName.equals(itemName)) continue; + + // 找到匹配的物品,执行对应操作 + switch (key) { + case "time-control" -> { + if (event.isLeftClick()) player.getWorld().setTime(1000); + else player.getWorld().setTime(13000); + player.sendMessage(getLang().getString("admin-time-set")); + } + case "weather-control" -> { + if (event.isLeftClick()) player.getWorld().setStorm(false); + else player.getWorld().setStorm(true); + player.sendMessage(getLang().getString("admin-weather-set")); + } + case "heal-self" -> { + player.setHealth(player.getMaxHealth()); + player.setFoodLevel(20); + player.sendMessage(getLang().getString("admin-heal-success")); + } + case "feed-self" -> { + player.setFoodLevel(20); + player.setSaturation(20f); + player.sendMessage(getLang().getString("admin-feed-success")); + } + case "repair-hand" -> { + var item = player.getInventory().getItemInMainHand(); + if (item.getItemMeta() instanceof org.bukkit.inventory.meta.Damageable d) { + d.setDamage(0); + item.setItemMeta((org.bukkit.inventory.meta.ItemMeta) d); + player.sendMessage(getLang().getString("admin-repair-success")); + } + } + case "vanish" -> { + HelpCommand.COMMAND_CACHE.get("vanish").execute(player, new String[]{}); + openMenu(player); // 刷新菜单 + } + case "reload" -> { + plugin.reloadConfig(); + EssentialsC.getLangManager().reload(); + player.sendMessage(getLang().getString("admin-reload-success")); } } - case String v when v.equals(vanish) -> { - new VanishCommand().execute(player, new String[]{}); - openMenu(player); // 刷新菜单 - } - case String rl when rl.equals(reload) -> { - plugin.reloadConfig(); - player.sendMessage(getLang().getString("admin-reload-success")); - } - default -> {} // 忽略其他点击 + break; // 找到后退出循环 } } } diff --git a/src/main/java/cn/infstar/essentialsC/commands/HelpCommand.java b/src/main/java/cn/infstar/essentialsC/commands/HelpCommand.java index 1da6356..3bdf034 100644 --- a/src/main/java/cn/infstar/essentialsC/commands/HelpCommand.java +++ b/src/main/java/cn/infstar/essentialsC/commands/HelpCommand.java @@ -2,10 +2,42 @@ package cn.infstar.essentialsC.commands; import cn.infstar.essentialsC.EssentialsC; import cn.infstar.essentialsC.LangManager; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -public class HelpCommand extends BaseCommand { +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class HelpCommand extends BaseCommand implements TabCompleter { + + // 缓存命令实例,避免重复创建 + static final java.util.Map COMMAND_CACHE = new java.util.HashMap<>(); + + static { + COMMAND_CACHE.put("workbench", new WorkbenchCommand()); + COMMAND_CACHE.put("anvil", new AnvilCommand()); + COMMAND_CACHE.put("enchantingtable", new EnchantingTableCommand()); + COMMAND_CACHE.put("cartographytable", new CartographyTableCommand()); + COMMAND_CACHE.put("grindstone", new GrindstoneCommand()); + COMMAND_CACHE.put("loom", new LoomCommand()); + COMMAND_CACHE.put("smithingtable", new SmithingTableCommand()); + COMMAND_CACHE.put("stonecutter", new StonecutterCommand()); + COMMAND_CACHE.put("enderchest", new EnderChestCommand()); + COMMAND_CACHE.put("hat", new HatCommand()); + COMMAND_CACHE.put("suicide", new SuicideCommand()); + COMMAND_CACHE.put("fly", new FlyCommand()); + COMMAND_CACHE.put("heal", new HealCommand()); + COMMAND_CACHE.put("vanish", new VanishCommand()); + COMMAND_CACHE.put("seen", new SeenCommand()); + COMMAND_CACHE.put("feed", new FeedCommand()); + COMMAND_CACHE.put("repair", new RepairCommand()); + COMMAND_CACHE.put("admin", new AdminMenuCommand()); + } public HelpCommand() { super("essentialsc.command.help"); @@ -13,6 +45,60 @@ public class HelpCommand extends BaseCommand { @Override protected boolean execute(@NotNull Player player, String[] args) { + if (args.length > 0) { + String subCommand = args[0].toLowerCase(); + + // 管理相关 + if (subCommand.equals("admin")) { + if (!player.hasPermission("essentialsc.command.admin")) { + player.sendMessage(getLang().getString("messages.no-permission")); + return true; + } + COMMAND_CACHE.get("admin").execute(player, new String[]{}); + return true; + } else if (subCommand.equals("reload")) { + if (!player.hasPermission("essentialsc.command.reload")) { + player.sendMessage(getLang().getString("messages.no-permission")); + return true; + } + plugin.reloadConfig(); + EssentialsC.getLangManager().reload(); + player.sendMessage("§a配置已重载!"); + return true; + } + // 功能方块和其他命令 - 使用别名映射 + String actualCommand = getActualCommand(subCommand); + if (actualCommand != null && COMMAND_CACHE.containsKey(actualCommand)) { + String permission = getPermissionForCommand(actualCommand); + if (!player.hasPermission(permission)) { + player.sendMessage(getLang().getString("messages.no-permission")); + return true; + } + + // seen 需要特殊处理参数 + if (actualCommand.equals("seen")) { + if (args.length < 2) { + player.sendMessage("§c用法: /essc seen <玩家名>"); + return true; + } + COMMAND_CACHE.get("seen").execute(player, new String[]{args[1]}); + } else { + COMMAND_CACHE.get(actualCommand).execute(player, new String[]{}); + } + return true; + } else if (subCommand.equals("version") || subCommand.equals("v")) { + player.sendMessage("§6EssentialsC §fv" + plugin.getDescription().getVersion()); + player.sendMessage("§7运行在 Paper " + Bukkit.getVersion()); + return true; + } else { + // 未知子命令 + player.sendMessage("§c未知子命令: " + subCommand); + player.sendMessage("§7使用 §f/essc help §7查看所有可用命令"); + return true; + } + } + + // 显示帮助 LangManager lang = getLang(); String version = plugin.getDescription().getVersion(); @@ -110,4 +196,101 @@ public class HelpCommand extends BaseCommand { player.sendMessage(lang.getString("help.footer")); return true; } + + /** + * 将别名映射到实际命令名 + */ + private String getActualCommand(String alias) { + return switch (alias) { + case "wb" -> "workbench"; + case "enchant", "et" -> "enchantingtable"; + case "cartography", "ct" -> "cartographytable"; + case "gs" -> "grindstone"; + case "smithing", "st" -> "smithingtable"; + case "sc" -> "stonecutter"; + case "ec" -> "enderchest"; + case "die" -> "suicide"; + case "info" -> "seen"; + case "rep" -> "repair"; + default -> alias; + }; + } + + /** + * 获取命令对应的权限节点 + */ + private String getPermissionForCommand(String command) { + return "essentialsc.command." + command; + } + + @Override + public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (args.length == 1) { + List completions = new ArrayList<>(); + String partial = args[0].toLowerCase(); + + // 所有可能的子命令及其权限(包括别名) + String[][] subCommands = { + {"admin", "essentialsc.command.admin"}, + {"reload", "essentialsc.command.reload"}, + {"workbench", "essentialsc.command.workbench"}, + {"wb", "essentialsc.command.workbench"}, + {"anvil", "essentialsc.command.anvil"}, + {"enchantingtable", "essentialsc.command.enchantingtable"}, + {"enchant", "essentialsc.command.enchantingtable"}, + {"et", "essentialsc.command.enchantingtable"}, + {"cartographytable", "essentialsc.command.cartographytable"}, + {"cartography", "essentialsc.command.cartographytable"}, + {"ct", "essentialsc.command.cartographytable"}, + {"grindstone", "essentialsc.command.grindstone"}, + {"gs", "essentialsc.command.grindstone"}, + {"loom", "essentialsc.command.loom"}, + {"smithingtable", "essentialsc.command.smithingtable"}, + {"smithing", "essentialsc.command.smithingtable"}, + {"st", "essentialsc.command.smithingtable"}, + {"stonecutter", "essentialsc.command.stonecutter"}, + {"sc", "essentialsc.command.stonecutter"}, + {"enderchest", "essentialsc.command.enderchest"}, + {"ec", "essentialsc.command.enderchest"}, + {"hat", "essentialsc.command.hat"}, + {"suicide", "essentialsc.command.suicide"}, + {"die", "essentialsc.command.suicide"}, + {"fly", "essentialsc.command.fly"}, + {"heal", "essentialsc.command.heal"}, + {"vanish", "essentialsc.command.vanish"}, + {"v", "essentialsc.command.vanish"}, + {"seen", "essentialsc.command.seen"}, + {"info", "essentialsc.command.seen"}, + {"feed", "essentialsc.command.feed"}, + {"repair", "essentialsc.command.repair"}, + {"rep", "essentialsc.command.repair"}, + {"version", null}, + {"help", null} + }; + + for (String[] subCmd : subCommands) { + if (subCmd[0].startsWith(partial)) { + if (subCmd[1] == null || sender.hasPermission(subCmd[1])) { + completions.add(subCmd[0]); + } + } + } + + return completions; + } else if (args.length == 2) { + String subCmd = args[0].toLowerCase(); + if ((subCmd.equals("seen") || subCmd.equals("info")) && sender.hasPermission("essentialsc.command.seen")) { + List players = new ArrayList<>(); + String partial = args[1].toLowerCase(); + for (Player p : Bukkit.getOnlinePlayers()) { + if (p.getName().toLowerCase().startsWith(partial)) { + players.add(p.getName()); + } + } + return players; + } + } + + return new ArrayList<>(); + } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 92d97af..afaf69c 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -9,6 +9,52 @@ language: "zh_CN" settings: # 启用或禁用命令反馈消息 enable-feedback: true - - # 所有插件消息的前缀 - message-prefix: "&6[EssentialsC] &r" + +# 管理员菜单配置 +admin-menu: + title: "&6EssentialsC 管理菜单" + items: + time-control: + slot: 10 + material: CLOCK + name: "&e时间控制" + lore: + - "&7左键: 设为白天" + - "&7右键: 设为夜晚" + weather-control: + slot: 11 + material: SUNFLOWER + name: "&e天气控制" + lore: + - "&7左键: 晴天" + - "&7右键: 雨天" + heal-self: + slot: 13 + material: GOLDEN_APPLE + name: "&a治疗自己" + lore: + - "&7补满生命值和饱食度" + feed-self: + slot: 14 + material: BREAD + name: "&6喂饱自己" + lore: + - "&7补满饱食度" + repair-hand: + slot: 15 + material: ANVIL + name: "&b修复手持物品" + lore: + - "&7修复当前手持物品" + vanish: + slot: 21 + material: ENDER_PEARL + name: "&d隐身模式" + lore: + - "&7点击切换隐身状态" + reload: + slot: 22 + material: BOOK + name: "&c重载配置" + lore: + - "&7重新加载配置文件" diff --git a/src/main/resources/lang/en_US.yml b/src/main/resources/lang/en_US.yml index 52f7198..a0ed0aa 100644 --- a/src/main/resources/lang/en_US.yml +++ b/src/main/resources/lang/en_US.yml @@ -1,6 +1,9 @@ # English Language File (en_US) # You can customize all messages here +# Plugin prefix +prefix: "&6[EssentialsC] &r" + # Command messages messages: no-permission: "&cYou don't have permission to use this command!\n&7Required permission: {permission}" @@ -14,14 +17,6 @@ messages: vanish-enabled: "&aYou are now vanished!" vanish-disabled: "&cYou are no longer vanished!" seen-usage: "&cUsage: /seen " - admin-menu-title: "&6EssentialsC Admin Menu" - admin-time-control: "&eTime Control" - admin-weather-control: "&eWeather Control" - admin-heal-self: "&aHeal Self" - admin-feed-self: "&aFeed Self" - admin-repair-hand: "&aRepair Hand Item" - admin-vanish: "&dVanish Mode" - admin-reload: "&dReload Plugin" admin-time-set: "&aTime set!" admin-weather-set: "&aWeather set!" admin-heal-success: "&aHealed!" diff --git a/src/main/resources/lang/zh_CN.yml b/src/main/resources/lang/zh_CN.yml index 8311471..7925496 100644 --- a/src/main/resources/lang/zh_CN.yml +++ b/src/main/resources/lang/zh_CN.yml @@ -1,6 +1,9 @@ # Chinese Language File (zh_CN) # 中文语言文件 +# 插件前缀 +prefix: "&6[EssentialsC] &r" + # 命令消息 messages: no-permission: "&c你没有权限执行此命令!\n&7需要权限: {permission}" @@ -14,14 +17,7 @@ messages: vanish-enabled: "&a你已进入隐身模式!" vanish-disabled: "&c你已退出隐身模式!" seen-usage: "&c用法: /seen <玩家名>" - admin-menu-title: "&6EssentialsC 管理菜单" - admin-time-control: "&e时间控制" - admin-weather-control: "&e天气控制" - admin-heal-self: "&a治疗自己" - admin-feed-self: "&a喂饱自己" - admin-repair-hand: "&a修复手中物品" - admin-vanish: "&d隐身模式" - admin-reload: "&d重载插件" + # 管理员菜单操作提示 admin-time-set: "&a时间已设置!" admin-weather-set: "&a天气已设置!" admin-heal-success: "&a已治疗!" diff --git a/src/main/resources/paper-plugin.yml b/src/main/resources/paper-plugin.yml index b3b5257..6e2cb64 100644 --- a/src/main/resources/paper-plugin.yml +++ b/src/main/resources/paper-plugin.yml @@ -67,6 +67,9 @@ permissions: essentialsc.command.help: description: Allows use of /essentialsc help command default: true + essentialsc.command.reload: + description: Allows use of /essc reload command + default: op essentialsc.*: description: All EssentialsC permissions default: false @@ -87,6 +90,7 @@ permissions: essentialsc.command.vanish: true essentialsc.command.seen: true essentialsc.command.admin: true + essentialsc.command.reload: true essentialsc.command.feed: true essentialsc.command.repair: true essentialsc.command.help: true