diff --git a/README.md b/README.md index 25a26c5..dd9c19d 100644 --- a/README.md +++ b/README.md @@ -30,13 +30,13 @@ ## 功能介绍 -- 支持 Postgresql 或 sqlite 存储数据; +- 支持 Postgresql、Mysql、Sqlite3 存储数据; - 支持BlueMap卫星地图渲染; - 支持为玩家单独设置特权; - 支持设置领地管理员; - 支持子领地; - 采用 TUI 方式进行权限配置交互,简单快捷; -- 支持基础价格系统; +- 支持经济系统(需要 Vault 前置); - 领地区域可视化; - 管理员可在游戏内使用TUI配置领地系统; - 支持[从 Residence 迁移](https://ssl.lunadeer.cn:14448/doc/73/)领地数据; diff --git a/pom.xml b/pom.xml index ffdaabb..8af04cf 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ cn.lunadeer Dominion - 1.32.0-res-migrate-beta + 1.33.6-res-migrate-beta jar Dominion @@ -82,7 +82,7 @@ cn.lunadeer MinecraftPluginUtils - 1.3.1-SNAPSHOT + 1.3.4-SNAPSHOT com.github.BlueMap-Minecraft diff --git a/src/main/java/cn/lunadeer/dominion/BlueMapConnect.java b/src/main/java/cn/lunadeer/dominion/BlueMapConnect.java index f061af8..cee9369 100644 --- a/src/main/java/cn/lunadeer/dominion/BlueMapConnect.java +++ b/src/main/java/cn/lunadeer/dominion/BlueMapConnect.java @@ -1,6 +1,7 @@ package cn.lunadeer.dominion; import cn.lunadeer.dominion.dtos.DominionDTO; +import cn.lunadeer.minecraftpluginutils.Scheduler; import cn.lunadeer.minecraftpluginutils.XLogger; import com.flowpowered.math.vector.Vector2d; import de.bluecolored.bluemap.api.BlueMapAPI; @@ -17,112 +18,116 @@ public class BlueMapConnect { if (!Dominion.config.getBlueMap()) { return; } - try { - BlueMapAPI.getInstance().ifPresent(api -> { - Map> world_dominions = new HashMap<>(); - for (DominionDTO dominion : Cache.instance.getDominions()) { - if (!world_dominions.containsKey(dominion.getWorld())) { - world_dominions.put(dominion.getWorld(), new ArrayList<>()); + Scheduler.runTaskAsync(() -> { + try { + BlueMapAPI.getInstance().ifPresent(api -> { + Map> world_dominions = new HashMap<>(); + for (DominionDTO dominion : Cache.instance.getDominions()) { + if (!world_dominions.containsKey(dominion.getWorld())) { + world_dominions.put(dominion.getWorld(), new ArrayList<>()); + } + world_dominions.get(dominion.getWorld()).add(dominion); } - world_dominions.get(dominion.getWorld()).add(dominion); - } - for (Map.Entry> d : world_dominions.entrySet()) { - api.getWorld(d.getKey()).ifPresent(world -> { - MarkerSet markerSet = MarkerSet.builder() - .label("Dominion") - .build(); - - for (DominionDTO dominion : d.getValue()) { - Collection vectors = new ArrayList<>(); - vectors.add(new Vector2d(dominion.getX1() + 0.001, dominion.getZ1() + 0.001)); - vectors.add(new Vector2d(dominion.getX2() - 0.001, dominion.getZ1() + 0.001)); - vectors.add(new Vector2d(dominion.getX2() - 0.001, dominion.getZ2() - 0.001)); - vectors.add(new Vector2d(dominion.getX1() + 0.001, dominion.getZ2() - 0.001)); - Shape shape = new Shape(vectors); - double x = vectors.iterator().next().getX(); - double z = vectors.iterator().next().getY(); - double y = dominion.getY1(); - - Color line = new Color(0, 191, 255, 0.8F); - Color fill = new Color(0, 191, 255, 0.2F); - if (dominion.getParentDomId() != -1) { // for children dominion - line = new Color(240, 230, 140, 0.8F); - fill = new Color(240, 230, 140, 0.2F); - } - ExtrudeMarker marker = ExtrudeMarker.builder() - .label(dominion.getName()) - .position(x, y, z) - .shape(shape, dominion.getY1() + 0.001f, dominion.getY2() - 0.001f) - .lineColor(line) - .fillColor(fill) + for (Map.Entry> d : world_dominions.entrySet()) { + api.getWorld(d.getKey()).ifPresent(world -> { + MarkerSet markerSet = MarkerSet.builder() + .label("Dominion") .build(); - markerSet.getMarkers() - .put(dominion.getName(), marker); - } - for (BlueMapMap map : world.getMaps()) { - map.getMarkerSets().put(d.getKey() + "-" + markerSet.getLabel(), markerSet); - } - }); - } - }); - } catch (NoClassDefFoundError e) { - XLogger.warn("无法连接 BlueMap 插件,如果你不打算使用卫星地图渲染建议前往配置文件关闭此功能以避免下方的报错。"); - XLogger.err(e.getMessage()); - } + for (DominionDTO dominion : d.getValue()) { + Collection vectors = new ArrayList<>(); + vectors.add(new Vector2d(dominion.getX1() + 0.001, dominion.getZ1() + 0.001)); + vectors.add(new Vector2d(dominion.getX2() - 0.001, dominion.getZ1() + 0.001)); + vectors.add(new Vector2d(dominion.getX2() - 0.001, dominion.getZ2() - 0.001)); + vectors.add(new Vector2d(dominion.getX1() + 0.001, dominion.getZ2() - 0.001)); + Shape shape = new Shape(vectors); + double x = vectors.iterator().next().getX(); + double z = vectors.iterator().next().getY(); + double y = dominion.getY1(); + + int r = dominion.getColorR(); + int g = dominion.getColorG(); + int b = dominion.getColorB(); + + Color line = new Color(r, g, b, 0.8F); + Color fill = new Color(r, g, b, 0.2F); + ExtrudeMarker marker = ExtrudeMarker.builder() + .label(dominion.getName()) + .position(x, y, z) + .shape(shape, dominion.getY1() + 0.001f, dominion.getY2() - 0.001f) + .lineColor(line) + .fillColor(fill) + .build(); + markerSet.getMarkers() + .put(dominion.getName(), marker); + } + + for (BlueMapMap map : world.getMaps()) { + map.getMarkerSets().put(d.getKey() + "-" + markerSet.getLabel(), markerSet); + } + }); + } + }); + } catch (NoClassDefFoundError e) { + XLogger.warn("无法连接 BlueMap 插件,如果你不打算使用卫星地图渲染建议前往配置文件关闭此功能以避免下方的报错。"); + XLogger.err(e.getMessage()); + } + }); } public static void renderMCA(Map> mca_files) { if (!Dominion.config.getBlueMap()) { return; } - try { - BlueMapAPI.getInstance().ifPresent(api -> { - for (String world : mca_files.keySet()) { - api.getWorld(world).ifPresent(bmWorld -> { - MarkerSet markerSet = MarkerSet.builder() - .label("MCA") - .defaultHidden(true) - .build(); - for (String file : mca_files.get(world)) { - // r.-1.-1.mca - int mca_x = Integer.parseInt(file.split("\\.")[1]); - int mca_z = Integer.parseInt(file.split("\\.")[2]); - int world_x1 = mca_x * 512; - int world_x2 = (mca_x + 1) * 512; - int world_z1 = mca_z * 512; - int world_z2 = (mca_z + 1) * 512; - Collection vectors = new ArrayList<>(); - vectors.add(new Vector2d(world_x1 + 0.001, world_z1 + 0.001)); - vectors.add(new Vector2d(world_x2 - 0.001, world_z1 + 0.001)); - vectors.add(new Vector2d(world_x2 - 0.001, world_z2 - 0.001)); - vectors.add(new Vector2d(world_x1 + 0.001, world_z2 - 0.001)); - Shape shape = new Shape(vectors); - double x = vectors.iterator().next().getX(); - double z = vectors.iterator().next().getY(); - double y = -64; - - Color line = new Color(0, 204, 0, 0.8F); - Color fill = new Color(0, 204, 0, 0.2F); - ExtrudeMarker marker = ExtrudeMarker.builder() - .label(file) - .position(x, y, z) - .shape(shape, -64, 320) - .lineColor(line) - .fillColor(fill) + Scheduler.runTaskAsync(() -> { + try { + BlueMapAPI.getInstance().ifPresent(api -> { + for (String world : mca_files.keySet()) { + api.getWorld(world).ifPresent(bmWorld -> { + MarkerSet markerSet = MarkerSet.builder() + .label("MCA") + .defaultHidden(true) .build(); - markerSet.getMarkers() - .put(file, marker); - } - for (BlueMapMap map : bmWorld.getMaps()) { - map.getMarkerSets().put(world + "-" + markerSet.getLabel(), markerSet); - } - }); - } - }); - } catch (NoClassDefFoundError e) { - XLogger.warn("无法连接 BlueMap 插件,如果你不打算使用卫星地图渲染建议前往配置文件关闭此功能以避免下方的报错。"); - XLogger.err(e.getMessage()); - } + for (String file : mca_files.get(world)) { + // r.-1.-1.mca + int mca_x = Integer.parseInt(file.split("\\.")[1]); + int mca_z = Integer.parseInt(file.split("\\.")[2]); + int world_x1 = mca_x * 512; + int world_x2 = (mca_x + 1) * 512; + int world_z1 = mca_z * 512; + int world_z2 = (mca_z + 1) * 512; + Collection vectors = new ArrayList<>(); + vectors.add(new Vector2d(world_x1 + 0.001, world_z1 + 0.001)); + vectors.add(new Vector2d(world_x2 - 0.001, world_z1 + 0.001)); + vectors.add(new Vector2d(world_x2 - 0.001, world_z2 - 0.001)); + vectors.add(new Vector2d(world_x1 + 0.001, world_z2 - 0.001)); + Shape shape = new Shape(vectors); + double x = vectors.iterator().next().getX(); + double z = vectors.iterator().next().getY(); + double y = -64; + + Color line = new Color(0, 204, 0, 0.8F); + Color fill = new Color(0, 204, 0, 0.2F); + ExtrudeMarker marker = ExtrudeMarker.builder() + .label(file) + .position(x, y, z) + .shape(shape, -64, 320) + .lineColor(line) + .fillColor(fill) + .build(); + markerSet.getMarkers() + .put(file, marker); + } + for (BlueMapMap map : bmWorld.getMaps()) { + map.getMarkerSets().put(world + "-" + markerSet.getLabel(), markerSet); + } + }); + } + }); + } catch (NoClassDefFoundError e) { + XLogger.warn("无法连接 BlueMap 插件,如果你不打算使用卫星地图渲染建议前往配置文件关闭此功能以避免下方的报错。"); + XLogger.err(e.getMessage()); + } + }); } } diff --git a/src/main/java/cn/lunadeer/dominion/Cache.java b/src/main/java/cn/lunadeer/dominion/Cache.java index a816f42..4ab7c4e 100644 --- a/src/main/java/cn/lunadeer/dominion/Cache.java +++ b/src/main/java/cn/lunadeer/dominion/Cache.java @@ -32,11 +32,14 @@ public class Cache { /** * 从数据库加载所有领地 + * 如果idToLoad为null,则加载所有领地 + * + * @param idToLoad 领地ID */ - public void loadDominions() { + public void loadDominions(Integer idToLoad) { if (_last_update_dominion.get() + UPDATE_INTERVAL < System.currentTimeMillis()) { XLogger.debug("run loadDominionsExecution directly"); - loadDominionsExecution(); + loadDominionsExecution(idToLoad); } else { if (_update_dominion_is_scheduled.get()) return; XLogger.debug("schedule loadDominionsExecution"); @@ -44,70 +47,113 @@ public class Cache { long delay_tick = (UPDATE_INTERVAL - (System.currentTimeMillis() - _last_update_dominion.get())) / 1000 * 20L; Scheduler.runTaskLaterAsync(() -> { XLogger.debug("run loadDominionsExecution scheduled"); - loadDominionsExecution(); + loadDominionsExecution(idToLoad); _update_dominion_is_scheduled.set(false); }, delay_tick); } } - private void loadDominionsExecution() { - id_dominions = new ConcurrentHashMap<>(); - world_dominion_tree = new ConcurrentHashMap<>(); - dominion_children = new ConcurrentHashMap<>(); - List dominions = DominionDTO.selectAll(); - Map> world_dominions = new HashMap<>(); - for (DominionDTO d : dominions) { - if (!world_dominions.containsKey(d.getWorld())) { - world_dominions.put(d.getWorld(), new ArrayList<>()); + public void loadDominions() { + loadDominions(null); + } + + private void loadDominionsExecution(Integer idToLoad) { + Scheduler.runTaskAsync(() -> { + long start = System.currentTimeMillis(); + int count = 0; + if (idToLoad == null) { + id_dominions = new ConcurrentHashMap<>(); + world_dominion_tree = new ConcurrentHashMap<>(); + dominion_children = new ConcurrentHashMap<>(); + List dominions = DominionDTO.selectAll(); + count = dominions.size(); + Map> world_dominions = new HashMap<>(); + for (DominionDTO d : dominions) { + if (!world_dominions.containsKey(d.getWorld())) { + world_dominions.put(d.getWorld(), new ArrayList<>()); + } + world_dominions.get(d.getWorld()).add(d); + id_dominions.put(d.getId(), d); + if (!dominion_children.containsKey(d.getParentDomId())) { + dominion_children.put(d.getParentDomId(), new ArrayList<>()); + } + dominion_children.get(d.getParentDomId()).add(d.getId()); + } + for (Map.Entry> entry : world_dominions.entrySet()) { + world_dominion_tree.put(entry.getKey(), DominionNode.BuildNodeTree(-1, entry.getValue())); + } + } else { + DominionDTO dominion = DominionDTO.select(idToLoad); + if (dominion == null && id_dominions.containsKey(idToLoad)) { + id_dominions.remove(idToLoad); + } else if (dominion != null) { + id_dominions.put(idToLoad, dominion); + count = 1; + } } - world_dominions.get(d.getWorld()).add(d); - id_dominions.put(d.getId(), d); - if (!dominion_children.containsKey(d.getParentDomId())) { - dominion_children.put(d.getParentDomId(), new ArrayList<>()); - } - dominion_children.get(d.getParentDomId()).add(d.getId()); - } - for (Map.Entry> entry : world_dominions.entrySet()) { - world_dominion_tree.put(entry.getKey(), DominionNode.BuildNodeTree(-1, entry.getValue())); - } - BlueMapConnect.render(); - _last_update_dominion.set(System.currentTimeMillis()); + BlueMapConnect.render(); + recheckPlayerState = true; + _last_update_dominion.set(System.currentTimeMillis()); + XLogger.debug("loadDominionsExecution cost: %d ms for %d dominions" + , System.currentTimeMillis() - start, count); + }); } /** * 从数据库加载所有玩家特权 + * 如果player_uuid为null,则加载所有玩家的特权 + * + * @param player_uuid 玩家UUID */ - public void loadPlayerPrivileges() { + public void loadPlayerPrivileges(UUID player_uuid) { if (_last_update_privilege.get() + UPDATE_INTERVAL < System.currentTimeMillis()) { - loadPlayerPrivilegesExecution(); + XLogger.debug("run loadPlayerPrivilegesExecution directly"); + loadPlayerPrivilegesExecution(player_uuid); } else { if (_update_privilege_is_scheduled.get()) return; + XLogger.debug("schedule loadPlayerPrivilegesExecution"); _update_privilege_is_scheduled.set(true); - long delay_tick = (UPDATE_INTERVAL - (System.currentTimeMillis() - _last_update_dominion.get())) / 1000 * 20L; + long delay_tick = (UPDATE_INTERVAL - (System.currentTimeMillis() - _last_update_privilege.get())) / 1000 * 20L; Scheduler.runTaskLaterAsync(() -> { - loadPlayerPrivilegesExecution(); + XLogger.debug("run loadPlayerPrivilegesExecution scheduled"); + loadPlayerPrivilegesExecution(player_uuid); _update_privilege_is_scheduled.set(false); }, delay_tick); } } - private void loadPlayerPrivilegesExecution() { - List all_privileges = PlayerPrivilegeDTO.selectAll(); - if (all_privileges == null) { - XLogger.err("加载玩家特权失败"); - return; - } - player_uuid_to_privilege = new ConcurrentHashMap<>(); - for (PlayerPrivilegeDTO privilege : all_privileges) { - UUID player_uuid = privilege.getPlayerUUID(); - if (!player_uuid_to_privilege.containsKey(player_uuid)) { - player_uuid_to_privilege.put(player_uuid, new ConcurrentHashMap<>()); + public void loadPlayerPrivileges() { + loadPlayerPrivileges(null); + } + + private void loadPlayerPrivilegesExecution(UUID player_to_update) { + Scheduler.runTaskAsync(() -> { + long start = System.currentTimeMillis(); + List all_privileges; + if (player_to_update == null) { + all_privileges = PlayerPrivilegeDTO.selectAll(); + player_uuid_to_privilege = new ConcurrentHashMap<>(); + } else { + all_privileges = PlayerPrivilegeDTO.selectAll(player_to_update); + if (!player_uuid_to_privilege.containsKey(player_to_update)) { + player_uuid_to_privilege.put(player_to_update, new ConcurrentHashMap<>()); + } + player_uuid_to_privilege.get(player_to_update).clear(); } - player_uuid_to_privilege.get(player_uuid).put(privilege.getDomID(), privilege); - } - _last_update_privilege.set(System.currentTimeMillis()); + for (PlayerPrivilegeDTO privilege : all_privileges) { + UUID player_uuid = privilege.getPlayerUUID(); + if (!player_uuid_to_privilege.containsKey(player_uuid)) { + player_uuid_to_privilege.put(player_uuid, new ConcurrentHashMap<>()); + } + player_uuid_to_privilege.get(player_uuid).put(privilege.getDomID(), privilege); + } + recheckPlayerState = true; + _last_update_privilege.set(System.currentTimeMillis()); + XLogger.debug("loadPlayerPrivilegesExecution cost: %d ms for %d privileges" + , System.currentTimeMillis() - start, all_privileges.size()); + }); } /** @@ -128,6 +174,11 @@ public class Cache { if (isInDominion(last_dominion, player)) { if (dominion_children.get(last_in_dom_id) == null || dominion_children.get(last_in_dom_id).size() == 0) { // 如果玩家仍在领地内,且领地没有子领地,则直接返回 + if (recheckPlayerState) { + lightOrNot(player, last_dominion); + flyOrNot(player, last_dominion); + recheckPlayerState = false; + } return last_dominion; } } @@ -138,19 +189,11 @@ public class Cache { return last_dominion; } if (last_dom_id != -1) { -// if (last_dominion.getParentDomId() == -1) -// Notification.info(player, "您已离开领地:%s", last_dominion.getName()); -// else -// Notification.info(player, "您已离开子领地:%s", last_dominion.getName()); String msg = last_dominion.getLeaveMessage(); msg = msg.replace("${DOM_NAME}", last_dominion.getName()); Notification.actionBar(player, msg); } if (current_dom_id != -1) { -// if (current_dominion.getParentDomId() == -1) -// Notification.info(player, "您正在进入领地:%s", current_dominion.getName()); -// else -// Notification.info(player, "您正在进入子领地:%s", current_dominion.getName()); String msg = current_dominion.getJoinMessage(); msg = msg.replace("${DOM_NAME}", current_dominion.getName()); Notification.actionBar(player, msg); @@ -243,7 +286,7 @@ public class Cache { if (player == null) return dominionTree; for (List tree : world_dominion_tree.values()) { for (DominionNode node : tree) { - if (node.dominion.getOwner().equals(player.getUuid())) { + if (node.getDominion().getOwner().equals(player.getUuid())) { dominionTree.add(node); } } @@ -336,7 +379,7 @@ public class Cache { private final AtomicLong _last_update_privilege = new AtomicLong(0); private final AtomicBoolean _update_privilege_is_scheduled = new AtomicBoolean(false); private static final long UPDATE_INTERVAL = 1000 * 4; - + private boolean recheckPlayerState = false; // 是否需要重新检查玩家状态(发光、飞行) public final Map NextTimeAllowTeleport = new java.util.HashMap<>(); private Map> residence_data = null; diff --git a/src/main/java/cn/lunadeer/dominion/Commands.java b/src/main/java/cn/lunadeer/dominion/Commands.java index 77ec964..4bfbf04 100644 --- a/src/main/java/cn/lunadeer/dominion/Commands.java +++ b/src/main/java/cn/lunadeer/dominion/Commands.java @@ -181,6 +181,12 @@ public class Commands implements TabExecutor { case "migrate": Migration.migrate(sender, args); break; + case "set_map_color": + DominionOperate.setMapColor(sender, args); + break; + case "env_info": + DominionEnvInfo.show(sender, args); + break; // ---=== CUI ===--- case "cui_rename": RenameDominion.open(sender, args); @@ -200,6 +206,9 @@ public class Commands implements TabExecutor { case "cui_template_create": CreateTemplate.open(sender, args); break; + case "cui_set_map_color": + SetMapColor.open(sender, args); + break; default: return false; } @@ -240,7 +249,9 @@ public class Commands implements TabExecutor { "template_manage", "template_delete", "template_create", - "template_set_flag" + "template_set_flag", + "all_dominion", + "set_map_color" ); } if (args.length == 2) { @@ -288,6 +299,8 @@ public class Commands implements TabExecutor { return allTemplates(sender); case "template_create": return Collections.singletonList("输入模板名称"); + case "set_map_color": + return Collections.singletonList("输入颜色(16进制)"); } } if (args.length == 3) { @@ -307,6 +320,7 @@ public class Commands implements TabExecutor { case "set_enter_msg": case "set_leave_msg": case "apply_template": + case "set_map_color": return playerDominions(sender); case "rename": return Collections.singletonList("输入新领地名称"); diff --git a/src/main/java/cn/lunadeer/dominion/Dominion.java b/src/main/java/cn/lunadeer/dominion/Dominion.java index 03878ae..9b80fa2 100644 --- a/src/main/java/cn/lunadeer/dominion/Dominion.java +++ b/src/main/java/cn/lunadeer/dominion/Dominion.java @@ -6,6 +6,8 @@ import cn.lunadeer.dominion.events.SelectPointEvents; import cn.lunadeer.dominion.managers.ConfigManager; import cn.lunadeer.dominion.managers.DatabaseTables; import cn.lunadeer.minecraftpluginutils.*; +import cn.lunadeer.minecraftpluginutils.databse.DatabaseManager; +import cn.lunadeer.minecraftpluginutils.databse.DatabaseType; import cn.lunadeer.minecraftpluginutils.scui.CuiManager; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -26,8 +28,8 @@ public final class Dominion extends JavaPlugin { new XLogger(this); config = new ConfigManager(this); XLogger.setDebug(config.isDebug()); - database = new DatabaseManager(this, - config.getDbType().equals("pgsql") ? DatabaseManager.TYPE.POSTGRESQL : DatabaseManager.TYPE.SQLITE, + new DatabaseManager(this, + DatabaseType.valueOf(config.getDbType().toUpperCase()), config.getDbHost(), config.getDbPort(), config.getDbName(), @@ -37,7 +39,9 @@ public final class Dominion extends JavaPlugin { new Scheduler(this); AutoClean.run(); Cache.instance = new Cache(); - new VaultConnect(this); + if (config.getEconomyEnable()) { + new VaultConnect(this); + } Bukkit.getPluginManager().registerEvents(new PlayerEvents(), this); Bukkit.getPluginManager().registerEvents(new EnvironmentEvents(), this); @@ -72,12 +76,11 @@ public final class Dominion extends JavaPlugin { @Override public void onDisable() { // Plugin shutdown logic - database.close(); + DatabaseManager.instance.close(); } public static Dominion instance; public static ConfigManager config; - public static DatabaseManager database; public static Map> pointsSelect = new HashMap<>(); private GiteaReleaseCheck giteaReleaseCheck; } diff --git a/src/main/java/cn/lunadeer/dominion/DominionNode.java b/src/main/java/cn/lunadeer/dominion/DominionNode.java index 1ec848f..83eeab4 100644 --- a/src/main/java/cn/lunadeer/dominion/DominionNode.java +++ b/src/main/java/cn/lunadeer/dominion/DominionNode.java @@ -5,30 +5,52 @@ import org.bukkit.Location; import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; public class DominionNode { - public DominionDTO dominion; - public List children = new ArrayList<>(); + private Integer dominion_id; + private List children = new ArrayList<>(); + + public DominionDTO getDominion() { + return Cache.instance.getDominion(dominion_id); + } + + public List getChildren() { + return children; + } public static List BuildNodeTree(Integer rootId, List dominions) { - List dominionTree = new ArrayList<>(); + // 映射父节点ID到其子节点列表 + Map> parentToChildrenMap = new HashMap<>(); for (DominionDTO dominion : dominions) { - if (Objects.equals(dominion.getParentDomId(), rootId)) { + parentToChildrenMap + .computeIfAbsent(dominion.getParentDomId(), k -> new ArrayList<>()) + .add(dominion); + } + + // 递归构建节点树 + return buildTree(rootId, parentToChildrenMap); + } + + private static List buildTree(Integer rootId, Map> parentToChildrenMap) { + List dominionTree = new ArrayList<>(); + List children = parentToChildrenMap.get(rootId); + + if (children != null) { + for (DominionDTO dominion : children) { DominionNode node = new DominionNode(); - node.dominion = dominion; - node.children = BuildNodeTree(dominion.getId(), dominions); + node.dominion_id = dominion.getId(); + node.children = buildTree(dominion.getId(), parentToChildrenMap); dominionTree.add(node); } } + return dominionTree; } public static DominionNode getLocInDominionNode(@NotNull List nodes, @NotNull Location loc) { for (DominionNode node : nodes) { - if (isInDominion(node.dominion, loc)) { + if (isInDominion(node.getDominion(), loc)) { if (node.children.isEmpty()) { return node; } else { @@ -48,7 +70,7 @@ public class DominionNode { if (nodes == null) return null; if (nodes.isEmpty()) return null; DominionNode dominionNode = getLocInDominionNode(nodes, loc); - return dominionNode == null ? null : dominionNode.dominion; + return dominionNode == null ? null : dominionNode.getDominion(); } public static boolean isInDominion(@Nullable DominionDTO dominion, Location location) { diff --git a/src/main/java/cn/lunadeer/dominion/commands/DominionFlag.java b/src/main/java/cn/lunadeer/dominion/commands/DominionFlag.java index 1ef2719..bb53985 100644 --- a/src/main/java/cn/lunadeer/dominion/commands/DominionFlag.java +++ b/src/main/java/cn/lunadeer/dominion/commands/DominionFlag.java @@ -2,6 +2,8 @@ package cn.lunadeer.dominion.commands; import cn.lunadeer.dominion.controllers.BukkitPlayerOperator; import cn.lunadeer.dominion.controllers.FlagsController; +import cn.lunadeer.dominion.dtos.Flag; +import cn.lunadeer.dominion.tuis.DominionEnvInfo; import cn.lunadeer.dominion.tuis.DominionFlagInfo; import cn.lunadeer.minecraftpluginutils.Notification; import org.bukkit.command.CommandSender; @@ -29,10 +31,15 @@ public class DominionFlag { } else if (args.length == 5) { FlagsController.setFlag(operator, args[1], Boolean.parseBoolean(args[2]), args[3]); String[] newArgs = new String[3]; - newArgs[0] = "flag_info"; + newArgs[0] = Flag.isDominionOnlyFlag(args[1]) ? "env_info" : "flag_info"; newArgs[1] = args[3]; newArgs[2] = args[4]; - DominionFlagInfo.show(sender, newArgs); + if (Flag.isDominionOnlyFlag(args[1])) { + DominionEnvInfo.show(sender, newArgs); + } else { + DominionFlagInfo.show(sender, newArgs); + } + } else { Notification.error(sender, "用法: /dominion set <权限名称> [领地名称]"); } diff --git a/src/main/java/cn/lunadeer/dominion/commands/DominionOperate.java b/src/main/java/cn/lunadeer/dominion/commands/DominionOperate.java index d06ef4f..b9b28f6 100644 --- a/src/main/java/cn/lunadeer/dominion/commands/DominionOperate.java +++ b/src/main/java/cn/lunadeer/dominion/commands/DominionOperate.java @@ -375,15 +375,17 @@ public class DominionOperate { } PlayerPrivilegeDTO privilegeDTO = PlayerPrivilegeDTO.select(player.getUniqueId(), dominionDTO.getId()); - if (privilegeDTO == null) { - if (!dominionDTO.getFlagValue(Flag.TELEPORT)) { - Notification.error(sender, "此领地禁止传送"); - return; - } - } else { - if (!privilegeDTO.getFlagValue(Flag.TELEPORT)) { - Notification.error(sender, "你不被允许传送到这个领地"); - return; + if (!player.getUniqueId().equals(dominionDTO.getOwner())) { // 领地所有人可以传送到自己的领地 + if (privilegeDTO == null) { + if (!dominionDTO.getFlagValue(Flag.TELEPORT)) { + Notification.error(sender, "此领地禁止传送"); + return; + } + } else { + if (!privilegeDTO.getFlagValue(Flag.TELEPORT)) { + Notification.error(sender, "你不被允许传送到这个领地"); + return; + } } } @@ -426,4 +428,25 @@ public class DominionOperate { } }, 20L * Dominion.config.getTpDelay()); } + + /** + * 设置领地卫星地图地块颜色 + * + * @param sender 命令发送者 + * @param args 命令参数 + */ + public static void setMapColor(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + if (args.length < 2) { + Notification.error(sender, "用法: /dominion set_map_color <颜色> [领地名称]"); + return; + } + BukkitPlayerOperator operator = BukkitPlayerOperator.create(player); + if (args.length == 2) { + DominionController.setMapColor(operator, args[1]); + } else { + DominionController.setMapColor(operator, args[1], args[2]); + } + } } diff --git a/src/main/java/cn/lunadeer/dominion/controllers/BukkitPlayerOperator.java b/src/main/java/cn/lunadeer/dominion/controllers/BukkitPlayerOperator.java index 64808d0..ef88d6f 100644 --- a/src/main/java/cn/lunadeer/dominion/controllers/BukkitPlayerOperator.java +++ b/src/main/java/cn/lunadeer/dominion/controllers/BukkitPlayerOperator.java @@ -45,8 +45,8 @@ public class BukkitPlayerOperator implements AbstractOperator { @Override public BlockFace getDirection() { - float yaw = player.getYaw(); - float pitch = player.getPitch(); + float yaw = player.getLocation().getYaw(); + float pitch = player.getLocation().getPitch(); if (pitch > -45 && pitch < 45) { if (yaw > -45 && yaw < 45) { return BlockFace.SOUTH; diff --git a/src/main/java/cn/lunadeer/dominion/controllers/DominionController.java b/src/main/java/cn/lunadeer/dominion/controllers/DominionController.java index c4bb435..38ca2aa 100644 --- a/src/main/java/cn/lunadeer/dominion/controllers/DominionController.java +++ b/src/main/java/cn/lunadeer/dominion/controllers/DominionController.java @@ -665,6 +665,48 @@ public class DominionController { operator.setResponse(new AbstractOperator.Result(AbstractOperator.Result.SUCCESS, "成功将领地 %s 及其所有子领地转让给 %s", dom_name, player_name)); } + /** + * 设置领地的卫星地图地块颜色 + * + * @param operator 操作者 + * @param color 16进制颜色 例如 #ff0000 + * @param dom_name 领地名称 + */ + public static void setMapColor(AbstractOperator operator, String color, String dom_name) { + AbstractOperator.Result FAIL = new AbstractOperator.Result(AbstractOperator.Result.FAILURE, "设置领地地图颜色失败"); + DominionDTO dominion = getExistDomAndIsOwner(operator, dom_name); + if (dominion == null) { + return; + } + if (notOwner(operator, dominion)) { + operator.setResponse(FAIL.addMessage("你不是领地 %s 的拥有者", dom_name)); + return; + } + color = color.toUpperCase(); // 转换为大写 + if (!color.matches("^#[0-9a-fA-F]{6}$")) { + operator.setResponse(FAIL.addMessage("颜色格式不正确")); + return; + } + dominion.setColor(color); + operator.setResponse(new AbstractOperator.Result(AbstractOperator.Result.SUCCESS, "成功设置领地 %s 的卫星地图颜色为 %s", dom_name, color)); + } + + /** + * 设置领地的卫星地图地块颜色 + * + * @param operator 操作者 + * @param color 16进制颜色 例如 #ff0000 + */ + public static void setMapColor(AbstractOperator operator, String color) { + AbstractOperator.Result FAIL = new AbstractOperator.Result(AbstractOperator.Result.FAILURE, "设置领地地图颜色失败"); + DominionDTO dominion = getPlayerCurrentDominion(operator); + if (dominion == null) { + operator.setResponse(FAIL.addMessage("无法获取你所处的领地,请指定名称")); + return; + } + setMapColor(operator, color, dominion.getName()); + } + /** * 判断两个领地是否相交 */ diff --git a/src/main/java/cn/lunadeer/dominion/controllers/PrivilegeController.java b/src/main/java/cn/lunadeer/dominion/controllers/PrivilegeController.java index c210837..5ea74c7 100644 --- a/src/main/java/cn/lunadeer/dominion/controllers/PrivilegeController.java +++ b/src/main/java/cn/lunadeer/dominion/controllers/PrivilegeController.java @@ -103,13 +103,17 @@ public class PrivilegeController { privilege = createPlayerPrivilege(operator, player.getUuid(), dominion); if (privilege == null) return; } - if (flag.equals("admin") || privilege.getAdmin()) { - if (notOwner(operator, dominion)) { - operator.setResponse(FAIL.addMessage("你不是领地 %s 的拥有者,无法修改其他管理员的权限", dominionName)); - return; - } + if ((flag.equals("admin") || privilege.getAdmin()) && notOwner(operator, dominion)) { + operator.setResponse(FAIL.addMessage("你不是领地 %s 的拥有者,无法修改其他玩家管理员的权限", dominionName)); + return; + } + if (flag.equals("admin")) { privilege.setAdmin(value); } else { + if (privilege.getAdmin()) { + operator.setResponse(FAIL.addMessage("管理员拥有所有权限,无需单独设置权限")); + return; + } Flag f = Flag.getFlag(flag); if (f == null) { operator.setResponse(FAIL.addMessage("未知的领地权限 %s", flag)); diff --git a/src/main/java/cn/lunadeer/dominion/cuis/SetMapColor.java b/src/main/java/cn/lunadeer/dominion/cuis/SetMapColor.java new file mode 100644 index 0000000..c177bc5 --- /dev/null +++ b/src/main/java/cn/lunadeer/dominion/cuis/SetMapColor.java @@ -0,0 +1,49 @@ +package cn.lunadeer.dominion.cuis; + +import cn.lunadeer.dominion.controllers.BukkitPlayerOperator; +import cn.lunadeer.dominion.controllers.DominionController; +import cn.lunadeer.dominion.dtos.DominionDTO; +import cn.lunadeer.dominion.tuis.DominionManage; +import cn.lunadeer.minecraftpluginutils.Notification; +import cn.lunadeer.minecraftpluginutils.XLogger; +import cn.lunadeer.minecraftpluginutils.scui.CuiTextInput; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import static cn.lunadeer.dominion.commands.Apis.playerOnly; + +public class SetMapColor { + + private static class setMapColorCB implements CuiTextInput.InputCallback { + private final Player sender; + private final String dominionName; + + public setMapColorCB(Player sender, String dominionName) { + this.sender = sender; + this.dominionName = dominionName; + } + + @Override + public void handleData(String input) { + XLogger.debug("editLeaveMessageCB.run: %s", input); + BukkitPlayerOperator operator = BukkitPlayerOperator.create(sender); + DominionController.setMapColor(operator, input, dominionName); + DominionManage.show(sender, new String[]{"manage", dominionName}); + } + } + + public static void open(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + DominionDTO dominion = DominionDTO.select(args[1]); + if (dominion == null) { + Notification.error(sender, "领地不存在"); + return; + } + CuiTextInput.InputCallback setMapColorCB = new SetMapColor.setMapColorCB(player, dominion.getName()); + CuiTextInput view = CuiTextInput.create(setMapColorCB).setText(dominion.getColor()).title("输入卫星地图地块颜色(16进制)"); + view.setSuggestCommand("/dominion set_map_color <颜色> [领地名称]"); + view.open(player); + } + +} diff --git a/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java b/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java index d68d3ac..cd488f4 100644 --- a/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java +++ b/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java @@ -3,6 +3,11 @@ package cn.lunadeer.dominion.dtos; import cn.lunadeer.dominion.Cache; import cn.lunadeer.dominion.Dominion; import cn.lunadeer.minecraftpluginutils.XLogger; +import cn.lunadeer.minecraftpluginutils.databse.DatabaseManager; +import cn.lunadeer.minecraftpluginutils.databse.Field; +import cn.lunadeer.minecraftpluginutils.databse.FieldType; +import cn.lunadeer.minecraftpluginutils.databse.syntax.InsertRow; +import cn.lunadeer.minecraftpluginutils.databse.syntax.UpdateRow; import org.bukkit.Location; import org.bukkit.World; @@ -13,40 +18,44 @@ import java.util.*; public class DominionDTO { private static List query(String sql, Object... args) { List dominions = new ArrayList<>(); - try (ResultSet rs = Dominion.database.query(sql, args)) { - if (sql.contains("UPDATE") || sql.contains("DELETE") || sql.contains("INSERT")) { - // 如果是更新操作,重新加载缓存 - Cache.instance.loadDominions(); - } - if (rs == null) return dominions; - while (rs.next()) { - Integer id = rs.getInt("id"); - UUID owner = UUID.fromString(rs.getString("owner")); - String name = rs.getString("name"); - String world = rs.getString("world"); - Integer x1 = rs.getInt("x1"); - Integer y1 = rs.getInt("y1"); - Integer z1 = rs.getInt("z1"); - Integer x2 = rs.getInt("x2"); - Integer y2 = rs.getInt("y2"); - Integer z2 = rs.getInt("z2"); - Integer parentDomId = rs.getInt("parent_dom_id"); - String tp_location = rs.getString("tp_location"); - Map flags = new HashMap<>(); - for (Flag f : Flag.getDominionFlagsEnabled()) { - flags.put(f, rs.getBoolean(f.getFlagName())); - } - - DominionDTO dominion = new DominionDTO(id, owner, name, world, x1, y1, z1, x2, y2, z2, parentDomId, - rs.getString("join_message"), - rs.getString("leave_message"), - flags, - tp_location - ); - dominions.add(dominion); - } + try (ResultSet rs = DatabaseManager.instance.query(sql, args)) { + return getDTOFromRS(rs); } catch (SQLException e) { - Dominion.database.handleDatabaseError("数据库操作失败: ", e, sql); + DatabaseManager.handleDatabaseError("数据库操作失败: ", e, sql); + } + return dominions; + } + + private static List getDTOFromRS(ResultSet rs) throws SQLException { + List dominions = new ArrayList<>(); + if (rs == null) return dominions; + while (rs.next()) { + Integer id = rs.getInt("id"); + UUID owner = UUID.fromString(rs.getString("owner")); + String name = rs.getString("name"); + String world = rs.getString("world"); + Integer x1 = rs.getInt("x1"); + Integer y1 = rs.getInt("y1"); + Integer z1 = rs.getInt("z1"); + Integer x2 = rs.getInt("x2"); + Integer y2 = rs.getInt("y2"); + Integer z2 = rs.getInt("z2"); + Integer parentDomId = rs.getInt("parent_dom_id"); + String tp_location = rs.getString("tp_location"); + Map flags = new HashMap<>(); + for (Flag f : Flag.getDominionFlagsEnabled()) { + flags.put(f, rs.getBoolean(f.getFlagName())); + } + String color = rs.getString("color"); + + DominionDTO dominion = new DominionDTO(id, owner, name, world, x1, y1, z1, x2, y2, z2, parentDomId, + rs.getString("join_message"), + rs.getString("leave_message"), + flags, + tp_location, + color + ); + dominions.add(dominion); } return dominions; } @@ -106,77 +115,33 @@ public class DominionDTO { } public static DominionDTO insert(DominionDTO dominion) { - StringBuilder sql = new StringBuilder("INSERT INTO dominion (" + - "owner, name, world, x1, y1, z1, x2, y2, z2, "); - for (Flag f : Flag.getAllDominionFlags()) { - sql.append(f.getFlagName()).append(", "); + InsertRow insert = new InsertRow().returningAll().table("dominion").onConflictDoNothing(new Field("id", null)); + insert.field(dominion.owner) + .field(dominion.name) + .field(dominion.world) + .field(dominion.x1).field(dominion.y1).field(dominion.z1) + .field(dominion.x2).field(dominion.y2).field(dominion.z2) + .field(dominion.parentDomId) + .field(dominion.joinMessage).field(dominion.leaveMessage) + .field(dominion.tp_location); + for (Flag f : Flag.getDominionFlagsEnabled()) { + insert.field(new Field(f.getFlagName(), f.getDefaultValue())); } - sql.append("tp_location, join_message, leave_message"); - sql.append(") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, "); - for (Flag f : Flag.getAllDominionFlags()) { - sql.append(f.getDefaultValue()).append(", "); + try (ResultSet rs = insert.execute()) { + Cache.instance.loadDominions(); + List dominions = getDTOFromRS(rs); + if (dominions.size() == 0) return null; + return dominions.get(0); + } catch (SQLException e) { + DatabaseManager.handleDatabaseError("数据库操作失败: ", e, insert.toString()); + return null; } - sql.append("?, ?, ?"); - sql.append(") RETURNING *;"); - List dominions = query(sql.toString(), - dominion.getOwner(), - dominion.getName(), - dominion.getWorld(), - dominion.getX1(), - dominion.getY1(), - dominion.getZ1(), - dominion.getX2(), - dominion.getY2(), - dominion.getZ2(), - dominion.tp_location, - dominion.getJoinMessage(), - dominion.getLeaveMessage() - ); - if (dominions.size() == 0) return null; - return dominions.get(0); } public static void delete(DominionDTO dominion) { String sql = "DELETE FROM dominion WHERE id = ?;"; query(sql, dominion.getId()); - } - - private static DominionDTO update(DominionDTO dominion) { - String tp_location; - if (dominion.getTpLocation() == null) { - tp_location = "default"; - } else { - Location loc = dominion.getTpLocation(); - tp_location = loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ(); - } - String sql = "UPDATE dominion SET " + - "owner = ?," + - "name = ?," + - "world = ?," + - "x1 = " + dominion.getX1() + ", " + - "y1 = " + dominion.getY1() + ", " + - "z1 = " + dominion.getZ1() + ", " + - "x2 = " + dominion.getX2() + ", " + - "y2 = " + dominion.getY2() + ", " + - "z2 = " + dominion.getZ2() + ", " + - "parent_dom_id = " + dominion.getParentDomId() + ", " + - "join_message = ?," + - "leave_message = ?,"; - for (Flag f : Flag.getDominionFlagsEnabled()) { - sql += f.getFlagName() + " = " + dominion.getFlagValue(f) + ","; - } - sql += "tp_location = ?" + - " WHERE id = " + dominion.getId() + - " RETURNING *;"; - List dominions = query(sql, - dominion.getOwner().toString(), - dominion.getName(), - dominion.getWorld(), - dominion.getJoinMessage(), - dominion.getLeaveMessage(), - tp_location); - if (dominions.size() == 0) return null; - return dominions.get(0); + Cache.instance.loadDominions(); } private DominionDTO(Integer id, UUID owner, String name, String world, @@ -184,39 +149,41 @@ public class DominionDTO { Integer parentDomId, String joinMessage, String leaveMessage, Map flags, - String tp_location) { - this.id = id; - this.owner = owner; - this.name = name; - this.world = world; - this.x1 = x1; - this.y1 = y1; - this.z1 = z1; - this.x2 = x2; - this.y2 = y2; - this.z2 = z2; - this.parentDomId = parentDomId; - this.joinMessage = joinMessage; - this.leaveMessage = leaveMessage; + String tp_location, + String color) { + this.id.value = id; + this.owner.value = owner.toString(); + this.name.value = name; + this.world.value = world; + this.x1.value = x1; + this.y1.value = y1; + this.z1.value = z1; + this.x2.value = x2; + this.y2.value = y2; + this.z2.value = z2; + this.parentDomId.value = parentDomId; + this.joinMessage.value = joinMessage; + this.leaveMessage.value = leaveMessage; this.flags.putAll(flags); - this.tp_location = tp_location; + this.tp_location.value = tp_location; + this.color.value = color; } private DominionDTO(Integer id, UUID owner, String name, String world, Integer x1, Integer y1, Integer z1, Integer x2, Integer y2, Integer z2, Integer parentDomId) { - this.id = id; - this.owner = owner; - this.name = name; - this.world = world; - this.x1 = x1; - this.y1 = y1; - this.z1 = z1; - this.x2 = x2; - this.y2 = y2; - this.z2 = z2; - this.parentDomId = parentDomId; + this.id.value = id; + this.owner.value = owner.toString(); + this.name.value = name; + this.world.value = world; + this.x1.value = x1; + this.y1.value = y1; + this.z1.value = z1; + this.x2.value = x2; + this.y2.value = y2; + this.z2.value = z2; + this.parentDomId.value = parentDomId; } public DominionDTO(UUID owner, String name, String world, @@ -224,153 +191,165 @@ public class DominionDTO { this(null, owner, name, world, x1, y1, z1, x2, y2, z2, -1); } - private Integer id; - private UUID owner; - private String name; - private final String world; - private Integer x1; - private Integer y1; - private Integer z1; - private Integer x2; - private Integer y2; - private Integer z2; - private Integer parentDomId = -1; - private String joinMessage = "欢迎来到 ${DOM_NAME}!"; - private String leaveMessage = "你正在离开 ${DOM_NAME},欢迎下次光临~"; + private final Field id = new Field("id", FieldType.INT); + private final Field owner = new Field("owner", FieldType.STRING); + private final Field name = new Field("name", FieldType.STRING); + private final Field world = new Field("world", FieldType.STRING); + private final Field x1 = new Field("x1", FieldType.INT); + private final Field y1 = new Field("y1", FieldType.INT); + private final Field z1 = new Field("z1", FieldType.INT); + private final Field x2 = new Field("x2", FieldType.INT); + private final Field y2 = new Field("y2", FieldType.INT); + private final Field z2 = new Field("z2", FieldType.INT); + private final Field parentDomId = new Field("parent_dom_id", -1); + private final Field joinMessage = new Field("join_message", "欢迎来到 ${DOM_NAME}!"); + private final Field leaveMessage = new Field("leave_message", "你正在离开 ${DOM_NAME},欢迎下次光临~"); private final Map flags = new HashMap<>(); - private String tp_location = "default"; + private final Field tp_location = new Field("tp_location", "default"); + private final Field color = new Field("color", "#00BFFF"); + // getters and setters public Integer getId() { - return id; - } - - public DominionDTO setId(Integer id) { - this.id = id; - return update(this); + return (Integer) id.value; } public UUID getOwner() { - return owner; + return UUID.fromString((String) owner.value); + } + + private DominionDTO doUpdate(UpdateRow updateRow) { + updateRow.returningAll(id) + .table("dominion") + .where("id = ?", id.value); + try (ResultSet rs = updateRow.execute()) { + List dominions = getDTOFromRS(rs); + if (dominions.size() == 0) return null; + Cache.instance.loadDominions((Integer) id.value); + return dominions.get(0); + } catch (SQLException e) { + DatabaseManager.handleDatabaseError("更新领地信息失败: ", e, updateRow.toString()); + return null; + } } public DominionDTO setOwner(UUID owner) { - this.owner = owner; - return update(this); + this.owner.value = owner.toString(); + return doUpdate(new UpdateRow().field(this.owner)); } public String getName() { - return name; + return (String) name.value; } public DominionDTO setName(String name) { - this.name = name; - return update(this); + this.name.value = name; + return doUpdate(new UpdateRow().field(this.name)); } public String getWorld() { - return world; + return (String) world.value; } public Integer getX1() { - return x1; + return (Integer) x1.value; } public DominionDTO setX1(Integer x1) { - this.x1 = x1; - return update(this); + this.x1.value = x1; + return doUpdate(new UpdateRow().field(this.x1)); } public Integer getY1() { - return y1; + return (Integer) y1.value; } public DominionDTO setY1(Integer y1) { - this.y1 = y1; - return update(this); + this.y1.value = y1; + return doUpdate(new UpdateRow().field(this.y1)); } public Integer getZ1() { - return z1; + return (Integer) z1.value; } public DominionDTO setZ1(Integer z1) { - this.z1 = z1; - return update(this); + this.z1.value = z1; + return doUpdate(new UpdateRow().field(this.z1)); } public Integer getX2() { - return x2; + return (Integer) x2.value; } public DominionDTO setX2(Integer x2) { - this.x2 = x2; - return update(this); + this.x2.value = x2; + return doUpdate(new UpdateRow().field(this.x2)); } public Integer getY2() { - return y2; + return (Integer) y2.value; } public DominionDTO setY2(Integer y2) { - this.y2 = y2; - return update(this); + this.y2.value = y2; + return doUpdate(new UpdateRow().field(this.y2)); } public Integer getZ2() { - return z2; + return (Integer) z2.value; } public DominionDTO setZ2(Integer z2) { - this.z2 = z2; - return update(this); + this.z2.value = z2; + return doUpdate(new UpdateRow().field(this.z2)); } public Integer getSquare() { - return (x2 - x1 + 1) * (z2 - z1 + 1); + return (getX2() - getX1() + 1) * (getZ2() - getZ1() + 1); } public Integer getVolume() { - return getSquare() * (y2 - y1 + 1); + return getSquare() * (getY2() - getY1() + 1); } public Integer getWidthX() { - return x2 - x1 + 1; + return getX2() - getX1() + 1; } public Integer getHeight() { - return y2 - y1 + 1; + return getY2() - getY1() + 1; } public Integer getWidthZ() { - return z2 - z1 + 1; + return getZ2() - getZ1() + 1; } public Integer getParentDomId() { - return parentDomId; + return (Integer) parentDomId.value; } public DominionDTO setParentDomId(Integer parentDomId) { - this.parentDomId = parentDomId; - return update(this); + this.parentDomId.value = parentDomId; + return doUpdate(new UpdateRow().field(this.parentDomId)); } public String getJoinMessage() { - return joinMessage; + return (String) joinMessage.value; } public DominionDTO setJoinMessage(String joinMessage) { - this.joinMessage = joinMessage; - return update(this); + this.joinMessage.value = joinMessage; + return doUpdate(new UpdateRow().field(this.joinMessage)); } public String getLeaveMessage() { - return leaveMessage; + return (String) leaveMessage.value; } public DominionDTO setLeaveMessage(String leaveMessage) { - this.leaveMessage = leaveMessage; - return update(this); + this.leaveMessage.value = leaveMessage; + return doUpdate(new UpdateRow().field(this.leaveMessage)); } public Boolean getFlagValue(Flag flag) { @@ -380,17 +359,18 @@ public class DominionDTO { public DominionDTO setFlagValue(Flag flag, Boolean value) { flags.put(flag, value); - return update(this); + Field flagField = new Field(flag.getFlagName(), value); + return doUpdate(new UpdateRow().field(flagField)); } public DominionDTO setXYZ(Integer x1, Integer y1, Integer z1, Integer x2, Integer y2, Integer z2) { - this.x1 = x1; - this.y1 = y1; - this.z1 = z1; - this.x2 = x2; - this.y2 = y2; - this.z2 = z2; - return update(this); + this.x1.value = x1; + this.y1.value = y1; + this.z1.value = z1; + this.x2.value = x2; + this.y2.value = y2; + this.z2.value = z2; + return doUpdate(new UpdateRow().field(this.x1).field(this.y1).field(this.z1).field(this.x2).field(this.y2).field(this.z2)); } public Location getTpLocation() { @@ -398,8 +378,8 @@ public class DominionDTO { return null; } else { // 0:0:0 - String[] loc = tp_location.split(":"); - World w = Dominion.instance.getServer().getWorld(world); + String[] loc = ((String) tp_location.value).split(":"); + World w = Dominion.instance.getServer().getWorld(getWorld()); if (loc.length == 3 && w != null) { return new Location(w, Integer.parseInt(loc[0]), Integer.parseInt(loc[1]), Integer.parseInt(loc[2])); } else { @@ -411,19 +391,36 @@ public class DominionDTO { } public DominionDTO setTpLocation(Location loc) { - if (loc != null) { - this.tp_location = loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ(); - } else { - this.tp_location = "default"; - } - return update(this); + this.tp_location.value = loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ(); + return doUpdate(new UpdateRow().field(tp_location)); } public Location getLocation1() { - return new Location(Dominion.instance.getServer().getWorld(world), x1, y1, z1); + return new Location(Dominion.instance.getServer().getWorld(getWorld()), getX1(), getY1(), getZ1()); } public Location getLocation2() { - return new Location(Dominion.instance.getServer().getWorld(world), x2, y2, z2); + return new Location(Dominion.instance.getServer().getWorld(getWorld()), getX2(), getY2(), getZ2()); + } + + public DominionDTO setColor(String color) { + this.color.value = color; + return doUpdate(new UpdateRow().field(this.color)); + } + + public int getColorR() { + return Integer.valueOf(getColor().substring(1, 3), 16); + } + + public int getColorG() { + return Integer.valueOf(getColor().substring(3, 5), 16); + } + + public int getColorB() { + return Integer.valueOf(getColor().substring(5, 7), 16); + } + + public String getColor() { + return (String) color.value; } } diff --git a/src/main/java/cn/lunadeer/dominion/dtos/Flag.java b/src/main/java/cn/lunadeer/dominion/dtos/Flag.java index b491d33..974150b 100644 --- a/src/main/java/cn/lunadeer/dominion/dtos/Flag.java +++ b/src/main/java/cn/lunadeer/dominion/dtos/Flag.java @@ -15,7 +15,7 @@ import java.util.List; public enum Flag { ANCHOR("anchor", "重生锚", "是否允许设置重生锚", false, false, true), ANIMAL_KILLING("animal_killing", "对动物造成伤害", "是否允许对动物造成伤害", false, false, true), - ANIMAL_SPAWN("animal_spawn", "动物生成", "是否允许动物生成", true, true, false), + ANIMAL_SPAWN("animal_spawn", "动物生成(繁殖)", "是否允许动物生成(包括繁殖)", true, true, false), ANVIL("anvil", "使用铁砧", "是否允许使用铁砧", false, false, true), BEACON("beacon", "信标交互", "是否允许与信标交互", false, false, true), BED("bed", "床交互", "是否允许使用床睡觉或设置重生点", false, false, true), @@ -26,14 +26,15 @@ public enum Flag { CONTAINER("container", "一般容器", "包含:箱子/木桶/潜影盒/盔甲架/展示框", false, false, true), CRAFT("craft", "使用工作台", "是否可以使用工作台", false, false, true), CREEPER_EXPLODE("creeper_explode", "实体爆炸", "包含:苦力怕/凋零头颅/水晶爆炸", false, true, true), - COMPARER("comparer", "比较器交互", "是否可以与比较器交互", false, false, true), + COMPARER("comparer", "比较器交互", "是否可以修改比较器状态", false, false, true), DOOR("door", "门交互", "是否可以使用各种材质的门(包括活板门)", false, false, true), DYE("dye", "染色", "是否可以使用染料(对羊、狗项圈、猫项圈)染色", false, false, true), + EDIT_SIGN("edit_sign", "编辑告示牌", "是否可以编辑告示牌", false, false, true), EGG("egg", "扔鸡蛋", "是否可以扔鸡蛋", false, false, true), ENCHANT("enchant", "使用附魔台", "是否可以使用附魔台", false, false, true), ENDER_MAN("ender_man", "末影人行为", "包含:末影人是否可以生成、瞬移", false, true, true), ENDER_PEARL("ender_pearl", "投掷末影珍珠", "是否可以使用末影珍珠", false, false, true), - FEED("feed", "喂养", "是否可以喂养动物", false, false, true), + FEED("feed", "喂养动物", "是否可以喂养动物", false, false, true), FIRE_SPREAD("fire_spread", "火焰蔓延", "是否可以火焰蔓延", false, true, true), FLOW_IN_PROTECTION("flow_in_protection", "外部流体是否可以进入", "包含:岩浆、水(不会阻止领地内部的流体蔓延)", false, true, true), FLY("fly", "飞行", "不是翅鞘飞行,是类似于创造模式的飞行", false, false, false), @@ -41,7 +42,7 @@ public enum Flag { HARVEST("harvest", "收获", "收获庄稼、作物", false, false, true), HONEY("honey", "蜂巢交互", "是否可以采蜂蜜", false, false, true), HOOK("hook", "使用钓钩", "是否可以使用钓钩", false, false, true), - HOPPER("hopper", "特殊容器", "包含:漏斗/熔炉/发射器等", false, false, true), + HOPPER("hopper", "特殊容器", "包含:漏斗/熔炉/发射器/投掷器/高炉/烟熏炉", false, false, true), IGNITE("ignite", "点燃", "是否可以使用打火石点火", false, false, true), LEVER("lever", "使用拉杆", "是否可以使用拉杆", false, false, true), MOB_DROP_ITEM("mob_drop_item", "生物战利品掉落", "生物死亡时是否产生凋落物", true, true, true), @@ -61,6 +62,8 @@ public enum Flag { TRAMPLE("trample", "作物践踏", "是否可以践踏作物(关闭意味着保护耕地)", false, true, true), VEHICLE_DESTROY("vehicle_destroy", "破坏载具", "是否可以破坏载具(主要是矿车)", false, false, true), VEHICLE_SPAWN("vehicle_spawn", "生成载具", "是否可以生成载具(主要是矿车)", false, false, true), + VILLAGER_KILLING("villager_killing", "对村民造成伤害", "是否可以对村民造成伤害", false, false, true), + VILLAGER_SPAWN("villager_spawn", "村民繁殖", "是否允许村民繁殖", true, true, true), WITHER_SPAWN("wither_spawn", "凋零生成", "凋零生成", false, true, true), ; private final String flag_name; @@ -119,6 +122,26 @@ public enum Flag { return Arrays.asList(Flag.values()); } + public static List getDominionOnlyFlagsEnabled() { + List flags = new ArrayList<>(); + for (Flag flag : Flag.values()) { + if (!flag.dominion_only) { + continue; + } + if (!flag.enable) { + continue; + } + flags.add(flag); + } + Comparator comparator = Collator.getInstance(java.util.Locale.CHINA); + flags.sort((o1, o2) -> comparator.compare(o1.getDisplayName(), o2.getDisplayName())); + return flags; + } + + public static boolean isDominionOnlyFlag(String flagName) { + return getFlag(flagName).dominion_only; + } + public static List getDominionFlagsEnabled() { List flags = new ArrayList<>(); for (Flag flag : Flag.values()) { diff --git a/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java b/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java index bedb5bf..156bc88 100644 --- a/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java +++ b/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java @@ -1,5 +1,9 @@ package cn.lunadeer.dominion.dtos; +import cn.lunadeer.minecraftpluginutils.databse.DatabaseManager; +import cn.lunadeer.minecraftpluginutils.databse.Field; +import cn.lunadeer.minecraftpluginutils.databse.syntax.InsertRow; +import cn.lunadeer.minecraftpluginutils.databse.syntax.UpdateRow; import cn.lunadeer.dominion.Dominion; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; @@ -7,6 +11,8 @@ import org.bukkit.entity.Player; import javax.annotation.Nullable; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Timestamp; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -37,24 +43,31 @@ public class PlayerDTO { return query(sql); } - public PlayerDTO onJoin() { + public PlayerDTO onJoin(String name) { + this.setLastKnownName(name); return update(this); } private static List query(String sql, Object... params) { List players = new ArrayList<>(); - try (ResultSet rs = Dominion.database.query(sql, params)) { - if (rs == null) return players; - while (rs.next()) { - Integer id = rs.getInt("id"); - UUID uuid = UUID.fromString(rs.getString("uuid")); - String lastKnownName = rs.getString("last_known_name"); - Long lastJoinAt = rs.getTimestamp("last_join_at").getTime(); - PlayerDTO player = new PlayerDTO(id, uuid, lastKnownName, lastJoinAt); - players.add(player); - } + try (ResultSet rs = DatabaseManager.instance.query(sql, params)) { + return getDTOFromRS(rs); } catch (SQLException e) { - Dominion.database.handleDatabaseError("查询玩家信息失败: ", e, sql); + DatabaseManager.handleDatabaseError("查询玩家信息失败: ", e, sql); + } + return players; + } + + private static List getDTOFromRS(ResultSet rs) throws SQLException { + List players = new ArrayList<>(); + if (rs == null) return players; + while (rs.next()) { + Integer id = rs.getInt("id"); + UUID uuid = UUID.fromString(rs.getString("uuid")); + String lastKnownName = rs.getString("last_known_name"); + Long lastJoinAt = rs.getTimestamp("last_join_at").getTime(); + PlayerDTO player = new PlayerDTO(id, uuid, lastKnownName, lastJoinAt); + players.add(player); } return players; } @@ -85,24 +98,44 @@ public class PlayerDTO { } private static PlayerDTO insert(PlayerDTO player) { - String sql = "INSERT INTO player_name (uuid, last_known_name, last_join_at) " + - "VALUES" + - " (?, ?, CURRENT_TIMESTAMP) " + - "RETURNING *;"; - List players = query(sql, player.getUuid().toString(), player.getLastKnownName()); - if (players.size() == 0) return null; - return players.get(0); + Field uuid = new Field("uuid", player.getUuid().toString()); + Field lastKnownName = new Field("last_known_name", player.getLastKnownName()); + Field lastJoinAt = new Field("last_join_at", Timestamp.valueOf(LocalDateTime.now())); + InsertRow insertRow = new InsertRow() + .table("player_name") + .field(uuid) + .field(lastKnownName) + .field(lastJoinAt) + .returningAll() + .onConflictOverwrite(new Field("id", null)); + try (ResultSet rs = insertRow.execute()) { + List players = getDTOFromRS(rs); + if (players.size() == 0) return null; + return players.get(0); + } catch (SQLException e) { + DatabaseManager.handleDatabaseError("插入玩家信息失败: ", e, insertRow.toString()); + return null; + } } private static PlayerDTO update(PlayerDTO player) { - String sql = "UPDATE player_name SET " + - "last_known_name = ?, " + - "last_join_at = CURRENT_TIMESTAMP " + - "WHERE uuid = ? " + - "RETURNING *;"; - List players = query(sql, player.getLastKnownName(), player.getUuid().toString()); - if (players.size() == 0) return null; - return players.get(0); + Field lastKnownName = new Field("last_known_name", player.getLastKnownName()); + Field uuid = new Field("uuid", player.getUuid().toString()); + Field lastJoinAt = new Field("last_join_at", Timestamp.valueOf(LocalDateTime.now())); + UpdateRow updateRow = new UpdateRow() + .table("player_name") + .field(lastKnownName) + .field(lastJoinAt) + .where("uuid = ?", uuid.value) + .returningAll(uuid); + try (ResultSet rs = updateRow.execute()) { + List players = getDTOFromRS(rs); + if (players.size() == 0) return null; + return players.get(0); + } catch (SQLException e) { + DatabaseManager.handleDatabaseError("更新玩家信息失败: ", e, updateRow.toString()); + return null; + } } private PlayerDTO(Integer id, UUID uuid, String lastKnownName, Long lastJoinAt) { diff --git a/src/main/java/cn/lunadeer/dominion/dtos/PlayerPrivilegeDTO.java b/src/main/java/cn/lunadeer/dominion/dtos/PlayerPrivilegeDTO.java index ec11ef1..57d533c 100644 --- a/src/main/java/cn/lunadeer/dominion/dtos/PlayerPrivilegeDTO.java +++ b/src/main/java/cn/lunadeer/dominion/dtos/PlayerPrivilegeDTO.java @@ -1,35 +1,87 @@ package cn.lunadeer.dominion.dtos; import cn.lunadeer.dominion.Cache; -import cn.lunadeer.dominion.Dominion; +import cn.lunadeer.minecraftpluginutils.databse.DatabaseManager; +import cn.lunadeer.minecraftpluginutils.databse.Field; +import cn.lunadeer.minecraftpluginutils.databse.syntax.InsertRow; +import cn.lunadeer.minecraftpluginutils.databse.syntax.UpdateRow; import java.sql.ResultSet; import java.util.*; public class PlayerPrivilegeDTO { + private static List query(String sql, Object... params) { + List players = new ArrayList<>(); + try (ResultSet rs = DatabaseManager.instance.query(sql, params)) { + return getDTOFromRS(rs); + } catch (Exception e) { + DatabaseManager.handleDatabaseError("查询玩家权限失败: ", e, sql); + } + return players; + } + + private static List getDTOFromRS(ResultSet rs) { + List players = new ArrayList<>(); + if (rs == null) return players; + try { + while (rs.next()) { + Map flags = new HashMap<>(); + for (Flag f : Flag.getPrivilegeFlagsEnabled()) { + flags.put(f, rs.getBoolean(f.getFlagName())); + } + PlayerPrivilegeDTO player = new PlayerPrivilegeDTO( + rs.getInt("id"), + UUID.fromString(rs.getString("player_uuid")), + rs.getBoolean("admin"), + rs.getInt("dom_id"), + flags + ); + players.add(player); + } + } catch (Exception e) { + DatabaseManager.handleDatabaseError("查询玩家权限失败: ", e, ""); + } + return players; + } + + private PlayerPrivilegeDTO doUpdate(UpdateRow updateRow) { + Field id = new Field("id", this.id); + updateRow.returningAll(id) + .table("player_privilege") + .where("id = ?", id.value); + try (ResultSet rs = updateRow.execute()) { + List players = getDTOFromRS(rs); + if (players.size() == 0) return null; + Cache.instance.loadPlayerPrivileges(playerUUID); + return players.get(0); + } catch (Exception e) { + DatabaseManager.handleDatabaseError("更新玩家权限失败: ", e, ""); + return null; + } + } + public static PlayerPrivilegeDTO insert(PlayerPrivilegeDTO player) { - StringBuilder sql = new StringBuilder("INSERT INTO player_privilege (player_uuid, admin, dom_id, "); - - for (Flag f : Flag.getAllPrivilegeFlags()) { - sql.append(f.getFlagName()).append(", "); + Field playerUUID = new Field("player_uuid", player.getPlayerUUID().toString()); + Field admin = new Field("admin", player.getAdmin()); + Field domID = new Field("dom_id", player.getDomID()); + InsertRow insertRow = new InsertRow().returningAll().onConflictDoNothing(new Field("id", null)) + .table("player_privilege") + .field(playerUUID) + .field(admin) + .field(domID); + for (Flag f : Flag.getPrivilegeFlagsEnabled()) { + insertRow.field(new Field(f.getFlagName(), player.getFlagValue(f))); } - sql = new StringBuilder(sql.substring(0, sql.length() - 2)); - - sql.append(") VALUES ('") - .append(player.getPlayerUUID()).append("', ") - .append(player.getAdmin()).append(", ") - .append(player.getDomID()).append(", "); - - for (Flag f : Flag.getAllPrivilegeFlags()) { - sql.append(player.getFlagValue(f)).append(", "); + try (ResultSet rs = insertRow.execute()) { + Cache.instance.loadPlayerPrivileges(player.getPlayerUUID()); + List players = getDTOFromRS(rs); + if (players.size() == 0) return null; + return players.get(0); + } catch (Exception e) { + DatabaseManager.handleDatabaseError("插入玩家权限失败: ", e, ""); + return null; } - sql = new StringBuilder(sql.substring(0, sql.length() - 2)); - - sql.append(") RETURNING *;"); - List players = query(sql.toString()); - if (players.size() == 0) return null; - return players.get(0); } public static PlayerPrivilegeDTO select(UUID playerUUID, Integer dom_id) { @@ -47,6 +99,7 @@ public class PlayerPrivilegeDTO { public static void delete(UUID player, Integer domID) { String sql = "DELETE FROM player_privilege WHERE player_uuid = ? AND dom_id = ?;"; query(sql, player.toString(), domID); + Cache.instance.loadPlayerPrivileges(player); } public static List selectAll() { @@ -89,20 +142,26 @@ public class PlayerPrivilegeDTO { public PlayerPrivilegeDTO setFlagValue(Flag flag, Boolean value) { flags.put(flag, value); - return update(this); + Field f = new Field(flag.getFlagName(), value); + UpdateRow updateRow = new UpdateRow().field(f); + return doUpdate(updateRow); } public PlayerPrivilegeDTO setAdmin(Boolean admin) { this.admin = admin; - return update(this); + Field f = new Field("admin", admin); + UpdateRow updateRow = new UpdateRow().field(f); + return doUpdate(updateRow); } public PlayerPrivilegeDTO applyTemplate(PrivilegeTemplateDTO template) { this.admin = template.getAdmin(); + UpdateRow updateRow = new UpdateRow().field(new Field("admin", admin)); for (Flag f : Flag.getPrivilegeFlagsEnabled()) { this.flags.put(f, template.getFlagValue(f)); + updateRow.field(new Field(f.getFlagName(), template.getFlagValue(f))); } - return update(this); + return doUpdate(updateRow); } private PlayerPrivilegeDTO(Integer id, UUID playerUUID, Boolean admin, Integer domID, Map flags) { @@ -123,46 +182,4 @@ public class PlayerPrivilegeDTO { } } - private static List query(String sql, Object... params) { - List players = new ArrayList<>(); - try (ResultSet rs = Dominion.database.query(sql, params)) { - if (sql.contains("UPDATE") || sql.contains("DELETE") || sql.contains("INSERT")) { - // 如果是更新操作,重新加载缓存 - Cache.instance.loadPlayerPrivileges(); - } - if (rs == null) return players; - while (rs.next()) { - Map flags = new HashMap<>(); - for (Flag f : Flag.getPrivilegeFlagsEnabled()) { - flags.put(f, rs.getBoolean(f.getFlagName())); - } - PlayerPrivilegeDTO player = new PlayerPrivilegeDTO( - rs.getInt("id"), - UUID.fromString(rs.getString("player_uuid")), - rs.getBoolean("admin"), - rs.getInt("dom_id"), - flags - ); - players.add(player); - } - } catch (Exception e) { - Dominion.database.handleDatabaseError("查询玩家权限失败: ", e, sql); - } - return players; - } - - private static PlayerPrivilegeDTO update(PlayerPrivilegeDTO player) { - String sql = "UPDATE player_privilege SET " + - "admin = " + player.getAdmin() + ", " + - "dom_id = " + player.getDomID() + ", "; - for (Flag f : Flag.getPrivilegeFlagsEnabled()) { - sql += f.getFlagName() + " = " + player.getFlagValue(f) + ", "; - } - sql = sql.substring(0, sql.length() - 2); - sql += " WHERE id = " + player.getId() + " " + - "RETURNING *;"; - List players = query(sql); - if (players.size() == 0) return null; - return players.get(0); - } } diff --git a/src/main/java/cn/lunadeer/dominion/dtos/PrivilegeTemplateDTO.java b/src/main/java/cn/lunadeer/dominion/dtos/PrivilegeTemplateDTO.java index 67484e7..6b48c89 100644 --- a/src/main/java/cn/lunadeer/dominion/dtos/PrivilegeTemplateDTO.java +++ b/src/main/java/cn/lunadeer/dominion/dtos/PrivilegeTemplateDTO.java @@ -1,6 +1,9 @@ package cn.lunadeer.dominion.dtos; -import cn.lunadeer.dominion.Dominion; +import cn.lunadeer.minecraftpluginutils.databse.DatabaseManager; +import cn.lunadeer.minecraftpluginutils.databse.Field; +import cn.lunadeer.minecraftpluginutils.databse.syntax.InsertRow; +import cn.lunadeer.minecraftpluginutils.databse.syntax.UpdateRow; import java.sql.ResultSet; import java.util.*; @@ -9,8 +12,18 @@ public class PrivilegeTemplateDTO { private static List query(String sql, Object... params) { List templates = new ArrayList<>(); - try (ResultSet rs = Dominion.database.query(sql, params)) { - if (rs == null) return templates; + try (ResultSet rs = DatabaseManager.instance.query(sql, params)) { + return getDTOFromRS(rs); + } catch (Exception e) { + DatabaseManager.handleDatabaseError("查询权限模版失败: ", e, sql); + } + return templates; + } + + private static List getDTOFromRS(ResultSet rs) { + List templates = new ArrayList<>(); + if (rs == null) return templates; + try { while (rs.next()) { Map flags = new HashMap<>(); for (Flag f : Flag.getPrivilegeFlagsEnabled()) { @@ -26,16 +39,41 @@ public class PrivilegeTemplateDTO { templates.add(template); } } catch (Exception e) { - Dominion.database.handleDatabaseError("查询权限模版失败: ", e, sql); + DatabaseManager.handleDatabaseError("查询权限模版失败: ", e, null); } return templates; } public static PrivilegeTemplateDTO create(UUID creator, String name) { - String sql = "INSERT INTO privilege_template (creator, name) VALUES (?, ?) RETURNING *;"; - List templates = query(sql, creator.toString(), name); - if (templates.size() == 0) return null; - return templates.get(0); + Field creatorField = new Field("creator", creator.toString()); + Field nameField = new Field("name", name); + InsertRow insertRow = new InsertRow().table("privilege_template").onConflictDoNothing(new Field("id", null)) + .field(creatorField) + .field(nameField) + .returningAll(); + try (ResultSet rs = insertRow.execute()) { + List templates = getDTOFromRS(rs); + if (templates.size() == 0) return null; + return templates.get(0); + } catch (Exception e) { + DatabaseManager.handleDatabaseError("创建权限模版失败: ", e, null); + return null; + } + } + + private PrivilegeTemplateDTO doUpdate(UpdateRow updateRow) { + Field id = new Field("id", this.id); + updateRow.returningAll(id) + .table("privilege_template") + .where("id = ?", id.value); + try (ResultSet rs = updateRow.execute()) { + List templates = getDTOFromRS(rs); + if (templates.size() == 0) return null; + return templates.get(0); + } catch (Exception e) { + DatabaseManager.handleDatabaseError("更新权限模版失败: ", e, null); + return null; + } } public static PrivilegeTemplateDTO select(UUID creator, String name) { @@ -93,25 +131,12 @@ public class PrivilegeTemplateDTO { public PrivilegeTemplateDTO setFlagValue(Flag flag, Boolean value) { flags.put(flag, value); - return update(this); + return doUpdate(new UpdateRow().field(new Field(flag.getFlagName(), value))); } public PrivilegeTemplateDTO setAdmin(Boolean admin) { this.admin = admin; - return update(this); - } - - private static PrivilegeTemplateDTO update(PrivilegeTemplateDTO template) { - StringBuilder sql = new StringBuilder("UPDATE privilege_template SET " + - "name = ?, " + - "admin = ?, "); - for (Flag f : Flag.getPrivilegeFlagsEnabled()) { - sql.append(f.getFlagName()).append(" = ").append(template.getFlagValue(f)).append(", "); - } - sql = new StringBuilder(sql.substring(0, sql.length() - 2) + " WHERE id = ? RETURNING *;"); - List templates = query(sql.toString(), template.getName(), template.getAdmin(), template.getId()); - if (templates.size() == 0) return null; - return templates.get(0); + return doUpdate(new UpdateRow().field(new Field("admin", admin))); } } diff --git a/src/main/java/cn/lunadeer/dominion/events/EnvironmentEvents.java b/src/main/java/cn/lunadeer/dominion/events/EnvironmentEvents.java index 02942d4..3b72a91 100644 --- a/src/main/java/cn/lunadeer/dominion/events/EnvironmentEvents.java +++ b/src/main/java/cn/lunadeer/dominion/events/EnvironmentEvents.java @@ -97,6 +97,9 @@ public class EnvironmentEvents implements Listener { @EventHandler(priority = EventPriority.HIGHEST) // trample public void onFarmlandTrample(PlayerInteractEvent event) { + if (event.getAction() != Action.PHYSICAL) { + return; + } Block block = event.getClickedBlock(); if (block == null) { return; @@ -104,11 +107,7 @@ public class EnvironmentEvents implements Listener { if (block.getType() != FARMLAND) { return; } - if (event.getAction() != Action.PHYSICAL) { - return; - } - Location location = block.getLocation(); - DominionDTO dom = Cache.instance.getDominion(location); + DominionDTO dom = Cache.instance.getDominion(block.getLocation()); checkFlag(dom, Flag.TRAMPLE, event); } @@ -161,4 +160,14 @@ public class EnvironmentEvents implements Listener { DominionDTO dom = Cache.instance.getDominion(entity.getLocation()); checkFlag(dom, Flag.ANIMAL_SPAWN, event); } + + @EventHandler(priority = EventPriority.HIGHEST) // villager_spawn + public void onVillagerSpawn(CreatureSpawnEvent event) { + Entity entity = event.getEntity(); + if (entity.getType() != EntityType.VILLAGER) { + return; + } + DominionDTO dom = Cache.instance.getDominion(entity.getLocation()); + checkFlag(dom, Flag.VILLAGER_SPAWN, event); + } } diff --git a/src/main/java/cn/lunadeer/dominion/events/PlayerEvents.java b/src/main/java/cn/lunadeer/dominion/events/PlayerEvents.java index 6e26275..351b884 100644 --- a/src/main/java/cn/lunadeer/dominion/events/PlayerEvents.java +++ b/src/main/java/cn/lunadeer/dominion/events/PlayerEvents.java @@ -8,14 +8,13 @@ import cn.lunadeer.minecraftpluginutils.Notification; import cn.lunadeer.minecraftpluginutils.Teleport; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.Tag; import org.bukkit.block.Block; import org.bukkit.entity.*; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockIgniteEvent; -import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.*; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityPlaceEvent; import org.bukkit.event.entity.ProjectileLaunchEvent; @@ -26,6 +25,7 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.*; import org.bukkit.event.vehicle.VehicleDestroyEvent; import org.bukkit.inventory.Inventory; +import org.bukkit.material.Colorable; import org.spigotmc.event.entity.EntityMountEvent; import static cn.lunadeer.dominion.events.Apis.checkFlag; @@ -36,7 +36,7 @@ public class PlayerEvents implements Listener { public void onPlayerJoin(PlayerJoinEvent event) { Player bukkitPlayer = event.getPlayer(); PlayerDTO player = PlayerDTO.get(bukkitPlayer); - player.onJoin(); // update name + player.onJoin(bukkitPlayer.getName()); // update name } @EventHandler @@ -102,9 +102,19 @@ public class PlayerEvents implements Listener { } @EventHandler(priority = EventPriority.HIGHEST) // bed - public void onBedUse(PlayerBedEnterEvent event) { + public void onBedUse(PlayerInteractEvent event) { + if (!event.getAction().isRightClick()) { + return; + } Player bukkitPlayer = event.getPlayer(); - DominionDTO dom = Cache.instance.getDominion(event.getBed().getLocation()); + Block block = event.getClickedBlock(); + if (block == null) { + return; + } + if (!(Tag.BEDS.isTagged(block.getType()))) { + return; + } + DominionDTO dom = Cache.instance.getDominion(block.getLocation()); checkFlag(dom, Flag.BED, bukkitPlayer, event); } @@ -155,36 +165,30 @@ public class PlayerEvents implements Listener { @EventHandler(priority = EventPriority.HIGHEST) // button public void onButton(PlayerInteractEvent event) { + if (!event.getAction().isRightClick()) { + return; + } Player player = event.getPlayer(); if (event.getClickedBlock() == null) { return; } - Material clicked = event.getClickedBlock().getType(); - if (clicked != Material.STONE_BUTTON && - clicked != Material.BAMBOO_BUTTON && - clicked != Material.OAK_BUTTON && - clicked != Material.SPRUCE_BUTTON && - clicked != Material.BIRCH_BUTTON && - clicked != Material.JUNGLE_BUTTON && - clicked != Material.ACACIA_BUTTON && - clicked != Material.DARK_OAK_BUTTON && - clicked != Material.CRIMSON_BUTTON && - clicked != Material.WARPED_BUTTON && - clicked != Material.POLISHED_BLACKSTONE_BUTTON && - clicked != Material.MANGROVE_BUTTON && - clicked != Material.CHERRY_BUTTON) { + Block block = event.getClickedBlock(); + if (!Tag.BUTTONS.isTagged(block.getType())) { return; } - DominionDTO dom = Cache.instance.getPlayerCurrentDominion(player); + DominionDTO dom = Cache.instance.getDominion(block.getLocation()); checkFlag(dom, Flag.BUTTON, player, event); } @EventHandler(priority = EventPriority.HIGHEST) // cake public void eatCake(PlayerInteractEvent event) { - if (event.getClickedBlock() == null) { + if (!event.getAction().isRightClick()) { return; } Block block = event.getClickedBlock(); + if (block == null) { + return; + } Material clicked = block.getType(); if (clicked != Material.CAKE) { return; @@ -276,7 +280,11 @@ public class PlayerEvents implements Listener { @EventHandler(priority = EventPriority.HIGHEST) // comparer public void comparerChange(PlayerInteractEvent event) { - if (event.getClickedBlock() == null) { + if (!event.getAction().isRightClick()) { + return; + } + Block block = event.getClickedBlock(); + if (block == null) { return; } Material clicked = event.getClickedBlock().getType(); @@ -290,45 +298,14 @@ public class PlayerEvents implements Listener { @EventHandler(priority = EventPriority.HIGHEST) // door public void doorUse(PlayerInteractEvent event) { - if (event.getClickedBlock() == null) { + if (!event.getAction().isRightClick()) { return; } - Material clicked = event.getClickedBlock().getType(); - if (clicked != Material.IRON_DOOR && - clicked != Material.OAK_DOOR && - clicked != Material.SPRUCE_DOOR && - clicked != Material.BIRCH_DOOR && - clicked != Material.JUNGLE_DOOR && - clicked != Material.ACACIA_DOOR && - clicked != Material.CHERRY_DOOR && - clicked != Material.DARK_OAK_DOOR && - clicked != Material.MANGROVE_DOOR && - clicked != Material.BAMBOO_DOOR && - clicked != Material.CRIMSON_DOOR && - clicked != Material.WARPED_DOOR && - clicked != Material.IRON_TRAPDOOR && - clicked != Material.OAK_TRAPDOOR && - clicked != Material.SPRUCE_TRAPDOOR && - clicked != Material.BIRCH_TRAPDOOR && - clicked != Material.JUNGLE_TRAPDOOR && - clicked != Material.ACACIA_TRAPDOOR && - clicked != Material.CHERRY_TRAPDOOR && - clicked != Material.DARK_OAK_TRAPDOOR && - clicked != Material.MANGROVE_TRAPDOOR && - clicked != Material.BAMBOO_TRAPDOOR && - clicked != Material.CRIMSON_TRAPDOOR && - clicked != Material.WARPED_TRAPDOOR && - clicked != Material.OAK_FENCE_GATE && - clicked != Material.SPRUCE_FENCE_GATE && - clicked != Material.BIRCH_FENCE_GATE && - clicked != Material.JUNGLE_FENCE_GATE && - clicked != Material.ACACIA_FENCE_GATE && - clicked != Material.CHERRY_FENCE_GATE && - clicked != Material.DARK_OAK_FENCE_GATE && - clicked != Material.MANGROVE_FENCE_GATE && - clicked != Material.BAMBOO_FENCE_GATE && - clicked != Material.CRIMSON_FENCE_GATE && - clicked != Material.WARPED_FENCE_GATE) { + Block block = event.getClickedBlock(); + if (block == null) { + return; + } + if (!Tag.DOORS.isTagged(block.getType())) { return; } Player player = event.getPlayer(); @@ -340,15 +317,38 @@ public class PlayerEvents implements Listener { public void dyeEvent(PlayerInteractEntityEvent event) { Player player = event.getPlayer(); Entity entity = event.getRightClicked(); - if (!(entity instanceof Sheep) - && !(entity instanceof Wolf) - && !(entity instanceof Cat)) { + if (!(entity instanceof Colorable)) { return; } DominionDTO dom = Cache.instance.getDominion(entity.getLocation()); checkFlag(dom, Flag.DYE, player, event); } + @EventHandler(priority = EventPriority.HIGHEST) // edit sign + public void onSignOpen(PlayerInteractEvent event) { + if (!event.getAction().isRightClick()) { + return; + } + Player player = event.getPlayer(); + Block block = event.getClickedBlock(); + if (block == null) { + return; + } + if (!(Tag.SIGNS.isTagged(block.getType()))) { + return; + } + DominionDTO dom = Cache.instance.getDominion(block.getLocation()); + checkFlag(dom, Flag.EDIT_SIGN, player, event); + } + + @EventHandler(priority = EventPriority.HIGHEST) // edit sign + public void onSignEdit(SignChangeEvent event) { + Player player = event.getPlayer(); + Block block = event.getBlock(); + DominionDTO dom = Cache.instance.getDominion(block.getLocation()); + checkFlag(dom, Flag.EDIT_SIGN, player, event); + } + @EventHandler(priority = EventPriority.HIGHEST) // egg public void onThrowingEgg(ProjectileLaunchEvent event) { if (!(event.getEntity().getShooter() instanceof Player)) { @@ -393,6 +393,10 @@ public class PlayerEvents implements Listener { if (!(event.getRightClicked() instanceof Animals)) { return; } + // if shearing sheep instead + if (event.getPlayer().getInventory().getItem(event.getHand()).getType() == Material.SHEARS) { + return; + } Player player = event.getPlayer(); DominionDTO dom = Cache.instance.getDominion(event.getRightClicked().getLocation()); checkFlag(dom, Flag.FEED, player, event); @@ -426,10 +430,13 @@ public class PlayerEvents implements Listener { @EventHandler(priority = EventPriority.HIGHEST) // honey public void honeyInteractive(PlayerInteractEvent event) { - if (event.getClickedBlock() == null) { + if (!event.getAction().isRightClick()) { return; } Block block = event.getClickedBlock(); + if (block == null) { + return; + } Material clicked = block.getType(); if (clicked != Material.BEEHIVE && clicked != Material.BEE_NEST) { return; @@ -481,10 +488,13 @@ public class PlayerEvents implements Listener { @EventHandler(priority = EventPriority.HIGHEST) // lever public void onLever(PlayerInteractEvent event) { - if (event.getClickedBlock() == null) { + if (!event.getAction().isRightClick()) { return; } Block block = event.getClickedBlock(); + if (block == null) { + return; + } Material clicked = block.getType(); if (clicked != Material.LEVER) { return; @@ -583,26 +593,14 @@ public class PlayerEvents implements Listener { @EventHandler(priority = EventPriority.HIGHEST) // pressure public void onPressure(PlayerInteractEvent event) { - if (event.getClickedBlock() == null) { + if (event.getAction() != Action.PHYSICAL) { return; } Block block = event.getClickedBlock(); - Material clicked = block.getType(); - if (clicked != Material.STONE_PRESSURE_PLATE && - clicked != Material.LIGHT_WEIGHTED_PRESSURE_PLATE && - clicked != Material.HEAVY_WEIGHTED_PRESSURE_PLATE && - clicked != Material.OAK_PRESSURE_PLATE && - clicked != Material.SPRUCE_PRESSURE_PLATE && - clicked != Material.BIRCH_PRESSURE_PLATE && - clicked != Material.JUNGLE_PRESSURE_PLATE && - clicked != Material.ACACIA_PRESSURE_PLATE && - clicked != Material.DARK_OAK_PRESSURE_PLATE && - clicked != Material.CRIMSON_PRESSURE_PLATE && - clicked != Material.WARPED_PRESSURE_PLATE && - clicked != Material.POLISHED_BLACKSTONE_PRESSURE_PLATE && - clicked != Material.MANGROVE_PRESSURE_PLATE && - clicked != Material.CHERRY_PRESSURE_PLATE && - clicked != Material.BAMBOO_PRESSURE_PLATE) { + if (block == null) { + return; + } + if (!Tag.PRESSURE_PLATES.isTagged(block.getType())) { return; } Player player = event.getPlayer(); @@ -693,4 +691,17 @@ public class PlayerEvents implements Listener { DominionDTO dom = Cache.instance.getDominion(entity.getLocation()); checkFlag(dom, Flag.VEHICLE_SPAWN, player, event); } + + @EventHandler(priority = EventPriority.HIGHEST) // villager_killing + public void onVillagerKilling(EntityDamageByEntityEvent event) { + if (!(event.getDamager() instanceof Player)) { + return; + } + if (!(event.getEntity() instanceof Villager)) { + return; + } + Player player = (Player) event.getDamager(); + DominionDTO dom = Cache.instance.getDominion(event.getEntity().getLocation()); + checkFlag(dom, Flag.VILLAGER_KILLING, player, event); + } } diff --git a/src/main/java/cn/lunadeer/dominion/managers/ConfigManager.java b/src/main/java/cn/lunadeer/dominion/managers/ConfigManager.java index 8faa0ac..a7a87bc 100644 --- a/src/main/java/cn/lunadeer/dominion/managers/ConfigManager.java +++ b/src/main/java/cn/lunadeer/dominion/managers/ConfigManager.java @@ -22,10 +22,6 @@ public class ConfigManager { _debug = _file.getBoolean("Debug", false); XLogger.setDebug(_debug); _db_type = _file.getString("Database.Type", "sqlite"); - if (!_db_type.equals("pgsql") && !_db_type.equals("sqlite")) { - XLogger.err("当前数据库只支持 pgsql 或 sqlite,已重置为 sqlite"); - setDbType("sqlite"); - } _db_host = _file.getString("Database.Host", "localhost"); _db_port = _file.getString("Database.Port", "5432"); _db_name = _file.getString("Database.Name", "dominion"); @@ -173,9 +169,6 @@ public class ConfigManager { } public String getDbPass() { - if (_db_pass.contains("@")) { - setDbPass("'" + _db_pass + "'"); - } return _db_pass; } diff --git a/src/main/java/cn/lunadeer/dominion/managers/DatabaseTables.java b/src/main/java/cn/lunadeer/dominion/managers/DatabaseTables.java index 7450ba7..f141507 100644 --- a/src/main/java/cn/lunadeer/dominion/managers/DatabaseTables.java +++ b/src/main/java/cn/lunadeer/dominion/managers/DatabaseTables.java @@ -1,104 +1,159 @@ package cn.lunadeer.dominion.managers; -import cn.lunadeer.dominion.Dominion; import cn.lunadeer.dominion.dtos.Flag; +import cn.lunadeer.minecraftpluginutils.databse.Field; +import cn.lunadeer.minecraftpluginutils.databse.FieldType; +import cn.lunadeer.minecraftpluginutils.databse.TableColumn; +import cn.lunadeer.minecraftpluginutils.databse.syntax.AddColumn; +import cn.lunadeer.minecraftpluginutils.databse.syntax.CreateTable; +import cn.lunadeer.minecraftpluginutils.databse.syntax.InsertRow; public class DatabaseTables { public static void migrate() { - String sql = ""; - // player name - sql = "CREATE TABLE IF NOT EXISTS player_name (" + - " id SERIAL PRIMARY KEY," + - " uuid VARCHAR(36) NOT NULL UNIQUE," + - " last_known_name TEXT NOT NULL," + - " last_join_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP" + - ");"; - Dominion.database.query(sql); + TableColumn player_name_id = new TableColumn("id", FieldType.INT, true, true, true, true, 0); + TableColumn player_name_uuid = new TableColumn("uuid", FieldType.STRING, false, false, true, true, "''"); + TableColumn player_name_last_known_name = new TableColumn("last_known_name", FieldType.STRING, false, false, true, false, "'unknown'"); + TableColumn player_name_last_join_at = new TableColumn("last_join_at", FieldType.DATETIME, false, false, true, false, "CURRENT_TIMESTAMP"); + CreateTable player_name = new CreateTable().ifNotExists(); + player_name.table("player_name") + .field(player_name_id) + .field(player_name_uuid) + .field(player_name_last_known_name) + .field(player_name_last_join_at); + player_name.execute(); // dominion table - sql = "CREATE TABLE IF NOT EXISTS dominion (" + - " id SERIAL PRIMARY KEY," + - " owner VARCHAR(36) NOT NULL," + - " name TEXT NOT NULL UNIQUE," + - " world TEXT NOT NULL," + - " x1 INT NOT NULL," + - " y1 INT NOT NULL," + - " z1 INT NOT NULL," + - " x2 INT NOT NULL," + - " y2 INT NOT NULL," + - " z2 INT NOT NULL," + - " parent_dom_id INT NOT NULL DEFAULT -1," + - " join_message TEXT NOT NULL DEFAULT '欢迎', " + - " leave_message TEXT NOT NULL DEFAULT '再见', " + - - " FOREIGN KEY (owner) REFERENCES player_name(uuid) ON DELETE CASCADE," + - " FOREIGN KEY (parent_dom_id) REFERENCES dominion(id) ON DELETE CASCADE" + - ");"; - Dominion.database.query(sql); + TableColumn dominion_id = new TableColumn("id", FieldType.INT, true, true, true, true, 0); + TableColumn dominion_owner = new TableColumn("owner", FieldType.STRING, false, false, true, false, "''"); + TableColumn dominion_name = new TableColumn("name", FieldType.STRING, false, false, true, false, "'未命名'"); + TableColumn dominion_world = new TableColumn("world", FieldType.STRING, false, false, true, false, "'world'"); + TableColumn dominion_x1 = new TableColumn("x1", FieldType.INT, false, false, true, false, 0); + TableColumn dominion_y1 = new TableColumn("y1", FieldType.INT, false, false, true, false, 0); + TableColumn dominion_z1 = new TableColumn("z1", FieldType.INT, false, false, true, false, 0); + TableColumn dominion_x2 = new TableColumn("x2", FieldType.INT, false, false, true, false, 0); + TableColumn dominion_y2 = new TableColumn("y2", FieldType.INT, false, false, true, false, 0); + TableColumn dominion_z2 = new TableColumn("z2", FieldType.INT, false, false, true, false, 0); + TableColumn dominion_parent_dom_id = new TableColumn("parent_dom_id", FieldType.INT, false, false, true, false, -1); + TableColumn dominion_join_message = new TableColumn("join_message", FieldType.STRING, false, false, true, false, "'欢迎'"); + TableColumn dominion_leave_message = new TableColumn("leave_message", FieldType.STRING, false, false, true, false, "'再见'"); + CreateTable.ForeignKey dominion_owner_fk = new CreateTable.ForeignKey(dominion_owner, "player_name", player_name_uuid, true); + CreateTable.ForeignKey dominion_parent_dom_id_fk = new CreateTable.ForeignKey(dominion_parent_dom_id, "dominion", dominion_id, true); + CreateTable dominion = new CreateTable().ifNotExists(); + dominion.table("dominion") + .field(dominion_id) + .field(dominion_owner) + .field(dominion_name) + .field(dominion_world) + .field(dominion_x1) + .field(dominion_y1) + .field(dominion_z1) + .field(dominion_x2) + .field(dominion_y2) + .field(dominion_z2) + .field(dominion_parent_dom_id) + .field(dominion_join_message) + .field(dominion_leave_message) + .foreignKey(dominion_owner_fk) + .foreignKey(dominion_parent_dom_id_fk); + dominion.execute(); // player privilege - sql = "CREATE TABLE IF NOT EXISTS player_privilege (" + - " id SERIAL PRIMARY KEY," + - " player_uuid VARCHAR(36) NOT NULL," + - " dom_id INT NOT NULL," + + TableColumn player_privilege_id = new TableColumn("id", FieldType.INT, true, true, true, true, 0); + TableColumn player_privilege_player_uuid = new TableColumn("player_uuid", FieldType.STRING, false, false, true, false, "''"); + TableColumn player_privilege_dom_id = new TableColumn("dom_id", FieldType.INT, false, false, true, false, -1); + TableColumn player_privilege_admin = new TableColumn("admin", FieldType.BOOLEAN, false, false, true, false, false); + CreateTable.ForeignKey player_privilege_player_uuid_fk = new CreateTable.ForeignKey(player_privilege_player_uuid, "player_name", player_name_uuid, true); + CreateTable.ForeignKey player_privilege_dom_id_fk = new CreateTable.ForeignKey(player_privilege_dom_id, "dominion", dominion_id, true); + CreateTable player_privilege = new CreateTable().ifNotExists(); + player_privilege.table("player_privilege") + .field(player_privilege_id) + .field(player_privilege_player_uuid) + .field(player_privilege_dom_id) + .field(player_privilege_admin) + .foreignKey(player_privilege_player_uuid_fk) + .foreignKey(player_privilege_dom_id_fk) + .unique(player_privilege_player_uuid, player_privilege_dom_id); + player_privilege.execute(); - " admin BOOLEAN NOT NULL DEFAULT FALSE," + + // server root player name + Field server_player_name_id_field = new Field("id", -1); + Field server_player_name_uuid_field = new Field("uuid", "00000000-0000-0000-0000-000000000000"); + Field server_player_name_last_known_name_field = new Field("last_known_name", "server"); + InsertRow insert_server_player_name = new InsertRow().table("player_name").onConflictDoNothing(server_player_name_id_field) + .field(server_player_name_id_field) + .field(server_player_name_uuid_field) + .field(server_player_name_last_known_name_field); + insert_server_player_name.execute(); - " UNIQUE (player_uuid, dom_id)," + - " FOREIGN KEY (player_uuid) REFERENCES player_name(uuid) ON DELETE CASCADE," + - " FOREIGN KEY (dom_id) REFERENCES dominion(id) ON DELETE CASCADE" + - ");"; - Dominion.database.query(sql); - - sql = "INSERT INTO player_name (" + - "id, uuid, last_known_name" + - ") VALUES (" + - "-1, '00000000-0000-0000-0000-000000000000', 'server'" + - ") ON CONFLICT DO NOTHING;"; - Dominion.database.query(sql); - - sql = "INSERT INTO dominion (" + - "id, owner, name, world, x1, y1, z1, x2, y2, z2, parent_dom_id, join_message, leave_message" + - ") VALUES (" + - "-1, '00000000-0000-0000-0000-000000000000', '根领地', 'all', " + - "-2147483648, -2147483648, -2147483648, " + - "2147483647, 2147483647, 2147483647, -1, " + - "'欢迎', '再见'" + - ") ON CONFLICT DO NOTHING;"; - Dominion.database.query(sql); + // server root dominion + Field server_dom_id_field = new Field("id", -1); + Field server_dom_owner_field = new Field("owner", "00000000-0000-0000-0000-000000000000"); + Field server_dom_name_field = new Field("name", "根领地"); + Field server_dom_world_field = new Field("world", "all"); + Field server_dom_x1_field = new Field("x1", -2147483648); + Field server_dom_y1_field = new Field("y1", -2147483648); + Field server_dom_z1_field = new Field("z1", -2147483648); + Field server_dom_x2_field = new Field("x2", 2147483647); + Field server_dom_y2_field = new Field("y2", 2147483647); + Field server_dom_z2_field = new Field("z2", 2147483647); + Field server_dom_parent_dom_id_field = new Field("parent_dom_id", -1); + Field server_dom_join_message_field = new Field("join_message", "欢迎"); + Field server_dom_leave_message_field = new Field("leave_message", "再见"); + InsertRow insert_server_dom = new InsertRow().table("dominion").onConflictDoNothing(server_dom_id_field) + .field(server_dom_id_field) + .field(server_dom_owner_field) + .field(server_dom_name_field) + .field(server_dom_world_field) + .field(server_dom_x1_field) + .field(server_dom_y1_field) + .field(server_dom_z1_field) + .field(server_dom_x2_field) + .field(server_dom_y2_field) + .field(server_dom_z2_field) + .field(server_dom_parent_dom_id_field) + .field(server_dom_join_message_field) + .field(server_dom_leave_message_field); + insert_server_dom.execute(); for (Flag flag : Flag.getAllDominionFlags()) { - Dominion.database.addColumnIfNotExists("dominion", - flag.getFlagName(), - "BOOLEAN NOT NULL DEFAULT " + flag.getDefaultValue()); + TableColumn column = new TableColumn(flag.getFlagName(), FieldType.BOOLEAN, false, false, true, false, flag.getDefaultValue()); + new AddColumn(column).table("dominion").ifNotExists().execute(); } for (Flag flag : Flag.getAllPrivilegeFlags()) { - Dominion.database.addColumnIfNotExists("player_privilege", - flag.getFlagName(), - "BOOLEAN NOT NULL DEFAULT " + flag.getDefaultValue()); + TableColumn column = new TableColumn(flag.getFlagName(), FieldType.BOOLEAN, false, false, true, false, flag.getDefaultValue()); + new AddColumn(column).table("player_privilege").ifNotExists().execute(); } // 1.18.0 - Dominion.database.addColumnIfNotExists("dominion", "tp_location", "TEXT NOT NULL DEFAULT 'default'"); + TableColumn dominion_tp_location = new TableColumn("tp_location", FieldType.STRING, false, false, true, false, "'default'"); + new AddColumn(dominion_tp_location).table("dominion").ifNotExists().execute(); // 1.31.0 - sql = "CREATE TABLE IF NOT EXISTS privilege_template (" + - " id SERIAL PRIMARY KEY," + - " creator VARCHAR(36) NOT NULL," + - " name TEXT NOT NULL," + - " admin BOOLEAN NOT NULL DEFAULT FALSE," + + TableColumn privilege_template_id = new TableColumn("id", FieldType.INT, true, true, true, true, 0); + TableColumn privilege_template_creator = new TableColumn("creator", FieldType.STRING, false, false, true, false, "''"); + TableColumn privilege_template_name = new TableColumn("name", FieldType.STRING, false, false, true, false, "'未命名'"); + TableColumn privilege_template_admin = new TableColumn("admin", FieldType.BOOLEAN, false, false, true, false, false); + CreateTable.ForeignKey privilege_template_creator_fk = new CreateTable.ForeignKey(privilege_template_creator, "player_name", player_name_uuid, true); + CreateTable privilege_template = new CreateTable().ifNotExists(); + privilege_template.table("privilege_template") + .field(privilege_template_id) + .field(privilege_template_creator) + .field(privilege_template_name) + .field(privilege_template_admin) + .foreignKey(privilege_template_creator_fk) + .unique(privilege_template_creator, privilege_template_name); + privilege_template.execute(); - " UNIQUE (creator, name)," + - " FOREIGN KEY (creator) REFERENCES player_name(uuid) ON DELETE CASCADE" + - ");"; - Dominion.database.query(sql); for (Flag flag : Flag.getAllPrivilegeFlags()) { - Dominion.database.addColumnIfNotExists("privilege_template", - flag.getFlagName(), - "BOOLEAN NOT NULL DEFAULT " + flag.getDefaultValue()); + TableColumn column = new TableColumn(flag.getFlagName(), FieldType.BOOLEAN, false, false, true, false, flag.getDefaultValue()); + new AddColumn(column).table("privilege_template").ifNotExists().execute(); } + + // 1.31.6 + TableColumn dominion_color = new TableColumn("color", FieldType.STRING, false, false, true, false, "'#00BFFF'"); + new AddColumn(dominion_color).table("dominion").ifNotExists().execute(); } } diff --git a/src/main/java/cn/lunadeer/dominion/tuis/DominionEnvInfo.java b/src/main/java/cn/lunadeer/dominion/tuis/DominionEnvInfo.java new file mode 100644 index 0000000..50c909e --- /dev/null +++ b/src/main/java/cn/lunadeer/dominion/tuis/DominionEnvInfo.java @@ -0,0 +1,61 @@ +package cn.lunadeer.dominion.tuis; + +import cn.lunadeer.dominion.dtos.DominionDTO; +import cn.lunadeer.dominion.dtos.Flag; +import cn.lunadeer.minecraftpluginutils.Notification; +import cn.lunadeer.minecraftpluginutils.stui.ListView; +import cn.lunadeer.minecraftpluginutils.stui.components.Button; +import cn.lunadeer.minecraftpluginutils.stui.components.Line; +import net.kyori.adventure.text.Component; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import static cn.lunadeer.dominion.commands.Apis.playerOnly; + +public class DominionEnvInfo { + + public static void show(CommandSender sender, String[] args) { + Player player = playerOnly(sender); + if (player == null) return; + if (args.length < 2) { + Notification.error(sender, "用法: /dominion env_info <领地名称> [页码]"); + return; + } + DominionDTO dominion = DominionDTO.select(args[1]); + if (dominion == null) { + Notification.error(sender, "领地 %s 不存在", args[1]); + return; + } + int page = 1; + if (args.length == 3) { + try { + page = Integer.parseInt(args[2]); + } catch (Exception ignored) { + } + } + ListView view = ListView.create(10, "/dominion env_info " + dominion.getName()); + view.title("领地 " + dominion.getName() + " 环境设置") + .navigator(Line.create() + .append(Button.create("主菜单").setExecuteCommand("/dominion menu").build()) + .append(Button.create("我的领地").setExecuteCommand("/dominion list").build()) + .append(Button.create("管理界面").setExecuteCommand("/dominion manage " + dominion.getName()).build()) + .append("环境设置")); + for (Flag flag : Flag.getDominionOnlyFlagsEnabled()) { + view.add(createOption(flag, dominion.getFlagValue(flag), dominion.getName(), page)); + } + view.showOn(player, page); + } + + private static Line createOption(Flag flag, boolean value, String dominion_name, int page) { + if (value) { + return Line.create() + .append(Button.createGreen("☑").setExecuteCommand("/dominion set " + flag.getFlagName() + " false " + dominion_name + " " + page).build()) + .append(Component.text(flag.getDisplayName()).hoverEvent(Component.text(flag.getDescription()))); + } else { + return Line.create() + .append(Button.createRed("☐").setExecuteCommand("/dominion set " + flag.getFlagName() + " true " + dominion_name + " " + page).build()) + .append(Component.text(flag.getDisplayName()).hoverEvent(Component.text(flag.getDescription()))); + } + } + +} diff --git a/src/main/java/cn/lunadeer/dominion/tuis/DominionFlagInfo.java b/src/main/java/cn/lunadeer/dominion/tuis/DominionFlagInfo.java index 574273b..4a9eb91 100644 --- a/src/main/java/cn/lunadeer/dominion/tuis/DominionFlagInfo.java +++ b/src/main/java/cn/lunadeer/dominion/tuis/DominionFlagInfo.java @@ -40,7 +40,7 @@ public class DominionFlagInfo { .append(Button.create("我的领地").setExecuteCommand("/dominion list").build()) .append(Button.create("管理界面").setExecuteCommand("/dominion manage " + dominion.getName()).build()) .append("访客权限")); - for (Flag flag : Flag.getDominionFlagsEnabled()) { + for (Flag flag : Flag.getPrivilegeFlagsEnabled()) { view.add(createOption(flag, dominion.getFlagValue(flag), dominion.getName(), page)); } view.showOn(player, page); diff --git a/src/main/java/cn/lunadeer/dominion/tuis/DominionManage.java b/src/main/java/cn/lunadeer/dominion/tuis/DominionManage.java index a377bfd..92d62b8 100644 --- a/src/main/java/cn/lunadeer/dominion/tuis/DominionManage.java +++ b/src/main/java/cn/lunadeer/dominion/tuis/DominionManage.java @@ -1,10 +1,13 @@ package cn.lunadeer.dominion.tuis; +import cn.lunadeer.dominion.Dominion; import cn.lunadeer.dominion.dtos.DominionDTO; import cn.lunadeer.minecraftpluginutils.Notification; import cn.lunadeer.minecraftpluginutils.stui.ListView; import cn.lunadeer.minecraftpluginutils.stui.components.Button; import cn.lunadeer.minecraftpluginutils.stui.components.Line; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -25,6 +28,9 @@ public class DominionManage { Line size_info = Line.create() .append(Button.create("详细信息").setExecuteCommand("/dominion info " + dominion.getName()).build()) .append("查看领地详细信息"); + Line env_info = Line.create() + .append(Button.create("环境设置").setExecuteCommand("/dominion env_info " + dominion.getName()).build()) + .append("设置领地内的一些非玩家相关效果"); Line flag_info = Line.create() .append(Button.create("访客权限").setExecuteCommand("/dominion flag_info " + dominion.getName()).build()) .append("访客在此领地的权限"); @@ -43,6 +49,11 @@ public class DominionManage { Line leave_msg = Line.create() .append(Button.create("编辑离开提示语").setExecuteCommand("/dominion cui_edit_leave_message " + dominion.getName()).build()) .append("当玩家离开领地时显示的消息"); + Line map_color = Line.create() + .append(Button.create("设置颜色").setExecuteCommand("/dominion cui_set_map_color " + dominion.getName()).build()) + .append(Component.text("设置卫星地图上的地块颜色") + .append(Component.text(dominion.getColor(), + TextColor.color(dominion.getColorR(), dominion.getColorG(), dominion.getColorB())))); ListView view = ListView.create(10, "/dominion manage " + dominion.getName()); view.title("领地 " + dominion.getName() + " 管理界面") .navigator(Line.create() @@ -50,12 +61,16 @@ public class DominionManage { .append(Button.create("我的领地").setExecuteCommand("/dominion list").build()) .append(dominion.getName())) .add(size_info) + .add(env_info) .add(flag_info) .add(privilege_list) .add(set_tp) .add(rename) .add(join_msg) - .add(leave_msg) - .showOn(player, 1); + .add(leave_msg); + if (Dominion.config.getBlueMap()) { + view.add(map_color); + } + view.showOn(player, 1); } } diff --git a/src/main/java/cn/lunadeer/dominion/tuis/ListDominion.java b/src/main/java/cn/lunadeer/dominion/tuis/ListDominion.java index 56df9c6..ebf0138 100644 --- a/src/main/java/cn/lunadeer/dominion/tuis/ListDominion.java +++ b/src/main/java/cn/lunadeer/dominion/tuis/ListDominion.java @@ -47,11 +47,11 @@ public class ListDominion { prefix.append(" | "); } for (DominionNode node : dominionTree) { - TextComponent manage = Button.createGreen("管理").setExecuteCommand("/dominion manage " + node.dominion.getName()).build(); - TextComponent delete = Button.createRed("删除").setExecuteCommand("/dominion delete " + node.dominion.getName()).build(); - Line line = Line.create().append(delete).append(manage).append(prefix + node.dominion.getName()); + TextComponent manage = Button.createGreen("管理").setExecuteCommand("/dominion manage " + node.getDominion().getName()).build(); + TextComponent delete = Button.createRed("删除").setExecuteCommand("/dominion delete " + node.getDominion().getName()).build(); + Line line = Line.create().append(delete).append(manage).append(prefix + node.getDominion().getName()); lines.add(line); - lines.addAll(BuildTreeLines(node.children, depth + 1)); + lines.addAll(BuildTreeLines(node.getChildren(), depth + 1)); } return lines; } diff --git a/src/main/java/cn/lunadeer/dominion/tuis/Menu.java b/src/main/java/cn/lunadeer/dominion/tuis/Menu.java index e5ae0d8..1543042 100644 --- a/src/main/java/cn/lunadeer/dominion/tuis/Menu.java +++ b/src/main/java/cn/lunadeer/dominion/tuis/Menu.java @@ -31,7 +31,7 @@ public class Menu { .append(Button.create("我的领地").setExecuteCommand("/dominion list").build()) .append("查看我的领地"); Line template = Line.create() - .append(Button.create("权限模板").setExecuteCommand("/dominion template_list").build()) + .append(Button.create("模板列表").setExecuteCommand("/dominion template_list").build()) .append("成员权限模板列表"); Line help = Line.create() .append(Button.create("指令帮助").setExecuteCommand("/dominion help").build()) diff --git a/src/main/java/cn/lunadeer/dominion/tuis/PrivilegeInfo.java b/src/main/java/cn/lunadeer/dominion/tuis/PrivilegeInfo.java index 83a6f64..1999ad8 100644 --- a/src/main/java/cn/lunadeer/dominion/tuis/PrivilegeInfo.java +++ b/src/main/java/cn/lunadeer/dominion/tuis/PrivilegeInfo.java @@ -59,13 +59,14 @@ public class PrivilegeInfo { view.add(Line.create() .append(Button.createGreen("☑").setExecuteCommand("/dominion set_privilege " + playerName + " admin false " + dominion.getName() + " " + page).build()) .append("管理员")); + view.add(createOption(Flag.GLOW, privilege.getFlagValue(Flag.GLOW), playerName, dominion.getName(), page)); } else { view.add(Line.create() .append(Button.createRed("☐").setExecuteCommand("/dominion set_privilege " + playerName + " admin true " + dominion.getName() + " " + page).build()) .append("管理员")); - } - for (Flag flag : Flag.getPrivilegeFlagsEnabled()) { - view.add(createOption(flag, privilege.getFlagValue(flag), playerName, dominion.getName(), page)); + for (Flag flag : Flag.getPrivilegeFlagsEnabled()) { + view.add(createOption(flag, privilege.getFlagValue(flag), playerName, dominion.getName(), page)); + } } view.showOn(player, page); } diff --git a/src/main/java/cn/lunadeer/dominion/tuis/TemplateList.java b/src/main/java/cn/lunadeer/dominion/tuis/TemplateList.java index 8dce339..62603c6 100644 --- a/src/main/java/cn/lunadeer/dominion/tuis/TemplateList.java +++ b/src/main/java/cn/lunadeer/dominion/tuis/TemplateList.java @@ -4,7 +4,6 @@ import cn.lunadeer.dominion.dtos.PrivilegeTemplateDTO; import cn.lunadeer.minecraftpluginutils.stui.ListView; import cn.lunadeer.minecraftpluginutils.stui.components.Button; import cn.lunadeer.minecraftpluginutils.stui.components.Line; -import net.kyori.adventure.text.Component; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -31,7 +30,7 @@ public class TemplateList { view.add(Line.create().append(create.build())); for (PrivilegeTemplateDTO template : templates) { - Button manage = Button.createGreen("管理").setExecuteCommand("/dominion template_manage " + template.getName()); + Button manage = Button.createGreen("配置").setExecuteCommand("/dominion template_manage " + template.getName()); Button delete = Button.createRed("删除").setExecuteCommand("/dominion template_delete " + template.getName()); Line line = Line.create() .append(delete.build()) diff --git a/src/main/java/cn/lunadeer/dominion/tuis/TemplateManage.java b/src/main/java/cn/lunadeer/dominion/tuis/TemplateManage.java index 39f5698..3a8d46c 100644 --- a/src/main/java/cn/lunadeer/dominion/tuis/TemplateManage.java +++ b/src/main/java/cn/lunadeer/dominion/tuis/TemplateManage.java @@ -10,10 +10,7 @@ import net.kyori.adventure.text.Component; 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.tuis.Apis.getPage; public class TemplateManage { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index bc30be3..a30669e 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,5 +1,5 @@ Database: - Type: sqlite # pgsql, sqlite + Type: sqlite # pgsql, sqlite, mysql Host: localhost Port: 5432 Name: dominion