diff --git a/pom.xml b/pom.xml
index 3d4700e..c80edf7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
cn.lunadeer
Dominion
- 1.31.1-beta
+ 1.32.0-beta
jar
Dominion
@@ -90,5 +90,10 @@
v2.6.2
provided
+
+ org.yaml
+ snakeyaml
+ 2.0
+
diff --git a/src/main/java/cn/lunadeer/dominion/Cache.java b/src/main/java/cn/lunadeer/dominion/Cache.java
index ce65544..b7456c6 100644
--- a/src/main/java/cn/lunadeer/dominion/Cache.java
+++ b/src/main/java/cn/lunadeer/dominion/Cache.java
@@ -4,6 +4,7 @@ import cn.lunadeer.dominion.dtos.DominionDTO;
import cn.lunadeer.dominion.dtos.Flag;
import cn.lunadeer.dominion.dtos.PlayerDTO;
import cn.lunadeer.dominion.dtos.PlayerPrivilegeDTO;
+import cn.lunadeer.dominion.utils.ResMigration;
import cn.lunadeer.minecraftpluginutils.Notification;
import cn.lunadeer.minecraftpluginutils.ParticleRender;
import cn.lunadeer.minecraftpluginutils.Scheduler;
@@ -27,6 +28,13 @@ 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);
+ }
}
/**
@@ -301,6 +309,10 @@ public class Cache {
return count;
}
+ public List getResidenceData(UUID player_uuid) {
+ return residence_data.get(player_uuid);
+ }
+
public List getDominions() {
return new ArrayList<>(id_dominions.values());
}
@@ -318,4 +330,6 @@ public class Cache {
private static final long UPDATE_INTERVAL = 1000 * 4;
public final Map NextTimeAllowTeleport = new java.util.HashMap<>();
+
+ private final Map> residence_data = new HashMap<>();
}
diff --git a/src/main/java/cn/lunadeer/dominion/Commands.java b/src/main/java/cn/lunadeer/dominion/Commands.java
index 6b1699c..1a4c34c 100644
--- a/src/main/java/cn/lunadeer/dominion/Commands.java
+++ b/src/main/java/cn/lunadeer/dominion/Commands.java
@@ -5,6 +5,7 @@ import cn.lunadeer.dominion.controllers.PlayerController;
import cn.lunadeer.dominion.cuis.*;
import cn.lunadeer.dominion.dtos.PlayerDTO;
import cn.lunadeer.dominion.tuis.*;
+import cn.lunadeer.dominion.tuis.MigrateList;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
@@ -174,6 +175,12 @@ public class Commands implements TabExecutor {
case "select_template":
SelectTemplate.show(sender, args);
break;
+ case "migrate_list":
+ MigrateList.show(sender, args);
+ break;
+ case "migration":
+ Migration.migrate(sender, args);
+ break;
// ---=== CUI ===---
case "cui_rename":
RenameDominion.open(sender, args);
diff --git a/src/main/java/cn/lunadeer/dominion/commands/Migration.java b/src/main/java/cn/lunadeer/dominion/commands/Migration.java
new file mode 100644
index 0000000..324a6e5
--- /dev/null
+++ b/src/main/java/cn/lunadeer/dominion/commands/Migration.java
@@ -0,0 +1,71 @@
+package cn.lunadeer.dominion.commands;
+
+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.utils.ResMigration;
+import cn.lunadeer.minecraftpluginutils.Notification;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.List;
+import java.util.Objects;
+
+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;
+ }
+ 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);
+ operator.getResponse().thenAccept(result -> {
+ if (Objects.equals(result.getStatus(), BukkitPlayerOperator.Result.SUCCESS)) {
+ DominionDTO dominion = DominionDTO.select(node.name);
+ if (dominion == null) {
+ return;
+ }
+ dominion.setTpLocation(node.tpLoc)
+ .setJoinMessage(node.joinMessage)
+ .setLeaveMessage(node.leaveMessage);
+ for (String msg : result.getMessages()) {
+ Notification.info(player, msg);
+ }
+ if (node.children != null) {
+ for (ResMigration.ResidenceNode child : node.children) {
+ create(player, child);
+ }
+ }
+ } else if (Objects.equals(result.getStatus(), BukkitPlayerOperator.Result.WARNING)) {
+ for (String msg : result.getMessages()) {
+ Notification.warn(player, msg);
+ }
+ } else {
+ for (String msg : result.getMessages()) {
+ Notification.error(player, msg);
+ }
+ }
+ });
+ DominionController.create(operator, node.name, node.loc1, node.loc2);
+ }
+}
diff --git a/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java b/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java
index 08f8089..ff34660 100644
--- a/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java
+++ b/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java
@@ -116,7 +116,7 @@ public class DominionDTO {
for (Flag f : Flag.getAllDominionFlags()) {
sql.append(f.getDefaultValue()).append(", ");
}
- sql.append("'default', ?, ?");
+ sql.append("?, ?, ?");
sql.append(") RETURNING *;");
List dominions = query(sql.toString(),
dominion.getOwner(),
@@ -128,8 +128,9 @@ public class DominionDTO {
dominion.getX2(),
dominion.getY2(),
dominion.getZ2(),
- "欢迎来到 ${DOM_NAME}!",
- "你正在离开 ${DOM_NAME},欢迎下次光临~"
+ dominion.tp_location,
+ dominion.getJoinMessage(),
+ dominion.getLeaveMessage()
);
if (dominions.size() == 0) return null;
return dominions.get(0);
@@ -234,10 +235,10 @@ public class DominionDTO {
private Integer y2;
private Integer z2;
private Integer parentDomId = -1;
- private String joinMessage = "欢迎";
- private String leaveMessage = "再见";
+ private String joinMessage = "欢迎来到 ${DOM_NAME}!";
+ private String leaveMessage = "你正在离开 ${DOM_NAME},欢迎下次光临~";
private final Map flags = new HashMap<>();
- private String tp_location;
+ private String tp_location = "default";
// getters and setters
public Integer getId() {
diff --git a/src/main/java/cn/lunadeer/dominion/tuis/Menu.java b/src/main/java/cn/lunadeer/dominion/tuis/Menu.java
index f719426..e1094ae 100644
--- a/src/main/java/cn/lunadeer/dominion/tuis/Menu.java
+++ b/src/main/java/cn/lunadeer/dominion/tuis/Menu.java
@@ -38,6 +38,9 @@ public class Menu {
Line link = Line.create()
.append(Button.create("使用文档").setOpenURL("https://ssl.lunadeer.cn:14448/doc/23/").build())
.append("在浏览器中打开使用文档");
+ Line migrate = Line.create()
+ .append(Button.create("迁移数据").setExecuteCommand("/dominion migrate_list").build())
+ .append("把你的领地从Residence迁移到Dominion");
Line all = Line.create()
.append(Button.create("所有领地").setExecuteCommand("/dominion all_dominion").build())
.append("查看所有领地");
@@ -57,7 +60,8 @@ public class Menu {
.add(list)
.add(template)
.add(help)
- .add(link);
+ .add(link)
+ .add(migrate);
if (player.isOp()) {
view.add(Line.create().append(""));
view.add(Line.create().append(Component.text("--- 以下选项仅OP可见 ---", ViewStyles.main_color)));
diff --git a/src/main/java/cn/lunadeer/dominion/tuis/MigrateList.java b/src/main/java/cn/lunadeer/dominion/tuis/MigrateList.java
new file mode 100644
index 0000000..59ca2de
--- /dev/null
+++ b/src/main/java/cn/lunadeer/dominion/tuis/MigrateList.java
@@ -0,0 +1,67 @@
+package cn.lunadeer.dominion.tuis;
+
+import cn.lunadeer.dominion.Cache;
+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.TextComponent;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static cn.lunadeer.dominion.commands.Apis.playerOnly;
+
+public class MigrateList {
+
+ public static void show(CommandSender sender, String[] args) {
+ Player player = playerOnly(sender);
+ if (player == null) return;
+
+ int page = 1;
+ if (args.length == 2) {
+ try {
+ page = Integer.parseInt(args[1]);
+ } catch (Exception ignored) {
+ }
+ }
+
+ ListView view = ListView.create(10, "/dominion migrate_list");
+
+ view.title("从 Residence 迁移数据");
+ view.navigator(Line.create().append(Button.create("主菜单").setExecuteCommand("/dominion menu").build()).append("Res数据"));
+
+ List res_data = Cache.instance.getResidenceData(player.getUniqueId());
+
+ if (res_data == null) {
+ view.add(Line.create().append("你没有可迁移的数据"));
+ } else {
+ view.addLines(BuildTreeLines(res_data, 0));
+ }
+
+ view.showOn(player, page);
+ }
+
+ public static List BuildTreeLines(List dominionTree, Integer depth) {
+ 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();
+ Line line = Line.create();
+ if (depth == 0) {
+ line.append(migrate);
+ } else {
+ line.append(" ");
+ }
+ line.append(prefix + node.name);
+ lines.add(line);
+ lines.addAll(BuildTreeLines(node.children, depth + 1));
+ }
+ return lines;
+ }
+}
diff --git a/src/main/java/cn/lunadeer/dominion/utils/ResMigration.java b/src/main/java/cn/lunadeer/dominion/utils/ResMigration.java
new file mode 100644
index 0000000..f44ef18
--- /dev/null
+++ b/src/main/java/cn/lunadeer/dominion/utils/ResMigration.java
@@ -0,0 +1,144 @@
+package cn.lunadeer.dominion.utils;
+
+import cn.lunadeer.dominion.Dominion;
+import cn.lunadeer.dominion.dtos.PlayerDTO;
+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.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;
+
+public class ResMigration {
+
+
+ /*
+Residences:
+ '03':
+ TPLoc: -3967.62:48.0:-1988.87:4.8:-5.08
+ Messages: 1
+ Permissions:
+ PlayerFlags:
+ 3244b8fb-3cf9-433e-8f4a-bb90bf6d4f54: 1
+ 8075e1ae-62fc-482f-b3af-3fc5b2770a2c: 2
+ 0a23b4e5-f18e-4f8b-947d-558444bb27ca: 3
+ AreaFlags: 4
+ OwnerUUID: 8075e1ae-62fc-482f-b3af-3fc5b2770a2c
+ OwnerLastKnownName: guajn
+ CreatedOn: 1630491137410
+ Areas:
+ main: -3998:0:-2014:-3939:255:-1955
+ '04':
+ TPLoc: -5640.7:189.0:-2029.38:40.35:-96.3
+ Messages: 1
+ Permissions:
+ PlayerFlags:
+ 8075e1ae-62fc-482f-b3af-3fc5b2770a2c: 2
+ 0a23b4e5-f18e-4f8b-947d-558444bb27ca: 1
+ AreaFlags: 5
+ OwnerUUID: 8075e1ae-62fc-482f-b3af-3fc5b2770a2c
+ OwnerLastKnownName: guajn
+ CreatedOn: 1641656609270
+ Areas:
+ main: -5673:0:-2055:-5609:255:-2005
+ */
+ public static class ResidenceNode {
+ public UUID owner;
+ public World world;
+ public String name;
+ public Location loc1;
+ public Location loc2;
+ public Location tpLoc;
+ public String joinMessage;
+ public String leaveMessage;
+ public List children = new ArrayList<>();
+ }
+
+ public static List extractFromResidence(JavaPlugin plugin) {
+ List dominions = new ArrayList<>();
+ File resSave = new File(plugin.getDataFolder().getParent(), "Residence");
+ resSave = new File(resSave, "Save");
+ resSave = new File(resSave, "Worlds");
+ if (!resSave.exists()) {
+ XLogger.info("Residence Save not found");
+ return dominions;
+ }
+ // list .yml files
+ File[] files = resSave.listFiles((dir, name) -> name.endsWith(".yml"));
+ if (files == null || files.length == 0) {
+ XLogger.info("No save files found");
+ return dominions;
+ }
+ for (File file : files) {
+ try {
+ dominions.addAll(processWorld(file));
+ } catch (Exception e) {
+ XLogger.err("Failed to process file: %s, %s", file.getName(), e.getMessage());
+ }
+ }
+ 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) {
+ XLogger.warn("Owner not found: " + res.Permissions.OwnerUUID);
+ return null;
+ }
+ PlayerDTO owner = PlayerDTO.get(bukkitOwner);
+ String[] loc = res.Areas.get("main").split(":");
+ if (loc.length != 6) {
+ XLogger.warn("Invalid location: " + res.Areas.get("main"));
+ return null;
+ }
+ ResidenceNode dominionNode = new ResidenceNode();
+ dominionNode.owner = owner.getUuid();
+ dominionNode.world = world;
+ dominionNode.name = name;
+ dominionNode.joinMessage = save.Messages.get(res.Messages).EnterMessage;
+ 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.Subzones != null) {
+ for (Map.Entry entry : res.Subzones.entrySet()) {
+ ResidenceNode sub = parseDominion(entry.getKey(), world, entry.getValue(), save);
+ if (sub != null) {
+ dominionNode.children.add(sub);
+ }
+ }
+ }
+ return dominionNode;
+ }
+
+ private static List processWorld(File saveFile) throws Exception {
+ 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);
+ inputStream.close();
+ List dominions = new ArrayList<>();
+ for (Map.Entry entry : save.Residences.entrySet()) {
+ String name = entry.getKey();
+ Residence residence = entry.getValue();
+ ResidenceNode dominion = parseDominion(name, world, residence, save);
+ dominions.add(dominion);
+ }
+ return dominions;
+ }
+
+}
diff --git a/src/main/java/cn/lunadeer/dominion/utils/Residence/Message.java b/src/main/java/cn/lunadeer/dominion/utils/Residence/Message.java
new file mode 100644
index 0000000..8dc1d24
--- /dev/null
+++ b/src/main/java/cn/lunadeer/dominion/utils/Residence/Message.java
@@ -0,0 +1,24 @@
+package cn.lunadeer.dominion.utils.Residence;
+
+public class Message {
+ public String LeaveMessage;
+ public String EnterMessage;
+
+ // getters and setters
+
+ public String getLeaveMessage() {
+ return LeaveMessage;
+ }
+
+ public void setLeaveMessage(String leaveMessage) {
+ LeaveMessage = leaveMessage;
+ }
+
+ public String getEnterMessage() {
+ return EnterMessage;
+ }
+
+ public void setEnterMessage(String enterMessage) {
+ EnterMessage = enterMessage;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/cn/lunadeer/dominion/utils/Residence/Permission.java b/src/main/java/cn/lunadeer/dominion/utils/Residence/Permission.java
new file mode 100644
index 0000000..71a46ae
--- /dev/null
+++ b/src/main/java/cn/lunadeer/dominion/utils/Residence/Permission.java
@@ -0,0 +1,24 @@
+package cn.lunadeer.dominion.utils.Residence;
+
+public class Permission {
+ public String OwnerUUID;
+ public String OwnerLastKnownName;
+
+ // getters and setters
+
+ public String getOwnerUUID() {
+ return OwnerUUID;
+ }
+
+ public void setOwnerUUID(String ownerUUID) {
+ OwnerUUID = ownerUUID;
+ }
+
+ public String getOwnerLastKnownName() {
+ return OwnerLastKnownName;
+ }
+
+ public void setOwnerLastKnownName(String ownerLastKnownName) {
+ OwnerLastKnownName = ownerLastKnownName;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/cn/lunadeer/dominion/utils/Residence/Residence.java b/src/main/java/cn/lunadeer/dominion/utils/Residence/Residence.java
new file mode 100644
index 0000000..3cca76f
--- /dev/null
+++ b/src/main/java/cn/lunadeer/dominion/utils/Residence/Residence.java
@@ -0,0 +1,62 @@
+package cn.lunadeer.dominion.utils.Residence;
+
+import java.util.Map;
+
+public class Residence {
+ public String TPLoc;
+ public Map Subzones;
+ public int Messages;
+ public Permission Permissions;
+ public long CreatedOn;
+ public Map Areas;
+
+ // getters and setters
+
+ public String getTPLoc() {
+ return TPLoc;
+ }
+
+ public void setTPLoc(String TPLoc) {
+ this.TPLoc = TPLoc;
+ }
+
+ public Map getSubzones() {
+ return Subzones;
+ }
+
+ public void setSubzones(Map subzones) {
+ Subzones = subzones;
+ }
+
+ public int getMessages() {
+ return Messages;
+ }
+
+ public void setMessages(int messages) {
+ Messages = messages;
+ }
+
+ public Permission getPermissions() {
+ return Permissions;
+ }
+
+ public void setPermissions(Permission permissions) {
+ Permissions = permissions;
+ }
+
+ public long getCreatedOn() {
+ return CreatedOn;
+ }
+
+ public void setCreatedOn(long createdOn) {
+ CreatedOn = createdOn;
+ }
+
+ public Map getAreas() {
+ return Areas;
+ }
+
+ public void setAreas(Map areas) {
+ Areas = areas;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/cn/lunadeer/dominion/utils/Residence/SaveFile.java b/src/main/java/cn/lunadeer/dominion/utils/Residence/SaveFile.java
new file mode 100644
index 0000000..6bdc34f
--- /dev/null
+++ b/src/main/java/cn/lunadeer/dominion/utils/Residence/SaveFile.java
@@ -0,0 +1,25 @@
+package cn.lunadeer.dominion.utils.Residence;
+
+import java.util.Map;
+
+public class SaveFile {
+ public Map Residences;
+ public Map Messages;
+
+ // getters and setters
+ public Map getResidences() {
+ return Residences;
+ }
+
+ public void setResidences(Map residences) {
+ Residences = residences;
+ }
+
+ public Map getMessages() {
+ return Messages;
+ }
+
+ public void setMessages(Map messages) {
+ Messages = messages;
+ }
+}
\ No newline at end of file