diff --git a/pom.xml b/pom.xml index c80edf7..ffdaabb 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ cn.lunadeer Dominion - 1.32.0-beta + 1.32.0-res-migrate-beta jar Dominion diff --git a/src/main/java/cn/lunadeer/dominion/Cache.java b/src/main/java/cn/lunadeer/dominion/Cache.java index b7456c6..a816f42 100644 --- a/src/main/java/cn/lunadeer/dominion/Cache.java +++ b/src/main/java/cn/lunadeer/dominion/Cache.java @@ -28,13 +28,6 @@ public class Cache { player_current_dominion_id = new HashMap<>(); loadDominions(); loadPlayerPrivileges(); - List residences = ResMigration.extractFromResidence(Dominion.instance); - for (ResMigration.ResidenceNode node : residences) { - if (!residence_data.containsKey(node.owner)) { - residence_data.put(node.owner, new ArrayList<>()); - } - residence_data.get(node.owner).add(node); - } } /** @@ -310,6 +303,21 @@ public class Cache { } public List getResidenceData(UUID player_uuid) { + if (residence_data == null) { + residence_data = new HashMap<>(); + List residences = ResMigration.extractFromResidence(Dominion.instance); + for (ResMigration.ResidenceNode node : residences) { + if (node == null) { + continue; + } + if (!residence_data.containsKey(node.owner)) { + XLogger.debug("residence_data put %s", node.owner); + residence_data.put(node.owner, new ArrayList<>()); + } + residence_data.get(node.owner).add(node); + } + XLogger.debug("residence_data: %d", residence_data.size()); + } return residence_data.get(player_uuid); } @@ -331,5 +339,5 @@ public class Cache { public final Map NextTimeAllowTeleport = new java.util.HashMap<>(); - private final Map> residence_data = new 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 1a4c34c..77ec964 100644 --- a/src/main/java/cn/lunadeer/dominion/Commands.java +++ b/src/main/java/cn/lunadeer/dominion/Commands.java @@ -178,7 +178,7 @@ public class Commands implements TabExecutor { case "migrate_list": MigrateList.show(sender, args); break; - case "migration": + case "migrate": Migration.migrate(sender, args); break; // ---=== CUI ===--- diff --git a/src/main/java/cn/lunadeer/dominion/commands/Migration.java b/src/main/java/cn/lunadeer/dominion/commands/Migration.java index 324a6e5..3673a1f 100644 --- a/src/main/java/cn/lunadeer/dominion/commands/Migration.java +++ b/src/main/java/cn/lunadeer/dominion/commands/Migration.java @@ -4,6 +4,7 @@ import cn.lunadeer.dominion.Cache; import cn.lunadeer.dominion.controllers.BukkitPlayerOperator; import cn.lunadeer.dominion.controllers.DominionController; import cn.lunadeer.dominion.dtos.DominionDTO; +import cn.lunadeer.dominion.tuis.MigrateList; import cn.lunadeer.dominion.utils.ResMigration; import cn.lunadeer.minecraftpluginutils.Notification; import org.bukkit.command.CommandSender; @@ -17,28 +18,43 @@ import static cn.lunadeer.dominion.commands.Apis.playerOnly; public class Migration { public static void migrate(CommandSender sender, String[] args) { - Player player = playerOnly(sender); - if (player == null) return; - if (args.length != 2) { - Notification.error(sender, "用法: /dominion migrate "); - return; + try { + Player player = playerOnly(sender); + if (player == null) return; + if (args.length < 2) { + Notification.error(sender, "用法: /dominion migrate "); + return; + } + String resName = args[1]; + List res_data = Cache.instance.getResidenceData(player.getUniqueId()); + if (res_data == null) { + Notification.error(sender, "你没有可迁移的数据"); + return; + } + ResMigration.ResidenceNode resNode = res_data.stream().filter(node -> node.name.equals(resName)).findFirst().orElse(null); + if (resNode == null) { + Notification.error(sender, "未找到指定的 Residence 领地"); + return; + } + if (!resNode.owner.equals(player.getUniqueId())) { + Notification.error(sender, "你不是该领地的所有者,无法迁移此领地"); + return; + } + create(player, resNode, ""); + if (args.length == 3 ) { + int parentId = Integer.parseInt(args[2]); + String[] newArgs = new String[2]; + newArgs[0] = "migrate_list"; + newArgs[1] = String.valueOf(parentId); + MigrateList.show(sender, newArgs); + } + } catch (Exception e) { + Notification.error(sender, "迁移失败: " + e.getMessage()); } - String resName = args[1]; - List res_data = Cache.instance.getResidenceData(player.getUniqueId()); - if (res_data == null) { - Notification.error(sender, "你没有可迁移的数据"); - return; - } - ResMigration.ResidenceNode resNode = res_data.stream().filter(node -> node.name.equals(resName)).findFirst().orElse(null); - if (resNode == null) { - Notification.error(sender, "未找到指定的 Residence 领地"); - return; - } - create(player, resNode); } - private static void create(Player player, ResMigration.ResidenceNode node) { - BukkitPlayerOperator operator = BukkitPlayerOperator.create(player); + private static void create(Player player, ResMigration.ResidenceNode node, String parentName) { + BukkitPlayerOperator operator = new BukkitPlayerOperator(player); operator.getResponse().thenAccept(result -> { if (Objects.equals(result.getStatus(), BukkitPlayerOperator.Result.SUCCESS)) { DominionDTO dominion = DominionDTO.select(node.name); @@ -51,9 +67,10 @@ public class Migration { for (String msg : result.getMessages()) { Notification.info(player, msg); } + Notification.info(player, "领地 " + node.name + " 已从 Residence 迁移至 Dominion"); if (node.children != null) { for (ResMigration.ResidenceNode child : node.children) { - create(player, child); + create(player, child, node.name); } } } else if (Objects.equals(result.getStatus(), BukkitPlayerOperator.Result.WARNING)) { @@ -66,6 +83,6 @@ public class Migration { } } }); - DominionController.create(operator, node.name, node.loc1, node.loc2); + DominionController.create(operator, node.name, node.loc1, node.loc2, parentName); } } diff --git a/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java b/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java index ff34660..d68d3ac 100644 --- a/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java +++ b/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java @@ -411,7 +411,11 @@ public class DominionDTO { } public DominionDTO setTpLocation(Location loc) { - this.tp_location = loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ(); + if (loc != null) { + this.tp_location = loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ(); + } else { + this.tp_location = "default"; + } return update(this); } diff --git a/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java b/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java index 4825423..bedb5bf 100644 --- a/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java +++ b/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java @@ -1,8 +1,10 @@ package cn.lunadeer.dominion.dtos; import cn.lunadeer.dominion.Dominion; +import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; +import javax.annotation.Nullable; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; @@ -19,6 +21,17 @@ public class PlayerDTO { return re; } + public static @Nullable PlayerDTO get(OfflinePlayer player) { + if (player.getName() == null) { + return null; + } + PlayerDTO re = select(player.getUniqueId()); + if (re == null) { + re = insert(new PlayerDTO(player.getUniqueId(), player.getName(), System.currentTimeMillis())); + } + return re; + } + public static List all() { String sql = "SELECT * FROM player_name WHERE id > 0;"; return query(sql); diff --git a/src/main/java/cn/lunadeer/dominion/tuis/MigrateList.java b/src/main/java/cn/lunadeer/dominion/tuis/MigrateList.java index 59ca2de..55e2569 100644 --- a/src/main/java/cn/lunadeer/dominion/tuis/MigrateList.java +++ b/src/main/java/cn/lunadeer/dominion/tuis/MigrateList.java @@ -5,7 +5,11 @@ import cn.lunadeer.dominion.utils.ResMigration; 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.TextComponent; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.format.TextDecoration; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -38,29 +42,32 @@ public class MigrateList { if (res_data == null) { view.add(Line.create().append("你没有可迁移的数据")); } else { - view.addLines(BuildTreeLines(res_data, 0)); + view.addLines(BuildTreeLines(res_data, 0, page)); } view.showOn(player, page); } - public static List BuildTreeLines(List dominionTree, Integer depth) { + public static List BuildTreeLines(List dominionTree, Integer depth, int page) { List lines = new ArrayList<>(); StringBuilder prefix = new StringBuilder(); for (int i = 0; i < depth; i++) { prefix.append(" | "); } for (ResMigration.ResidenceNode node : dominionTree) { - TextComponent migrate = Button.create("迁移").setExecuteCommand("/dominion migrate " + node.name).build(); + TextComponent migrate = Button.create("迁移").setExecuteCommand("/dominion migrate " + node.name + " " + page).build(); Line line = Line.create(); if (depth == 0) { line.append(migrate); } else { - line.append(" "); + line.append(Component.text("[迁移]", + Style.style(TextColor.color(190, 190, 190), + TextDecoration.STRIKETHROUGH)) + .hoverEvent(Component.text("子领地无法手动迁移,会随父领地自动迁移"))); } line.append(prefix + node.name); lines.add(line); - lines.addAll(BuildTreeLines(node.children, depth + 1)); + lines.addAll(BuildTreeLines(node.children, depth + 1, page)); } return lines; } diff --git a/src/main/java/cn/lunadeer/dominion/utils/ResMigration.java b/src/main/java/cn/lunadeer/dominion/utils/ResMigration.java index f44ef18..5c5170d 100644 --- a/src/main/java/cn/lunadeer/dominion/utils/ResMigration.java +++ b/src/main/java/cn/lunadeer/dominion/utils/ResMigration.java @@ -2,22 +2,21 @@ package cn.lunadeer.dominion.utils; import cn.lunadeer.dominion.Dominion; import cn.lunadeer.dominion.dtos.PlayerDTO; +import cn.lunadeer.dominion.utils.Residence.Message; +import cn.lunadeer.dominion.utils.Residence.Permission; import cn.lunadeer.dominion.utils.Residence.Residence; import cn.lunadeer.dominion.utils.Residence.SaveFile; import cn.lunadeer.minecraftpluginutils.XLogger; import org.bukkit.Location; +import org.bukkit.OfflinePlayer; import org.bukkit.World; -import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.yaml.snakeyaml.Yaml; import java.io.File; import java.io.InputStream; import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.*; public class ResMigration { @@ -70,7 +69,7 @@ Residences: resSave = new File(resSave, "Save"); resSave = new File(resSave, "Worlds"); if (!resSave.exists()) { - XLogger.info("Residence Save not found"); + XLogger.info("Residence Save not found, skipping migration"); return dominions; } // list .yml files @@ -86,17 +85,18 @@ Residences: XLogger.err("Failed to process file: %s, %s", file.getName(), e.getMessage()); } } + XLogger.info("Extract %d residences", dominions.size()); return dominions; } private static ResidenceNode parseDominion(String name, World world, Residence res, SaveFile save) { - Player bukkitOwner = Dominion.instance.getServer().getPlayer(res.Permissions.OwnerUUID); - if (bukkitOwner == null) { + OfflinePlayer bukkitOwner = Dominion.instance.getServer().getOfflinePlayer(UUID.fromString(res.Permissions.OwnerUUID)); + PlayerDTO owner = PlayerDTO.get(bukkitOwner); + if (owner == null) { XLogger.warn("Owner not found: " + res.Permissions.OwnerUUID); return null; } - PlayerDTO owner = PlayerDTO.get(bukkitOwner); - String[] loc = res.Areas.get("main").split(":"); + String[] loc = res.Areas.values().toArray()[0].toString().split(":"); if (loc.length != 6) { XLogger.warn("Invalid location: " + res.Areas.get("main")); return null; @@ -109,9 +109,11 @@ Residences: dominionNode.leaveMessage = save.Messages.get(res.Messages).LeaveMessage; dominionNode.loc1 = new Location(world, Double.parseDouble(loc[0]), Double.parseDouble(loc[1]), Double.parseDouble(loc[2])); dominionNode.loc2 = new Location(world, Double.parseDouble(loc[3]), Double.parseDouble(loc[4]), Double.parseDouble(loc[5])); - String[] tpLocStr = res.TPLoc.split(":"); - if (tpLocStr.length == 3) { - dominionNode.tpLoc = new Location(world, Double.parseDouble(tpLocStr[0]), Double.parseDouble(tpLocStr[1]), Double.parseDouble(tpLocStr[2])); + if (res.TPLoc != null) { + String[] tpLocStr = res.TPLoc.split(":"); + if (tpLocStr.length == 3) { + dominionNode.tpLoc = new Location(world, Double.parseDouble(tpLocStr[0]), Double.parseDouble(tpLocStr[1]), Double.parseDouble(tpLocStr[2])); + } } if (res.Subzones != null) { for (Map.Entry entry : res.Subzones.entrySet()) { @@ -124,12 +126,53 @@ Residences: return dominionNode; } + private static Map parseResYml(Map zones) { + Map res = new HashMap<>(); + for (Map.Entry entry : zones.entrySet()) { + Map zone = (Map) entry.getValue(); + Residence residence = new Residence(); + if (zone.containsKey("TPLoc")) { + residence.setTPLoc((String) zone.get("TPLoc")); + } + residence.setMessages((int) zone.get("Messages")); + Permission permission = new Permission(); + permission.OwnerUUID = ((Map) zone.get("Permissions")).get("OwnerUUID").toString(); + permission.OwnerLastKnownName = ((Map) zone.get("Permissions")).get("OwnerLastKnownName").toString(); + residence.setPermissions(permission); + residence.setAreas((Map) zone.get("Areas")); + if (zone.containsKey("Subzones")) { + residence.setSubzones(parseResYml((Map) zone.get("Subzones"))); + } + res.put(entry.getKey(), residence); + } + return res; + } + private static List processWorld(File saveFile) throws Exception { + XLogger.debug("====================================="); + XLogger.debug("Processing file: %s", saveFile.getName()); String worldName = saveFile.getName().replace("res_", "").replace(".yml", ""); World world = Dominion.instance.getServer().getWorld(worldName); - Yaml yaml = new Yaml(); InputStream inputStream = Files.newInputStream(saveFile.toPath()); - SaveFile save = yaml.loadAs(inputStream, SaveFile.class); + + Map yaml = new Yaml().load(inputStream); + + SaveFile save = new SaveFile(); + + Map Messages = (Map) yaml.get("Messages"); + Map messages = new HashMap<>(); + for (Map.Entry entry : Messages.entrySet()) { + Map message = (Map) entry.getValue(); + Message msg = new Message(); + msg.EnterMessage = (String) message.get("EnterMessage"); + msg.LeaveMessage = (String) message.get("LeaveMessage"); + messages.put(entry.getKey(), msg); + } + save.setMessages(messages); + + Map Residences = (Map) yaml.get("Residences"); + save.Residences = parseResYml(Residences); + inputStream.close(); List dominions = new ArrayList<>(); for (Map.Entry entry : save.Residences.entrySet()) { diff --git a/src/main/java/cn/lunadeer/dominion/utils/Residence/Residence.java b/src/main/java/cn/lunadeer/dominion/utils/Residence/Residence.java index 3cca76f..0ac0004 100644 --- a/src/main/java/cn/lunadeer/dominion/utils/Residence/Residence.java +++ b/src/main/java/cn/lunadeer/dominion/utils/Residence/Residence.java @@ -7,7 +7,6 @@ public class Residence { public Map Subzones; public int Messages; public Permission Permissions; - public long CreatedOn; public Map Areas; // getters and setters @@ -44,14 +43,6 @@ public class Residence { Permissions = permissions; } - public long getCreatedOn() { - return CreatedOn; - } - - public void setCreatedOn(long createdOn) { - CreatedOn = createdOn; - } - public Map getAreas() { return Areas; } diff --git a/src/main/java/cn/lunadeer/dominion/utils/Time.java b/src/main/java/cn/lunadeer/dominion/utils/Time.java deleted file mode 100644 index 8f95b54..0000000 --- a/src/main/java/cn/lunadeer/dominion/utils/Time.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.lunadeer.dominion.utils; - -import org.bukkit.Bukkit; - -import java.text.SimpleDateFormat; -import java.util.Date; - -public class Time { - - public static String nowStr() { - // yyyy-MM-dd HH:mm:ss - return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); - } - - /** - * 尝试获取folia的调度器 - * - * @return 是否成功 - */ - private static boolean tryFolia() { - try { - Bukkit.getAsyncScheduler(); - return true; - } catch (Throwable ignored) { - } - return false; - } - - private static Boolean IS_FOLIA = null; - - /** - * 判断是否是folia核心 - * - * @return 是否是folia核心 - */ - public static Boolean isFolia() { - if (IS_FOLIA == null) IS_FOLIA = tryFolia(); - return IS_FOLIA; - } -}