From 9a4d2a462c02c2c3d82ecba7c969edf25fb1849f Mon Sep 17 00:00:00 2001 From: zhangyuheng Date: Fri, 16 Feb 2024 20:40:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E9=80=9A=E8=BF=87ui?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E5=88=9B=E5=BB=BA=E7=8E=A9=E5=AE=B6=E7=89=B9?= =?UTF-8?q?=E6=9D=83=E7=9A=84=E9=80=94=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 54 +++++++++++++++++++ pom.xml | 2 +- resource/frame.drawio | 1 + .../java/cn/lunadeer/dominion/Commands.java | 10 +++- .../dominion/commands/PlayerPrivilege.java | 52 ++++++++++++++++-- .../controllers/PrivilegeController.java | 41 ++++++++++++-- .../cn/lunadeer/dominion/dtos/PlayerDTO.java | 2 +- .../dominion/dtos/PlayerPrivilegeDTO.java | 39 ++++++++++++-- .../java/cn/lunadeer/dominion/tuis/Apis.java | 7 +-- .../dominion/tuis/DominionPrivilegeList.java | 7 +-- .../lunadeer/dominion/tuis/SelectPlayer.java | 37 +++++++++++++ 11 files changed, 228 insertions(+), 24 deletions(-) create mode 100644 README.md create mode 100644 resource/frame.drawio create mode 100644 src/main/java/cn/lunadeer/dominion/tuis/SelectPlayer.java diff --git a/README.md b/README.md new file mode 100644 index 0000000..8dae5ae --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# Dominion + +## 简介 + +鉴于 Residence 插件的作者项目较多,维护压力大,无法及时跟进新版本以及适配Folia核心。故开发此插件,旨在平替纯净版生存服Residence的使用。 + +## 说明 + +本插件基本还原了Residence的核心功能,主要适用于原版纯净生存服务器的防破坏目的,因此暂不考虑引入价格系统、商店等非原版Minecraft玩法。 + +![](https://ssl.lunadeer.cn:14437/i/2024/02/16/65cf3b08c986b.png) + +为了提高存储效率,本插件使用了数据库+缓存的方式存储领地数据,玩家配置领地权限直接修改数据库内容,随后触发缓存更新。权限控制则以异步的方式访问缓存,减少事件阻塞。 + +权限系统主要由领地权限、玩家特权组成,玩家特权优先级高于领地权限。没有特权的玩家在领地内收到领地权限的控制,有特权配置则按照特权设置受控。 + +## 功能介绍 + +- 使用 Postgresql 存储数据; +- 支持BlueMap卫星地图渲染; +- 可视化领地权限配置; +- 支持为玩家单独设置特权; +- 支持设置领地管理员; +- 支持子领地; + +## 支持版本 + +- 1.20.1+ (Paper、Folia) + +## 安装方法 + +1. 将插件放入服务器的 `plugins` 目录下 +2. 重启服务器 +3. 在 `plugins/XXXXXXX/config.yml` 中配置 +4. 重启服务器 + +## 玩家使用方法 + +## 管理员指南 + +## 指令 + +### 玩家指令 + +### 管理员指令 + +## 配置文件参考 + +```yaml +``` + +## TODO + +- WebUI diff --git a/pom.xml b/pom.xml index dfe28f3..4574063 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ cn.lunadeer Dominion - 1.0-beta + 1.2-beta jar Dominion diff --git a/resource/frame.drawio b/resource/frame.drawio new file mode 100644 index 0000000..bde19ed --- /dev/null +++ b/resource/frame.drawio @@ -0,0 +1 @@ +7ZvbcuI4EIafhstQtmUbc5lAmJmtbG1qM1uzuRS2bDQRFiOL0z79tmwZbGQSpjiEpHxDUEvW8dOvVpt00GC6+iLwbPInjwjrOFa06qBhx3ECx4ZPZVgXBg+5hSERNCpM1tbwRP8jhdEurXMakUzbCpPknEk6qxtDnqYklDUbFoIv68VizqKaYYYTYhieQsxM6w8ayUlhdf2gkvGV0GSim0bI0j2f4rK0NmQTHPFlxYTuO2ggOJfFt+lqQJiavPrEjPbkbjogSCoPeeD5ORn80ROPv5bu37b1kL746/im7NwCs7kesu6tXJdzQCKYEp3kQk54wlPM7rfWO8HnaURUOxakshciQzV2GxITHE7mgnzBMzC4YPhJkySvCibgLpyLBRlRKWma6Ae2LTxwPtPGn0TKtaYDzyVXFcsp07kxT+UITylTkN2KcEIlsJDBKKAwLA0RutATn4tQ1TGREgACGm/hA2ZMfagCWTfhHLqHZzTrhnyaZ4RZXnQUF03A11ojnnO320zRUdtXkyGxkLeKRLCEDGcZDUvziLJyCMWkq5neu7ralJVj2Lekgd4mWCREvlLORhsIYfcSPiVSwOgsQRiWdFHvCNb7KNmU04/C0PC6UmDGaapmZVPzozJAAa0IvuUVNWpBQP4Otbvl/VfLw5eiB2WqMpStKd8Jv7ErAmNTfP/nm7EvttSrFVwqIJ5mOF+bpVC8Vxk9blNcKeGO2u4xUDzgjIt8VlAcx05YIC74C6nkRP7Y9/wN7AsiJFm9jrtJp37A86w6FqXsLrcqbZeHyKQi0K61H+gKVL/PTDmGVkk/jZKW/FyplPacDyCltulg/CDjVk2vSk393rWpKbINQK5ePGGyxfpf3XqeeFaJrlcmh6tq5nCtU1eKoym6KU/JjuJaJ1bc8o73puI6RyruUXTa5lk/xBKPcUZaXTtI14gdeaTXpGt9v4fwmbxEt2fqGoidqWv+uXTNdgxyBrDMLTYnw0YBQ0PMbhlNUsiTSr1PAVPQexsmFFwSpr6pQt//ylqUDkIJQAoitwmlwBkj/0QKFPTr0HgNnhVyG6BxzuZZtRG/T3dPRYd6TXtgvYzX5PZa0C7tm5M0MlEE4zlBPDYOYgQuAsfu1kMXbj8oLWU1Bfz6yR1STxDHcM2YsBTAG6yM4zOYp7uxqLHt/5qrNzv5qt1k+bIBEZbtzVb5pJf58C1Rf+ezCEvTD1Tr8oDHhNW5xNq7CWGNcjh23Z4pjaJiAxFoHI/z+hQROqoElXt3HW+4w5V3KPN7z0b9Jk632NkcZFWeXpGHvSfpjdW1dwJeN7rJI/FyapU6O1zxOM7IWZAqZbt6F4CpF5wxRVXrxR0SHwtC0hwfGwee61mvkXrE24bg3e+RnsHO/YLocHHLzdvePyZB3MiNHwZkHJ/nytgUV228Mp4vrtr/eD5YG1c92jFDzoE3BHSsB3fcDQF9ZDq7th1UCbXf4DNPPRJBYfIUJB8L2v0328qdQ5O9vXC8F9fFefleXJfdrJzWI5pG1ZtDcQkY8ilNKU/bU/yKvD/jFPfNU7zfcIj3z3WIu20I73OdzofG74ofz76bipn31W+ZqWG3EWhYK2BXJGD94G0B611UwNrfyn0uAXMPFbD3dcNcA7uvuEHBHgVdUEZgYowsroK8KZetvl2RvtnWAR5aU5jlbAKHzPDc1rXfZWrEcNLG7a4KKPtyQEFy+z9AxauF7X9Sofv/AQ== \ No newline at end of file diff --git a/src/main/java/cn/lunadeer/dominion/Commands.java b/src/main/java/cn/lunadeer/dominion/Commands.java index be54351..89fd6c3 100644 --- a/src/main/java/cn/lunadeer/dominion/Commands.java +++ b/src/main/java/cn/lunadeer/dominion/Commands.java @@ -99,6 +99,9 @@ public class Commands implements TabExecutor { case "set": DominionFlag.setDominionFlag(sender, args); break; + case "create_privilege": + PlayerPrivilege.createPlayerPrivilege(sender, args); + break; case "set_privilege": PlayerPrivilege.setPlayerPrivilege(sender, args); break; @@ -111,6 +114,9 @@ public class Commands implements TabExecutor { case "privilege_info": PrivilegeInfo.show(sender, args); break; + case "select_player_create_privilege": + SelectPlayer.show(sender, args); + break; default: return false; } @@ -135,7 +141,7 @@ public class Commands implements TabExecutor { 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", "list", "privilege_info" + "create_privilege", "set_privilege", "clear_privilege", "list", "privilege_info" ); } if (args.length == 2) { @@ -154,6 +160,7 @@ public class Commands implements TabExecutor { return playerDominions(sender); case "set": return dominionFlags(); + case "create_privilege": case "set_privilege": case "clear_privilege": case "privilege_info": @@ -175,6 +182,7 @@ public class Commands implements TabExecutor { case "expand": case "contract": case "clear_privilege": + case "create_privilege": case "privilege_info": case "auto_create_sub": case "create_sub": diff --git a/src/main/java/cn/lunadeer/dominion/commands/PlayerPrivilege.java b/src/main/java/cn/lunadeer/dominion/commands/PlayerPrivilege.java index 6fa1e11..3119245 100644 --- a/src/main/java/cn/lunadeer/dominion/commands/PlayerPrivilege.java +++ b/src/main/java/cn/lunadeer/dominion/commands/PlayerPrivilege.java @@ -1,5 +1,6 @@ package cn.lunadeer.dominion.commands; +import cn.lunadeer.dominion.tuis.DominionPrivilegeList; import cn.lunadeer.dominion.tuis.PrivilegeInfo; import cn.lunadeer.dominion.utils.Notification; import org.bukkit.command.CommandSender; @@ -8,9 +9,44 @@ import org.bukkit.entity.Player; import static cn.lunadeer.dominion.commands.Apis.playerOnly; import static cn.lunadeer.dominion.controllers.PrivilegeController.clearPrivilege; import static cn.lunadeer.dominion.controllers.PrivilegeController.setPrivilege; +import static cn.lunadeer.dominion.controllers.PrivilegeController.createPrivilege; public class PlayerPrivilege { + /** + * 创建玩家特权 + * /dominion create_privilege <玩家名称> [领地名称] + * + * @param sender 命令发送者 + * @param args 命令参数 + */ + public static void createPlayerPrivilege(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + if (args.length != 2 && args.length != 3 && args.length != 4) { + Notification.error(sender, "用法: /dominion create_privilege <玩家名称> [领地名称]"); + return; + } + if (args.length == 2) { + if (!createPrivilege(player, args[1])) { + Notification.error(sender, "创建玩家特权失败"); + return; + } + } else { + if (!createPrivilege(player, args[1], args[2])) { + Notification.error(sender, "创建玩家特权失败"); + return; + } + } + Notification.info(sender, "成功创建玩家特权 " + args[1]); + if (args.length == 4) { + String[] newArgs = new String[3]; + newArgs[0] = "privilege_list"; + newArgs[1] = args[2]; + DominionPrivilegeList.show(sender, newArgs); + } + } + /** * 设置玩家权限 * /dominion set_privilege <玩家名称> <权限名称> [领地名称] @@ -61,20 +97,28 @@ public class PlayerPrivilege { public static void clearPlayerPrivilege(CommandSender sender, String[] args) { Player player = playerOnly(sender); if (player == null) return; - if (args.length != 2 && args.length != 3) { + if (args.length != 2 && args.length != 3 && args.length != 4) { Notification.error(sender, "用法: /dominion clear_privilege <玩家名称> [领地名称]"); return; } if (args.length == 2) { - if (clearPrivilege(player, args[1])) { + if (!clearPrivilege(player, args[1])) { + Notification.error(sender, "重置玩家权限失败"); return; } } else { - if (clearPrivilege(player, args[1], args[2])) { + if (!clearPrivilege(player, args[1], args[2])) { + Notification.error(sender, "重置玩家权限失败"); return; } } - Notification.error(sender, "重置玩家权限失败"); + Notification.info(sender, "成功清除玩家权限 " + args[1]); + if (args.length == 4) { + String[] newArgs = new String[3]; + newArgs[0] = "privilege_list"; + newArgs[1] = args[2]; + DominionPrivilegeList.show(sender, newArgs); + } } } diff --git a/src/main/java/cn/lunadeer/dominion/controllers/PrivilegeController.java b/src/main/java/cn/lunadeer/dominion/controllers/PrivilegeController.java index 948d79b..e6038f9 100644 --- a/src/main/java/cn/lunadeer/dominion/controllers/PrivilegeController.java +++ b/src/main/java/cn/lunadeer/dominion/controllers/PrivilegeController.java @@ -9,6 +9,7 @@ import org.bukkit.entity.Player; import java.util.UUID; import static cn.lunadeer.dominion.controllers.Apis.noAuthToChangeFlags; +import static cn.lunadeer.dominion.controllers.Apis.notOwner; public class PrivilegeController { @@ -21,7 +22,10 @@ public class PrivilegeController { */ public static boolean clearPrivilege(Player operator, String player_name) { DominionDTO dominion = Apis.getPlayerCurrentDominion(operator); - if (dominion == null) return false; + if (dominion == null) { + Notification.error(operator, "你不在任何领地内,请指定领地名称 /dominion clear_privilege <玩家名称> <领地名称>"); + return false; + } return clearPrivilege(operator, player_name, dominion.getName()); } @@ -60,7 +64,10 @@ public class PrivilegeController { */ public static boolean setPrivilege(Player operator, String player_name, String flag, boolean value) { DominionDTO dominion = Apis.getPlayerCurrentDominion(operator); - if (dominion == null) return false; + if (dominion == null) { + Notification.error(operator, "你不在任何领地内,请指定领地名称 /dominion set_privilege <玩家名称> <权限名称> [领地名称]"); + return false; + } return setPrivilege(operator, player_name, flag, value, dominion.getName()); } @@ -199,6 +206,30 @@ public class PrivilegeController { return true; } + public static boolean createPrivilege(Player operator, String player_name) { + DominionDTO dominion = Apis.getPlayerCurrentDominion(operator); + if (dominion == null) { + Notification.error(operator, "你不在任何领地内,请指定领地名称 /dominion create_privilege <玩家名称> <领地名称>"); + return false; + } + return createPrivilege(operator, player_name, dominion.getName()); + } + + public static boolean createPrivilege(Player operator, String player_name, String dominionName) { + DominionDTO dominion = DominionDTO.select(dominionName); + if (dominion == null) { + Notification.error(operator, "领地 " + dominionName + " 不存在,无法设置特权"); + return false; + } + if (notOwner(operator, dominion)) return false; + PlayerDTO player = PlayerController.getPlayerDTO(player_name); + if (player == null) { + Notification.error(operator, "玩家 " + player_name + " 不存在或没有登录过"); + return false; + } + return createPlayerPrivilege(operator, player.getUuid(), dominion) != null; + } + private static PlayerPrivilegeDTO createPlayerPrivilege(Player operator, UUID player, DominionDTO dom) { PlayerPrivilegeDTO privilege = new PlayerPrivilegeDTO(player, dom.getId(), dom.getAnchor(), dom.getAnimalKilling(), dom.getAnvil(), @@ -208,7 +239,7 @@ public class PrivilegeController { dom.getEgg(), dom.getEnchant(), dom.getEnderPearl(), dom.getFeed(), dom.getGlow(), - dom.getHoney(), dom.getHook(), + dom.getHarvest(), dom.getHoney(), dom.getHook(), dom.getIgnite(), dom.getLever(), dom.getMonsterKilling(), dom.getMove(), @@ -216,10 +247,10 @@ public class PrivilegeController { dom.getRiding(), dom.getRepeater(), dom.getShear(), dom.getShoot(), dom.getTrade(), - dom.getVehicleDestroy(), dom.getHarvest()); + dom.getVehicleDestroy()); privilege = PlayerPrivilegeDTO.insert(privilege); if (privilege == null) { - Notification.error(operator, "创建玩家特权关联玩家时失败"); + Notification.error(operator, "创建玩家特权失败,可能是此玩家已存在特权"); return null; } return privilege; diff --git a/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java b/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java index 6cc729d..2cba659 100644 --- a/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java +++ b/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java @@ -21,7 +21,7 @@ public class PlayerDTO { } public static List all() { - String sql = "SELECT * FROM player_name;"; + String sql = "SELECT * FROM player_name WHERE id > 0;"; return query(sql); } diff --git a/src/main/java/cn/lunadeer/dominion/dtos/PlayerPrivilegeDTO.java b/src/main/java/cn/lunadeer/dominion/dtos/PlayerPrivilegeDTO.java index b647aa4..7d23ef4 100644 --- a/src/main/java/cn/lunadeer/dominion/dtos/PlayerPrivilegeDTO.java +++ b/src/main/java/cn/lunadeer/dominion/dtos/PlayerPrivilegeDTO.java @@ -12,10 +12,41 @@ import java.util.UUID; public class PlayerPrivilegeDTO { public static PlayerPrivilegeDTO insert(PlayerPrivilegeDTO player) { - String sql = "INSERT INTO player_privilege (player_uuid, admin, dom_id) VALUES (" + - "'" + player.getPlayerUUID() + "', " + - player.getAdmin() + ", " + - player.getDomID() + + String sql = "INSERT INTO player_privilege (player_uuid, admin, dom_id, " + + "anchor, animal_killing, anvil, " + + "beacon, bed, brew, break, button, " + + "cake, container, craft, comparer, " + + "door, dye, " + + "egg, enchant, ender_pearl, " + + "feed, " + + "glow, " + + "harvest, honey, hook, " + + "ignite, " + + "lever, " + + "monster_killing, move, " + + "place, pressure, " + + "riding, repeater, " + + "shear, shoot, " + + "trade, " + + "vehicle_destroy" + + ") VALUES (" + + "'" + player.getPlayerUUID() + "', " + player.getAdmin() + ", " + player.getDomID() + ", " + + player.getAnchor() + ", " + player.getAnimalKilling() + ", " + player.getAnvil() + ", " + + player.getBeacon() + ", " + player.getBed() + ", " + player.getBrew() + ", " + player.getBreak() + ", " + player.getButton() + ", " + + player.getCake() + ", " + player.getContainer() + ", " + player.getCraft() + ", " + player.getComparer() + ", " + + player.getDoor() + ", " + player.getDye() + ", " + + player.getEgg() + ", " + player.getEnchant() + ", " + player.getEnderPearl() + ", " + + player.getFeed() + ", " + + player.getGlow() + ", " + + player.getHarvest() + ", " + player.getHoney() + ", " + player.getHook() + ", " + + player.getIgnite() + ", " + + player.getLever() + ", " + + player.getMonsterKilling() + ", " + player.getMove() + ", " + + player.getPlace() + ", " + player.getPressure() + ", " + + player.getRiding() + ", " + player.getRepeater() + ", " + + player.getShear() + ", " + player.getShoot() + ", " + + player.getTrade() + ", " + + player.getVehicleDestroy() + ") RETURNING *;"; List players = query(sql); if (players.size() == 0) return null; diff --git a/src/main/java/cn/lunadeer/dominion/tuis/Apis.java b/src/main/java/cn/lunadeer/dominion/tuis/Apis.java index c21e1c8..abb0280 100644 --- a/src/main/java/cn/lunadeer/dominion/tuis/Apis.java +++ b/src/main/java/cn/lunadeer/dominion/tuis/Apis.java @@ -66,10 +66,11 @@ public class Apis { .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 create_privilege <玩家名称> [领地名称]")) + .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 privilege_info <玩家名称> [领地名称] [页码]")) + .add(Line.create().append("查看玩家特权信息").append("/dominion privilege_info <玩家名称> [领地名称] [页码]")) .showOn(player, page); } diff --git a/src/main/java/cn/lunadeer/dominion/tuis/DominionPrivilegeList.java b/src/main/java/cn/lunadeer/dominion/tuis/DominionPrivilegeList.java index a011b60..0070082 100644 --- a/src/main/java/cn/lunadeer/dominion/tuis/DominionPrivilegeList.java +++ b/src/main/java/cn/lunadeer/dominion/tuis/DominionPrivilegeList.java @@ -36,10 +36,6 @@ public class DominionPrivilegeList { ListView view = ListView.create(10, "/dominion privilege_list " + dominion.getName()); if (noAuthToManage(player, dominion)) return; List privileges = PlayerPrivilegeDTO.select(dominion.getId()); - if (privileges.isEmpty()) { - Notification.warn(sender, "领地 " + dominion.getName() + " 没有任何玩家拥有特权"); - return; - } view.title("领地 " + dominion.getName() + " 玩家特权列表"); view.navigator( Line.create() @@ -48,13 +44,14 @@ public class DominionPrivilegeList { .append(Button.create("管理界面", "/dominion manage " + dominion.getName())) .append("特权列表") ); + view.add(Line.create().append(Button.create("选择玩家创建特权", "/dominion select_player_create_privilege " + dominion.getName()))); for (PlayerPrivilegeDTO privilege : privileges) { PlayerDTO p_player = PlayerDTO.select(privilege.getPlayerUUID()); if (p_player == null) continue; view.add(Line.create() .append(p_player.getLastKnownName()) .append(Button.createGreen("管理", "/dominion privilege_info " + p_player.getLastKnownName() + " " + dominion.getName())) - .append(Button.createRed("清空", "/dominion clear_privilege " + p_player.getLastKnownName() + " " + dominion.getName())) + .append(Button.createRed("清除", "/dominion clear_privilege " + p_player.getLastKnownName() + " " + dominion.getName() + " b")) ); } view.showOn(player, page); diff --git a/src/main/java/cn/lunadeer/dominion/tuis/SelectPlayer.java b/src/main/java/cn/lunadeer/dominion/tuis/SelectPlayer.java new file mode 100644 index 0000000..f2650a3 --- /dev/null +++ b/src/main/java/cn/lunadeer/dominion/tuis/SelectPlayer.java @@ -0,0 +1,37 @@ +package cn.lunadeer.dominion.tuis; + +import cn.lunadeer.dominion.controllers.PlayerController; +import cn.lunadeer.dominion.dtos.PlayerDTO; +import cn.lunadeer.dominion.utils.STUI.Button; +import cn.lunadeer.dominion.utils.STUI.Line; +import cn.lunadeer.dominion.utils.STUI.ListView; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.List; + +import static cn.lunadeer.dominion.commands.Apis.playerOnly; + +public class SelectPlayer { + // /dominion select_player_create_privilege <领地名称> [页码] + public static void show(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + int page = 1; + if (args.length == 3) { + try { + page = Integer.parseInt(args[2]); + } catch (Exception ignored) { + } + } + String dominion_name = args[1]; + ListView view = ListView.create(10, "/dominion select_player_create_privilege " + dominion_name); + view.title("选择玩家以创建特权").subtitle("只能选择已经登录过的玩家"); + List players = PlayerController.allPlayers(); + for (PlayerDTO p : players) { + view.add(Line.create(). + append(Button.create(p.getLastKnownName(), + "/dominion create_privilege " + p.getLastKnownName() + " " + dominion_name + " b"))); + } + view.showOn(player, page); + } +}