From 0dd5899b92a2912ded0c63132358c8a9ee8b4b14 Mon Sep 17 00:00:00 2001 From: zhangyuheng Date: Wed, 7 Feb 2024 16:38:37 +0800 Subject: [PATCH] finish most tui command --- .../java/cn/lunadeer/dominion/Commands.java | 229 +++++++++ .../java/cn/lunadeer/dominion/Dominion.java | 7 +- src/main/java/cn/lunadeer/dominion/TUIs.java | 460 ++++++++++++++++++ .../cn/lunadeer/dominion/commands/Helper.java | 73 +++ .../dominion/commands/PrivilegeGroup.java | 107 ++++ .../controllers/DominionController.java | 6 +- .../dominion/controllers/GroupController.java | 54 +- .../controllers/PlayerController.java | 4 + .../cn/lunadeer/dominion/dtos/PlayerDTO.java | 2 +- .../dominion/dtos/PrivilegeTemplateDTO.java | 2 +- .../lunadeer/dominion/utils/STUI/Button.java | 10 + .../dominion/utils/STUI/ListView.java | 8 +- 12 files changed, 936 insertions(+), 26 deletions(-) create mode 100644 src/main/java/cn/lunadeer/dominion/Commands.java create mode 100644 src/main/java/cn/lunadeer/dominion/TUIs.java create mode 100644 src/main/java/cn/lunadeer/dominion/commands/Helper.java create mode 100644 src/main/java/cn/lunadeer/dominion/commands/PrivilegeGroup.java diff --git a/src/main/java/cn/lunadeer/dominion/Commands.java b/src/main/java/cn/lunadeer/dominion/Commands.java new file mode 100644 index 0000000..06f48d9 --- /dev/null +++ b/src/main/java/cn/lunadeer/dominion/Commands.java @@ -0,0 +1,229 @@ +package cn.lunadeer.dominion; + +import cn.lunadeer.dominion.commands.*; +import cn.lunadeer.dominion.controllers.DominionController; +import cn.lunadeer.dominion.controllers.GroupController; +import cn.lunadeer.dominion.controllers.PlayerController; +import cn.lunadeer.dominion.dtos.DominionDTO; +import cn.lunadeer.dominion.dtos.PlayerDTO; +import cn.lunadeer.dominion.dtos.PrivilegeTemplateDTO; +import cn.lunadeer.dominion.utils.Notification; +import cn.lunadeer.dominion.utils.STUI.Line; +import cn.lunadeer.dominion.utils.STUI.ListView; +import cn.lunadeer.dominion.utils.STUI.Pagination; +import cn.lunadeer.dominion.utils.STUI.View; +import net.kyori.adventure.text.TextComponent; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static cn.lunadeer.dominion.commands.Apis.playerOnly; +import static cn.lunadeer.dominion.commands.Helper.*; + +public class Commands implements TabExecutor { + /* + 创建领地: /dominion create <领地名称> + 自动创建领地: /dominion auto_create <领地名称> + 创建子领地: /dominion create_sub <子领地名称> [父领地名称] + 自动创建子领地: /dominion auto_create_sub <子领地名称> [父领地名称] + 扩张领地: /dominion expand [大小] [领地名称] + 缩小领地: /dominion contract [大小] [领地名称] + 删除领地: /dominion delete <领地名称> [force] + 设置领地权限: /dominion set <权限名称> [领地名称] + 设置玩家权限: /dominion set_privilege <玩家名称> <权限名称> [领地名称] + 重置玩家权限: /dominion clear_privilege <玩家名称> [领地名称] + 创建权限组: /dominion create_group <权限组名称> + 删除权限组: /dominion delete_group <权限组名称> + 设置权限组权限: /dominion set_group <权限组名称> <权限名称> + 设置玩家在某个领地归属的权限组: /dominion add_player <玩家名称> <权限组名称> [领地名称] + 删除玩家在某个领地归属的权限组: /dominion remove_player <玩家名称> <权限组名称> [领地名称] + */ + + + /** + * Executes the given command, returning its success. + *
+ * If false is returned, then the "usage" plugin.yml entry for this command + * (if defined) will be sent to the player. + * + * @param sender Source of the command + * @param command Command which was executed + * @param label Alias of the command which was used + * @param args Passed command arguments + * @return true if a valid command, otherwise false + */ + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (args.length == 0) { + return false; + } + switch (args[0]) { + case "menu": + TUIs.menu(sender, args); + break; + case "help": + TUIs.printHelp(sender, args); + break; + case "info": + TUIs.sizeInfo(sender, args); + break; + case "manage": + TUIs.manage(sender, args); + break; + case "flag_info": + TUIs.flagInfo(sender, args); + break; + case "create": + DominionOperate.createDominion(sender, args); + break; + case "auto_create": + DominionOperate.autoCreateDominion(sender, args); + break; + case "create_sub": + DominionOperate.createSubDominion(sender, args); + break; + case "auto_create_sub": + DominionOperate.autoCreateSubDominion(sender, args); + break; + case "expand": + DominionOperate.expandDominion(sender, args); + break; + case "contract": + DominionOperate.contractDominion(sender, args); + break; + case "delete": + DominionOperate.deleteDominion(sender, args); + break; + case "set": + DominionFlag.setDominionFlag(sender, args); + break; + case "set_privilege": + PlayerPrivilege.setPlayerPrivilege(sender, args); + break; + case "clear_privilege": + PlayerPrivilege.clearPlayerPrivilege(sender, args); + break; + case "create_group": + PrivilegeGroup.createGroup(sender, args); + break; + case "delete_group": + PrivilegeGroup.deleteGroup(sender, args); + break; + case "set_group": + PrivilegeGroup.setDominionFlag(sender, args); + break; + case "add_player": + PrivilegeGroup.addPlayer(sender, args); + break; + case "remove_player": + PrivilegeGroup.removePlayer(sender, args); + break; + default: + return false; + } + return true; + } + + /** + * Requests a list of possible completions for a command argument. + * + * @param sender Source of the command. For players tab-completing a + * command inside a command block, this will be the player, not + * the command block. + * @param command Command which was executed + * @param label Alias of the command which was used + * @param args The arguments passed to the command, including final + * partial argument to be completed + * @return A List of possible completions for the final argument, or null + * to default to the command executor + */ + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (args.length == 1) { + return Arrays.asList("menu", "help", "info", "manage", "flag_info", "group_list", "privilege_list", "group", + "create", "auto_create", "create_sub", "auto_create_sub", "expand", "contract", "delete", "set", + "set_privilege", "clear_privilege", "create_group", "delete_group", "set_group", "add_player", + "remove_player" + ); + } + if (args.length == 2) { + switch (args[0]) { + case "help": + case "group": + return Collections.singletonList("页码(可选)"); + case "create": + case "auto_create": + return Collections.singletonList("输入领地名称"); + case "delete": + case "create_sub": + case "auto_create_sub": + case "expand": + case "contract": + case "info": + case "manage": + case "flag_info": + case "group_list": + case "privilege_list": + return playerDominions(sender); + case "set": + return dominionFlags(); + case "set_privilege": + case "clear_privilege": + case "add_player": + case "remove_player": + return playerNames(); + case "create_group": + case "delete_group": + case "set_group": + return playerGroups(sender); + } + } + if (args.length == 3) { + switch (args[0]) { + case "set": + return boolOptions(); + case "set_privilege": + return playerPrivileges(); + case "set_group": + return groupPrivileges(); + case "add_player": + case "remove_player": + return playerGroups(sender); + } + } + if (args.length == 4) { + switch (args[0]) { + case "set": + case "set_privilege": + case "clear_privilege": + case "add_player": + case "remove_player": + return playerDominions(sender); + case "set_group": + return boolOptions(); + } + } + return null; + } + + private static List boolOptions() { + return Arrays.asList("true", "false"); + } + + private static List playerNames() { + List players = PlayerController.allPlayers(); + List names = new ArrayList<>(); + for (PlayerDTO player : players) { + names.add(player.getLastKnownName()); + } + return names; + } +} diff --git a/src/main/java/cn/lunadeer/dominion/Dominion.java b/src/main/java/cn/lunadeer/dominion/Dominion.java index ae8b79e..8c69afa 100644 --- a/src/main/java/cn/lunadeer/dominion/Dominion.java +++ b/src/main/java/cn/lunadeer/dominion/Dominion.java @@ -3,15 +3,13 @@ package cn.lunadeer.dominion; import cn.lunadeer.dominion.utils.ConfigManager; import cn.lunadeer.dominion.utils.Database; import cn.lunadeer.dominion.utils.XLogger; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.plugin.java.JavaPlugin; import org.postgresql.core.Tuple; import java.sql.Connection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.*; public final class Dominion extends JavaPlugin { @@ -22,6 +20,7 @@ public final class Dominion extends JavaPlugin { config = new ConfigManager(this); dbConnection = Database.createConnection(); + Objects.requireNonNull(Bukkit.getPluginCommand("dominion")).setExecutor(new Commands()); XLogger.info("领地插件已启动"); XLogger.info("版本:" + this.getPluginMeta().getVersion()); diff --git a/src/main/java/cn/lunadeer/dominion/TUIs.java b/src/main/java/cn/lunadeer/dominion/TUIs.java new file mode 100644 index 0000000..c99320a --- /dev/null +++ b/src/main/java/cn/lunadeer/dominion/TUIs.java @@ -0,0 +1,460 @@ +package cn.lunadeer.dominion; + +import cn.lunadeer.dominion.commands.Helper; +import cn.lunadeer.dominion.controllers.PlayerController; +import cn.lunadeer.dominion.dtos.DominionDTO; +import cn.lunadeer.dominion.dtos.PlayerDTO; +import cn.lunadeer.dominion.dtos.PlayerPrivilegeDTO; +import cn.lunadeer.dominion.utils.Notification; +import cn.lunadeer.dominion.utils.STUI.Button; +import cn.lunadeer.dominion.utils.STUI.Line; +import cn.lunadeer.dominion.utils.STUI.ListView; +import cn.lunadeer.dominion.utils.STUI.View; +import net.kyori.adventure.text.TextComponent; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.List; + +import static cn.lunadeer.dominion.commands.Apis.playerOnly; +import static cn.lunadeer.dominion.commands.Helper.playerDominions; +import static cn.lunadeer.dominion.controllers.Apis.getPlayerCurrentDominion; + +public class TUIs { + private static int getPage(String[] args) { + int page = 1; + if (args.length == 3) { + try { + page = Integer.parseInt(args[2]); + } catch (Exception e) { + return 1; + } + } + return page; + } + + private static DominionDTO getDominion(Player player, String[] args) { + if (args.length == 3) { + return DominionDTO.select(args[2]); + } else { + return getPlayerCurrentDominion(player); + } + } + + private static boolean noAuthToManage(Player player, DominionDTO dominion) { + if (player.isOp()) return false; + if (!dominion.getOwner().equals(player.getUniqueId())) { + List privileges = PlayerPrivilegeDTO.select(player.getUniqueId(), dominion.getId()); + for (PlayerPrivilegeDTO privilege : privileges) { + if (privilege.getAdmin()) return false; + } + Notification.error(player, "你不是领地 " + dominion.getName() + " 的拥有者或管理员,无权访问此页面"); + return true; + } else { + return false; + } + } + + public static void printHelp(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + int page = getPage(args); + ListView view = ListView.create(5, "/dominion help"); + view.title("领地插件命令帮助") + .add(Line.create().append("打开交互菜单").append(Button.create("/dominion menu", "/dominion menu"))) + .add(Line.create().append("列出所有领地").append(Button.create("/dominion list", "/dominion list"))) + .add(Line.create().append("查看帮助").append(Button.create("/dominion help [页码]", "/dominion help 1"))) + .add(Line.create().append("查看领地信息").append(Button.create("/dominion info [领地名称]", "/dominion info"))) + .add(Line.create().append("查看领地权限信息").append(Button.create("/dominion flag_info <领地名称> [页码]", "/dominion flag_info"))) + .add(Line.create().append("管理领地").append("/dominion manage <领地名称>")) + .add(Line.create().append("创建领地").append("/dominion create <领地名称>")) + .add(Line.create().append("自动创建领地").append("/dominion auto_create <领地名称>")) + .add(Line.create().append("创建子领地").append("/dominion create_sub <子领地名称> [父领地名称]")) + .add(Line.create().append("自动创建子领地").append("/dominion auto_create_sub <子领地名称> [父领地名称]")) + .add(Line.create().append("扩张领地").append("/dominion expand [大小] [领地名称]")) + .add(Line.create().append("缩小领地").append("/dominion contract [大小] [领地名称]")) + .add(Line.create().append("删除领地").append("/dominion delete <领地名称> [force]")) + .add(Line.create().append("设置领地权限").append("/dominion set <权限名称> [领地名称]")) + .add(Line.create().append("设置玩家权限").append("/dominion set_privilege <玩家名称> <权限名称> [领地名称]")) + .add(Line.create().append("重置玩家权限").append("/dominion clear_privilege <玩家名称> [领地名称]")) + .add(Line.create().append("查看领地玩家权限").append("/dominion privilege_list <领地名称> [页码]")) + .add(Line.create().append("查看权限组").append("/dominion group [页码]")) + .add(Line.create().append("创建权限组").append("/dominion create_group <权限组名称>")) + .add(Line.create().append("删除权限组").append("/dominion delete_group <权限组名称>")) + .add(Line.create().append("设置权限组权限").append("/dominion set_group <权限组名称> <权限名称> ")) + .add(Line.create().append("设置玩家在某个领地归属的权限组").append("/dominion add_player <玩家名称> <权限组名称> [领地名称]")) + .add(Line.create().append("删除玩家在某个领地归属的权限组").append("/dominion remove_player <玩家名称> <权限组名称> [领地名称]")) + .add(Line.create().append("查看领地的权限组").append("/dominion group_list <领地名称> [页码]")) + .showOn(player, page); + } + + public static void sizeInfo(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + DominionDTO dominion = getDominion(player, args); + if (dominion == null) { + Notification.error(sender, "你不在任何领地内,请指定领地名称 /dominion info <领地名称>"); + return; + } + PlayerDTO owner = PlayerController.getPlayerDTO(dominion.getOwner()); + Integer x1 = dominion.getX1(); + Integer y1 = dominion.getY1(); + Integer z1 = dominion.getZ1(); + Integer x2 = dominion.getX2(); + Integer y2 = dominion.getY2(); + Integer z2 = dominion.getZ2(); + View view = View.create(); + view.title("领地 " + dominion.getName() + " 的尺寸信息") + .subtitle("领地归属:" + owner.getLastKnownName()) + .addLine(Line.create().append("领地大小:").append((x2 - x1) + " x" + (y2 - y1) + " x" + (z2 - z1))) + .addLine(Line.create().append("中心坐标:").append((x1 + (x2 - x1) / 2) + " " + (y1 + (y2 - y1) / 2) + " " + (z1 + (z2 - z1) / 2))) + .addLine(Line.create().append("垂直高度:").append(String.valueOf(y2 - y1))) + .addLine(Line.create().append("水平面积:").append(String.valueOf((x2 - x1) * (z2 - z1)))) + .addLine(Line.create().append("领地体积:").append(String.valueOf((x2 - x1) * (y2 - y1) * (z2 - z1)))) + .actionBar(Line.create() + .append(Button.create("管理界面", "/dominion manage " + dominion.getName())) + .append(Button.create("权限列表", "/dominion flag_info " + dominion.getName()))) + .showOn(player); + } + + public static void group(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + int page = getPage(args); + // todo + } + + public static void menu(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + Line list = Line.create() + .append(Button.create("我的领地", "/dominion list")) + .append("查看我的领地"); + Line group = Line.create() + .append(Button.create("权限组", "/dominion group")) + .append("管理权限组"); + Line help = Line.create() + .append(Button.create("指令帮助", "/dominion help")) + .append("查看指令帮助"); + View view = View.create(); + view.title("Dominion 领地系统") + .subtitle("主菜单") + .addLine(list) + .addLine(group) + .addLine(help) + .showOn(player); + } + + public static void list(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + int page = getPage(args); + ListView view = ListView.create(5, "/dominion list"); + List dominions = playerDominions(sender); + if (dominions.isEmpty()) { + Notification.warn(sender, "你没有任何领地"); + return; + } + for (String dominion : dominions) { + TextComponent manage = Button.createGreen("管理", "/dominion manage " + dominion); + TextComponent delete = Button.createRed("删除", "/dominion delete " + dominion); + view.add(Line.create().append(dominion).append(manage).append(delete)); + } + view.showOn(player, page); + } + + public static void flagInfo(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + if (args.length < 2) { + Notification.error(sender, "用法: /dominion flag_info <领地名称> [页码]"); + return; + } + DominionDTO dominion = DominionDTO.select(args[1]); + if (dominion == null) { + Notification.error(sender, "领地 " + args[1] + " 不存在"); + return; + } + int page = 1; + if (args.length == 3) { + try { + page = Integer.parseInt(args[2]); + } catch (Exception ignored) { + } + } + ListView view = ListView.create(6, "/dominion flag_info " + dominion.getName()); + view.title("领地 " + dominion.getName() + " 默认权限") + .subtitle(Button.create("前往管理界面", "/dominion manage " + dominion.getName())); + if (dominion.getAnchor()) { + view.add(Line.create().append("重生锚").append(Button.createRed("禁用", "/dominion set anchor false " + dominion.getName()))); + } else { + view.add(Line.create().append("重生锚").append(Button.createGreen("启用", "/dominion set anchor true " + dominion.getName()))); + } + if (dominion.getAnimalKilling()) { + view.add(Line.create().append("动物伤害").append(Button.createRed("禁用", "/dominion set animal_killing false " + dominion.getName()))); + } else { + view.add(Line.create().append("动物伤害").append(Button.createGreen("启用", "/dominion set animal_killing true " + dominion.getName()))); + } + if (dominion.getAnvil()) { + view.add(Line.create().append("使用铁砧").append(Button.createRed("禁用", "/dominion set anvil false " + dominion.getName()))); + } else { + view.add(Line.create().append("使用铁砧").append(Button.createGreen("启用", "/dominion set anvil true " + dominion.getName()))); + } + if (dominion.getBeacon()) { + view.add(Line.create().append("信标交互").append(Button.createRed("禁用", "/dominion set beacon false " + dominion.getName()))); + } else { + view.add(Line.create().append("信标交互").append(Button.createGreen("启用", "/dominion set beacon true " + dominion.getName()))); + } + if (dominion.getBed()) { + view.add(Line.create().append("床交互").append(Button.createRed("禁用", "/dominion set bed false " + dominion.getName()))); + } else { + view.add(Line.create().append("床交互").append(Button.createGreen("启用", "/dominion set bed true " + dominion.getName()))); + } + if (dominion.getBrew()) { + view.add(Line.create().append("使用酿造台").append(Button.createRed("禁用", "/dominion set brew false " + dominion.getName()))); + } else { + view.add(Line.create().append("使用酿造台").append(Button.createGreen("启用", "/dominion set brew true " + dominion.getName()))); + } + if (dominion.getButton()) { + view.add(Line.create().append("使用按钮").append(Button.createRed("禁用", "/dominion set button false " + dominion.getName()))); + } else { + view.add(Line.create().append("使用按钮").append(Button.createGreen("启用", "/dominion set button true " + dominion.getName()))); + } + if (dominion.getCake()) { + view.add(Line.create().append("使用蛋糕").append(Button.createRed("禁用", "/dominion set cake false " + dominion.getName()))); + } else { + view.add(Line.create().append("使用蛋糕").append(Button.createGreen("启用", "/dominion set cake true " + dominion.getName()))); + } + if (dominion.getContainer()) { + view.add(Line.create().append("容器交互").append(Button.createRed("禁用", "/dominion set container false " + dominion.getName()))); + } else { + view.add(Line.create().append("容器交互").append(Button.createGreen("启用", "/dominion set container true " + dominion.getName()))); + } + if (dominion.getCraft()) { + view.add(Line.create().append("合成").append(Button.createRed("禁用", "/dominion set craft false " + dominion.getName()))); + } else { + view.add(Line.create().append("合成").append(Button.createGreen("启用", "/dominion set craft true " + dominion.getName()))); + } + if (dominion.getCreeperExplode()) { + view.add(Line.create().append("苦力怕爆炸").append(Button.createRed("禁用", "/dominion set creeper_explode false " + dominion.getName()))); + } else { + view.add(Line.create().append("苦力怕爆炸").append(Button.createGreen("启用", "/dominion set creeper_explode true " + dominion.getName()))); + } + if (dominion.getDiode()) { + view.add(Line.create().append("中继器交互").append(Button.createRed("禁用", "/dominion set diode false " + dominion.getName()))); + } else { + view.add(Line.create().append("中继器交互").append(Button.createGreen("启用", "/dominion set diode true " + dominion.getName()))); + } + if (dominion.getDoor()) { + view.add(Line.create().append("门交互").append(Button.createRed("禁用", "/dominion set door false " + dominion.getName()))); + } else { + view.add(Line.create().append("门交互").append(Button.createGreen("启用", "/dominion set door true " + dominion.getName()))); + } + if (dominion.getDye()) { + view.add(Line.create().append("染色").append(Button.createRed("禁用", "/dominion set dye false " + dominion.getName()))); + } else { + view.add(Line.create().append("染色").append(Button.createGreen("启用", "/dominion set dye true " + dominion.getName()))); + } + if (dominion.getEgg()) { + view.add(Line.create().append("投掷鸡蛋").append(Button.createRed("禁用", "/dominion set egg false " + dominion.getName()))); + } else { + view.add(Line.create().append("投掷鸡蛋").append(Button.createGreen("启用", "/dominion set egg true " + dominion.getName()))); + } + if (dominion.getEnchant()) { + view.add(Line.create().append("附魔").append(Button.createRed("禁用", "/dominion set enchant false " + dominion.getName()))); + } else { + view.add(Line.create().append("附魔").append(Button.createGreen("启用", "/dominion set enchant true " + dominion.getName()))); + } + if (dominion.getEnderPearl()) { + view.add(Line.create().append("末影珍珠").append(Button.createRed("禁用", "/dominion set ender_pearl false " + dominion.getName()))); + } else { + view.add(Line.create().append("末影珍珠").append(Button.createGreen("启用", "/dominion set ender_pearl true " + dominion.getName()))); + } + if (dominion.getFeed()) { + view.add(Line.create().append("喂食").append(Button.createRed("禁用", "/dominion set feed false " + dominion.getName()))); + } else { + view.add(Line.create().append("喂食").append(Button.createGreen("启用", "/dominion set feed true " + dominion.getName()))); + } + if (dominion.getFireSpread()) { + view.add(Line.create().append("火焰蔓延").append(Button.createRed("禁用", "/dominion set fire_spread false " + dominion.getName()))); + } else { + view.add(Line.create().append("火焰蔓延").append(Button.createGreen("启用", "/dominion set fire_spread true " + dominion.getName()))); + } + if (dominion.getFlowInProtection()) { + view.add(Line.create().append("流体保护").append(Button.createRed("禁用", "/dominion set flow_in_protection false " + dominion.getName()))); + } else { + view.add(Line.create().append("流体保护").append(Button.createGreen("启用", "/dominion set flow_in_protection true " + dominion.getName()))); + } + if (dominion.getGlow()) { + view.add(Line.create().append("发光").append(Button.createRed("禁用", "/dominion set glow false " + dominion.getName()))); + } else { + view.add(Line.create().append("发光").append(Button.createGreen("启用", "/dominion set glow true " + dominion.getName()))); + } + if (dominion.getGrow()) { + view.add(Line.create().append("植物生长").append(Button.createRed("禁用", "/dominion set grow false " + dominion.getName()))); + } else { + view.add(Line.create().append("植物生长").append(Button.createGreen("启用", "/dominion set grow true " + dominion.getName()))); + } + if (dominion.getHoney()) { + view.add(Line.create().append("蜂巢交互").append(Button.createRed("禁用", "/dominion set honey false " + dominion.getName()))); + } else { + view.add(Line.create().append("蜂巢交互").append(Button.createGreen("启用", "/dominion set honey true " + dominion.getName()))); + } + if (dominion.getHook()) { + view.add(Line.create().append("钩子交互").append(Button.createRed("禁用", "/dominion set hook false " + dominion.getName()))); + } else { + view.add(Line.create().append("钩子交互").append(Button.createGreen("启用", "/dominion set hook true " + dominion.getName()))); + } + if (dominion.getIgnite()) { + view.add(Line.create().append("点燃").append(Button.createRed("禁用", "/dominion set ignite false " + dominion.getName()))); + } else { + view.add(Line.create().append("点燃").append(Button.createGreen("启用", "/dominion set ignite true " + dominion.getName()))); + } + if (dominion.getMobKilling()) { + view.add(Line.create().append("生物伤害").append(Button.createRed("禁用", "/dominion set mob_killing false " + dominion.getName()))); + } else { + view.add(Line.create().append("生物伤害").append(Button.createGreen("启用", "/dominion set mob_killing true " + dominion.getName()))); + } + if (dominion.getMove()) { + view.add(Line.create().append("移动").append(Button.createRed("禁用", "/dominion set move false " + dominion.getName()))); + } else { + view.add(Line.create().append("移动").append(Button.createGreen("启用", "/dominion set move true " + dominion.getName()))); + } + if (dominion.getPlace()) { + view.add(Line.create().append("放置").append(Button.createRed("禁用", "/dominion set place false " + dominion.getName()))); + } else { + view.add(Line.create().append("放置").append(Button.createGreen("启用", "/dominion set place true " + dominion.getName()))); + } + if (dominion.getPressure()) { + view.add(Line.create().append("压力板交互").append(Button.createRed("禁用", "/dominion set pressure false " + dominion.getName()))); + } else { + view.add(Line.create().append("压力板交互").append(Button.createGreen("启用", "/dominion set pressure true " + dominion.getName()))); + } + if (dominion.getRiding()) { + view.add(Line.create().append("骑乘").append(Button.createRed("禁用", "/dominion set riding false " + dominion.getName()))); + } else { + view.add(Line.create().append("骑乘").append(Button.createGreen("启用", "/dominion set riding true " + dominion.getName()))); + } + if (dominion.getShear()) { + view.add(Line.create().append("剪羊毛").append(Button.createRed("禁用", "/dominion set shear false " + dominion.getName()))); + } else { + view.add(Line.create().append("剪羊毛").append(Button.createGreen("启用", "/dominion set shear true " + dominion.getName()))); + } + if (dominion.getShoot()) { + view.add(Line.create().append("发射").append(Button.createRed("禁用", "/dominion set shoot false " + dominion.getName()))); + } else { + view.add(Line.create().append("发射").append(Button.createGreen("启用", "/dominion set shoot true " + dominion.getName()))); + } + if (dominion.getTntExplode()) { + view.add(Line.create().append("TNT爆炸").append(Button.createRed("禁用", "/dominion set tnt_explode false " + dominion.getName()))); + } else { + view.add(Line.create().append("TNT爆炸").append(Button.createGreen("启用", "/dominion set tnt_explode true " + dominion.getName()))); + } + if (dominion.getTrade()) { + view.add(Line.create().append("交易").append(Button.createRed("禁用", "/dominion set trade false " + dominion.getName()))); + } else { + view.add(Line.create().append("交易").append(Button.createGreen("启用", "/dominion set trade true " + dominion.getName()))); + } + if (dominion.getVehicleDestroy()) { + view.add(Line.create().append("破坏载具").append(Button.createRed("禁用", "/dominion set vehicle_destroy false " + dominion.getName()))); + } else { + view.add(Line.create().append("破坏载具").append(Button.createGreen("启用", "/dominion set vehicle_destroy true " + dominion.getName()))); + } + if (dominion.getWitherSpawn()) { + view.add(Line.create().append("凋零生成").append(Button.createRed("禁用", "/dominion set wither_spawn false " + dominion.getName()))); + } else { + view.add(Line.create().append("凋零生成").append(Button.createGreen("启用", "/dominion set wither_spawn true " + dominion.getName()))); + } + if (dominion.getHarvest()) { + view.add(Line.create().append("收获").append(Button.createRed("禁用", "/dominion set harvest false " + dominion.getName()))); + } else { + view.add(Line.create().append("收获").append(Button.createGreen("启用", "/dominion set harvest true " + dominion.getName()))); + } + view.showOn(player, page); + } + + public static void manage(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + DominionDTO dominion = getDominion(player, args); + if (dominion == null) { + Notification.error(sender, "你不在任何领地内,请指定领地名称 /dominion manage <领地名称>"); + return; + } + if (noAuthToManage(player, dominion)) return; + Line size_info = Line.create() + .append(Button.create("尺寸信息", "/dominion info " + dominion.getName())) + .append("查看领地尺寸信息"); + Line flag_info = Line.create() + .append(Button.create("权限设置", "/dominion flag_info " + dominion.getName())) + .append("管理领地默认权限"); + Line group_info = Line.create() + .append(Button.create("权限组", "/dominion group_list " + dominion.getName())) + .append("管理领地权限组"); + Line privilege_list = Line.create() + .append(Button.create("玩家权限", "/dominion privilege_list " + dominion.getName())) + .append("管理玩家特权"); + View view = View.create(); + view.title("领地 " + dominion.getName() + " 管理界面") + .subtitle(Button.createRed("领地列表", "/dominion list")) + .addLine(size_info) + .addLine(flag_info) + .addLine(group_info) + .addLine(privilege_list) + .showOn(player); + } + + public static void groupList(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + if (args.length < 2) { + Notification.error(sender, "用法: /dominion group_list <领地名称> [页码]"); + return; + } + DominionDTO dominion = DominionDTO.select(args[1]); + if (dominion == null) { + Notification.error(sender, "领地 " + args[1] + " 不存在"); + return; + } + if (noAuthToManage(player, dominion)) return; + int page = 1; + if (args.length == 3) { + try { + page = Integer.parseInt(args[2]); + } catch (Exception ignored) { + } + } + ListView view = ListView.create(6, "/dominion group_list " + dominion.getName()); + view.title("领地 " + dominion.getName() + " 权限组信息") + .subtitle(Button.create("返回管理界面", "/dominion manage " + dominion.getName())); + // todo + view.showOn(player, page); + } + + public static void privilegeList(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + if (args.length < 2) { + Notification.error(sender, "用法: /dominion privilege_list <领地名称> [页码]"); + return; + } + DominionDTO dominion = DominionDTO.select(args[1]); + if (dominion == null) { + Notification.error(sender, "领地 " + args[1] + " 不存在"); + return; + } + if (noAuthToManage(player, dominion)) return; + int page = 1; + if (args.length == 3) { + try { + page = Integer.parseInt(args[2]); + } catch (Exception ignored) { + } + } + ListView view = ListView.create(6, "/dominion privilege_list " + dominion.getName()); + view.title("领地 " + dominion.getName() + " 玩家权限信息") + .subtitle(Button.create("返回管理界面", "/dominion manage " + dominion.getName())); + // todo + view.showOn(player, page); + } +} diff --git a/src/main/java/cn/lunadeer/dominion/commands/Helper.java b/src/main/java/cn/lunadeer/dominion/commands/Helper.java new file mode 100644 index 0000000..4158ed8 --- /dev/null +++ b/src/main/java/cn/lunadeer/dominion/commands/Helper.java @@ -0,0 +1,73 @@ +package cn.lunadeer.dominion.commands; + +import cn.lunadeer.dominion.controllers.DominionController; +import cn.lunadeer.dominion.controllers.GroupController; +import cn.lunadeer.dominion.controllers.PlayerController; +import cn.lunadeer.dominion.dtos.DominionDTO; +import cn.lunadeer.dominion.dtos.PlayerDTO; +import cn.lunadeer.dominion.dtos.PrivilegeTemplateDTO; +import cn.lunadeer.dominion.utils.Notification; +import cn.lunadeer.dominion.utils.STUI.Button; +import cn.lunadeer.dominion.utils.STUI.Line; +import cn.lunadeer.dominion.utils.STUI.ListView; +import cn.lunadeer.dominion.utils.STUI.View; +import net.kyori.adventure.text.TextComponent; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static cn.lunadeer.dominion.commands.Apis.playerOnly; +import static cn.lunadeer.dominion.controllers.Apis.getPlayerCurrentDominion; + +public class Helper { + + public static List dominionFlags() { + return Arrays.asList( + "anchor", "animal_killing", "anvil", "beacon", "bed", "brew", "button", "cake", "container", "craft", + "creeper_explode", "diode", "door", "dye", "egg", "enchant", "ender_pearl", "feed", "fire_spread", + "flow_in_protection", "glow", "grow", "honey", "hook", "ignite", "mob_killing", "move", "place", + "pressure", "riding", "shear", "shoot", "tnt_explode", "trade", "vehicle_destroy", "wither_spawn", + "harvest"); + } + + public static List groupPrivileges() { + return Arrays.asList( + "anchor", "animal_killing", "anvil", "beacon", "bed", "brew", "button", "cake", "container", "craft", + "diode", "door", "dye", "egg", "enchant", "ender_pearl", "feed", "glow", "honey", "hook", "ignite", + "mob_killing", "move", "place", "pressure", "riding", "shear", "shoot", "trade", "vehicle_destroy", + "harvest"); + } + + public static List playerPrivileges() { + List privileges = new ArrayList<>(groupPrivileges()); + privileges.add("admin"); + return privileges; + } + + public static List playerDominions(CommandSender sender) { + List dominions_name = new ArrayList<>(); + Player player = playerOnly(sender); + if (player == null) return dominions_name; + List dominions = DominionController.all(player); + for (DominionDTO dominion : dominions) { + dominions_name.add(dominion.getName()); + } + return dominions_name; + } + + public static List playerGroups(CommandSender sender) { + List groups_name = new ArrayList<>(); + Player player = playerOnly(sender); + if (player == null) return groups_name; + List groups = GroupController.all(player); + for (PrivilegeTemplateDTO group : groups) { + groups_name.add(group.getName()); + } + return groups_name; + } + + +} diff --git a/src/main/java/cn/lunadeer/dominion/commands/PrivilegeGroup.java b/src/main/java/cn/lunadeer/dominion/commands/PrivilegeGroup.java new file mode 100644 index 0000000..a072587 --- /dev/null +++ b/src/main/java/cn/lunadeer/dominion/commands/PrivilegeGroup.java @@ -0,0 +1,107 @@ +package cn.lunadeer.dominion.commands; + +import cn.lunadeer.dominion.controllers.FlagsController; +import cn.lunadeer.dominion.controllers.GroupController; +import cn.lunadeer.dominion.controllers.PlayerController; +import cn.lunadeer.dominion.dtos.PlayerDTO; +import cn.lunadeer.dominion.utils.Notification; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import static cn.lunadeer.dominion.commands.Apis.playerOnly; + +public class PrivilegeGroup { + + /** + * 创建权限组 + * /dominion create_group <权限组名称> + * + * @param sender 命令发送者 + * @param args 命令参数 + */ + public static void createGroup(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + if (args.length != 2) { + Notification.error(sender, "用法: /dominion create_group <权限组名称>"); + return; + } + GroupController.create(player, args[1]); + } + + /** + * 删除权限组 + * /dominion delete_group <权限组名称> + * + * @param sender 命令发送者 + * @param args 命令参数 + */ + public static void deleteGroup(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + if (args.length != 2) { + Notification.error(sender, "用法: /dominion delete_group <权限组名称>"); + return; + } + GroupController.delete(player, args[1]); + } + + /** + * 设置权限组权限 + * /dominion set_group <权限组名称> <权限名称> + * + * @param sender 命令发送者 + * @param args 命令参数 + */ + public static void setDominionFlag(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + if (args.length != 4) { + Notification.error(sender, "用法: /dominion set_group <权限组名称> <权限名称> "); + return; + } + GroupController.setFlag(player, args[1], args[2], Boolean.parseBoolean(args[3])); + } + + /** + * 设置玩家在某个领地归属的权限组 + * /dominion add_player <玩家名称> <权限组名称> [领地名称] + * + * @param sender 命令发送者 + * @param args 命令参数 + */ + public static void addPlayer(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + if (args.length != 3 && args.length != 4) { + Notification.error(sender, "用法: /dominion add_player <玩家名称> <权限组名称> [领地名称]"); + return; + } + if (args.length == 3) { + GroupController.addPlayer(player, args[1], args[2]); + } else { + GroupController.addPlayer(player, args[1], args[2], args[3]); + } + } + + /** + * 删除玩家在某个领地归属的权限组 + * /dominion remove_player <玩家名称> <权限组名称> [领地名称] + * + * @param sender 命令发送者 + * @param args 命令参数 + */ + public static void removePlayer(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + if (args.length != 3 && args.length != 4) { + Notification.error(sender, "用法: /dominion remove_player <玩家名称> <权限组名称> [领地名称]"); + return; + } + if (args.length == 3) { + GroupController.removePlayer(player, args[1], args[2]); + } else { + GroupController.removePlayer(player, args[1], args[2], args[3]); + } + } +} diff --git a/src/main/java/cn/lunadeer/dominion/controllers/DominionController.java b/src/main/java/cn/lunadeer/dominion/controllers/DominionController.java index c8d8e37..10e265c 100644 --- a/src/main/java/cn/lunadeer/dominion/controllers/DominionController.java +++ b/src/main/java/cn/lunadeer/dominion/controllers/DominionController.java @@ -15,6 +15,10 @@ import static cn.lunadeer.dominion.controllers.Apis.notOwner; public class DominionController { + public static List all(Player owner){ + return DominionDTO.selectAll(owner.getUniqueId()); + } + /** * 创建领地 * @@ -310,7 +314,7 @@ public class DominionController { sub_names = sub_names.substring(0, sub_names.length() - 2); Notification.warn(operator, "当前子领地(不包含子领地的子领地等):" + sub_names); } - Notification.warn(operator, "输入 /dominion force_delete " + dominion_name + " 确认删除"); + Notification.warn(operator, "输入 /dominion delete " + dominion_name + " force 确认删除"); return; } DominionDTO.delete(dominion); diff --git a/src/main/java/cn/lunadeer/dominion/controllers/GroupController.java b/src/main/java/cn/lunadeer/dominion/controllers/GroupController.java index 2b56551..e3cb3ec 100644 --- a/src/main/java/cn/lunadeer/dominion/controllers/GroupController.java +++ b/src/main/java/cn/lunadeer/dominion/controllers/GroupController.java @@ -1,17 +1,23 @@ package cn.lunadeer.dominion.controllers; import cn.lunadeer.dominion.dtos.DominionDTO; +import cn.lunadeer.dominion.dtos.PlayerDTO; import cn.lunadeer.dominion.dtos.PlayerPrivilegeDTO; import cn.lunadeer.dominion.dtos.PrivilegeTemplateDTO; import cn.lunadeer.dominion.utils.Notification; import org.bukkit.entity.Player; +import java.util.List; import java.util.UUID; import static cn.lunadeer.dominion.controllers.Apis.noAuthToChangeFlags; public class GroupController { + public static List all(Player owner) { + return PrivilegeTemplateDTO.selectGroup(owner.getUniqueId()); + } + /** * 创建权限组 * @@ -57,80 +63,87 @@ public class GroupController { return false; } if (!Apis.updateTemplateFlag(privilege, flag, value)) { - Notification.error(operator, "未知的领地权限 " + flag); + Notification.error(operator, "未知的权限组权限 " + flag); return false; } + Notification.info(operator, "设置权限组 " + name + " 权限 " + flag + " 为 " + value); return true; } /** * 添加玩家到权限组 * - * @param operator 操作者 - * @param player 玩家 - * @param groupName 权限组名称 + * @param operator 操作者 + * @param player_name 玩家 + * @param groupName 权限组名称 * @return 是否添加成功 */ - public static boolean addPlayer(Player operator, UUID player, String groupName) { + public static boolean addPlayer(Player operator, String player_name, String groupName) { DominionDTO dominion = Apis.getPlayerCurrentDominion(operator); if (dominion == null) return false; - return addPlayer(operator, player, groupName, dominion.getName()); + return addPlayer(operator, player_name, groupName, dominion.getName()); } /** * 添加玩家到权限组 * * @param operator 操作者 - * @param player 玩家 + * @param player_name 玩家 * @param groupName 权限组名称 * @param dominionName 领地名称 * @return 是否添加成功 */ - public static boolean addPlayer(Player operator, UUID player, String groupName, String dominionName) { + public static boolean addPlayer(Player operator, String player_name, String groupName, String dominionName) { PrivilegeTemplateDTO template = PrivilegeTemplateDTO.select(operator.getUniqueId(), groupName); if (template == null) { Notification.error(operator, "没有找到权限组 " + groupName + " 或者需要先创建权限组"); return false; } + PlayerDTO player = PlayerDTO.select(player_name); + if (player == null) { + Notification.error(operator, "玩家 " + player_name + " 不存在或没有登录过"); + return false; + } DominionDTO dominion = DominionDTO.select(dominionName); if (dominion == null) { Notification.error(operator, "领地 " + dominionName + " 不存在"); return false; } if (noAuthToChangeFlags(operator, dominion)) return false; - PlayerPrivilegeDTO privilege = new PlayerPrivilegeDTO(player, false, dominion.getId(), template.getId()); + PlayerPrivilegeDTO privilege = new PlayerPrivilegeDTO(player.getUuid(), false, dominion.getId(), template.getId()); privilege = PlayerPrivilegeDTO.insert(privilege); if (privilege == null) { - Notification.error(operator, "添加玩家 " + player + " 到权限组 " + groupName + " 失败"); + Notification.error(operator, "设置玩家" + player.getLastKnownName() + "在领地 " + dominionName + " 归属权限组 " + groupName + " 失败"); return false; } + Notification.info(operator, "设置玩家" + player.getLastKnownName() + "在领地 " + dominionName + " 归属权限组 " + groupName); return true; } /** * 从权限组中移除玩家 * - * @param operator 操作者 - * @param player 玩家 - * @param groupName 权限组名称 + * @param operator 操作者 + * @param player_name 玩家 + * @param groupName 权限组名称 * @return 是否移除成功 */ - public static boolean removePlayer(Player operator, UUID player, String groupName) { + public static boolean removePlayer(Player operator, String player_name, String groupName) { DominionDTO dominion = Apis.getPlayerCurrentDominion(operator); if (dominion == null) return false; - return removePlayer(operator, player, groupName, dominion.getName()); + return removePlayer(operator, player_name, groupName, dominion.getName()); } /** * 从权限组中移除玩家 * * @param operator 操作者 - * @param player 玩家 + * @param player_name 玩家 * @param groupName 权限组名称 * @param dominionName 领地名称 * @return 是否移除成功 */ - public static boolean removePlayer(Player operator, UUID player, String groupName, String dominionName) { + public static boolean removePlayer(Player operator, String player_name, String groupName, String dominionName) { PrivilegeTemplateDTO template = PrivilegeTemplateDTO.select(operator.getUniqueId(), groupName); if (template == null) { Notification.error(operator, "没有找到权限组 " + groupName); @@ -142,7 +155,12 @@ public class GroupController { return false; } if (noAuthToChangeFlags(operator, dominion)) return false; - PlayerPrivilegeDTO.delete(player, dominion.getId(), template.getId()); + PlayerDTO player = PlayerDTO.select(player_name); + if (player == null) { + Notification.error(operator, "玩家 " + player_name + " 不存在或没有登录过"); + return false; + } + PlayerPrivilegeDTO.delete(player.getUuid(), dominion.getId(), template.getId()); return true; } } diff --git a/src/main/java/cn/lunadeer/dominion/controllers/PlayerController.java b/src/main/java/cn/lunadeer/dominion/controllers/PlayerController.java index a1e98e6..b924961 100644 --- a/src/main/java/cn/lunadeer/dominion/controllers/PlayerController.java +++ b/src/main/java/cn/lunadeer/dominion/controllers/PlayerController.java @@ -11,6 +11,10 @@ public class PlayerController { return PlayerDTO.select(playerName); } + public static PlayerDTO getPlayerDTO(UUID uuid) { + return PlayerDTO.select(uuid); + } + public static List searchPlayer(String playerName) { return PlayerDTO.search(playerName); } diff --git a/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java b/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java index 12513b8..2f35965 100644 --- a/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java +++ b/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java @@ -48,7 +48,7 @@ public class PlayerDTO { return players; } - private static PlayerDTO select(UUID uuid) { + public static PlayerDTO select(UUID uuid) { String sql = "SELECT * FROM player_name WHERE uuid = '" + uuid.toString() + "'"; List players = query(sql); if (players.size() == 0) return null; diff --git a/src/main/java/cn/lunadeer/dominion/dtos/PrivilegeTemplateDTO.java b/src/main/java/cn/lunadeer/dominion/dtos/PrivilegeTemplateDTO.java index 6e9575e..fb985fc 100644 --- a/src/main/java/cn/lunadeer/dominion/dtos/PrivilegeTemplateDTO.java +++ b/src/main/java/cn/lunadeer/dominion/dtos/PrivilegeTemplateDTO.java @@ -33,7 +33,7 @@ public class PrivilegeTemplateDTO { return query(sql); } - public static List searchGroup(UUID creator){ + public static List selectGroup(UUID creator){ String sql = "SELECT * FROM privilege_template WHERE creator = '" + creator.toString() + "' AND group = true"; return query(sql); } diff --git a/src/main/java/cn/lunadeer/dominion/utils/STUI/Button.java b/src/main/java/cn/lunadeer/dominion/utils/STUI/Button.java index 2048497..0da51e9 100644 --- a/src/main/java/cn/lunadeer/dominion/utils/STUI/Button.java +++ b/src/main/java/cn/lunadeer/dominion/utils/STUI/Button.java @@ -9,4 +9,14 @@ public class Button { return Component.text("[" + text + "]", ViewStyles.action_color) .clickEvent(net.kyori.adventure.text.event.ClickEvent.clickEvent(net.kyori.adventure.text.event.ClickEvent.Action.RUN_COMMAND, command)); } + + public static TextComponent createRed(String text, String command) { + return Component.text("[" + text + "]", ViewStyles.error_color) + .clickEvent(net.kyori.adventure.text.event.ClickEvent.clickEvent(net.kyori.adventure.text.event.ClickEvent.Action.RUN_COMMAND, command)); + } + + public static TextComponent createGreen(String text, String command) { + return Component.text("[" + text + "]", ViewStyles.success_color) + .clickEvent(net.kyori.adventure.text.event.ClickEvent.clickEvent(net.kyori.adventure.text.event.ClickEvent.Action.RUN_COMMAND, command)); + } } diff --git a/src/main/java/cn/lunadeer/dominion/utils/STUI/ListView.java b/src/main/java/cn/lunadeer/dominion/utils/STUI/ListView.java index b45c9cc..ef9a4b8 100644 --- a/src/main/java/cn/lunadeer/dominion/utils/STUI/ListView.java +++ b/src/main/java/cn/lunadeer/dominion/utils/STUI/ListView.java @@ -1,6 +1,7 @@ package cn.lunadeer.dominion.utils.STUI; import cn.lunadeer.dominion.utils.Notification; +import net.kyori.adventure.text.TextComponent; import org.bukkit.entity.Player; import java.util.ArrayList; @@ -13,7 +14,7 @@ public class ListView { private String command = ""; private final View view = View.create(); - public ListView(int page_size, String command) { + private ListView(int page_size, String command) { super(); this.page_size = page_size; this.command = command; @@ -39,6 +40,11 @@ public class ListView { return this; } + public ListView subtitle(TextComponent subtitle) { + view.subtitle(subtitle); + return this; + } + public ListView add(Line line) { lines.add(line); return this;