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