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);
+ }
+}