diff --git a/README.md b/README.md
index feb2fa2..dd9c19d 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,7 @@
- 支持经济系统(需要 Vault 前置);
- 领地区域可视化;
- 管理员可在游戏内使用TUI配置领地系统;
+- 支持[从 Residence 迁移](https://ssl.lunadeer.cn:14448/doc/73/)领地数据;
diff --git a/pom.xml b/pom.xml
index ce02b18..427be4f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -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 9d4c30a..4ab7c4e 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;
@@ -344,6 +345,25 @@ public class Cache {
return count;
}
+ 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);
+ }
+
public List getDominions() {
return new ArrayList<>(id_dominions.values());
}
@@ -361,4 +381,6 @@ public class Cache {
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 efeae3c..4bfbf04 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 "migrate":
+ Migration.migrate(sender, args);
+ break;
case "set_map_color":
DominionOperate.setMapColor(sender, args);
break;
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..3a7df89
--- /dev/null
+++ b/src/main/java/cn/lunadeer/dominion/commands/Migration.java
@@ -0,0 +1,95 @@
+package cn.lunadeer.dominion.commands;
+
+import cn.lunadeer.dominion.Cache;
+import cn.lunadeer.dominion.Dominion;
+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;
+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) {
+ try {
+ Player player = playerOnly(sender);
+ if (player == null) return;
+
+ if (!Dominion.config.getResidenceMigration()) {
+ Notification.error(sender, "Residence 迁移功能没有开启");
+ 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());
+ }
+ }
+
+ 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);
+ if (dominion == null) {
+ return;
+ }
+ dominion.setTpLocation(node.tpLoc)
+ .setJoinMessage(node.joinMessage)
+ .setLeaveMessage(node.leaveMessage);
+ 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, node.name);
+ }
+ }
+ } 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, parentName, true);
+ }
+}
diff --git a/src/main/java/cn/lunadeer/dominion/commands/SetConfig.java b/src/main/java/cn/lunadeer/dominion/commands/SetConfig.java
index a8f0671..2fb88c4 100644
--- a/src/main/java/cn/lunadeer/dominion/commands/SetConfig.java
+++ b/src/main/java/cn/lunadeer/dominion/commands/SetConfig.java
@@ -67,6 +67,9 @@ public class SetConfig {
case "economy_refund":
setEconomyRefund(sender, args);
break;
+ case "residence_migration":
+ setResidenceMigration(sender, args);
+ break;
default:
Notification.error(sender, "未知参数");
}
@@ -250,4 +253,10 @@ public class SetConfig {
Dominion.config.setEconomyRefund(economyRefund);
}
}
+
+ private static void setResidenceMigration(CommandSender sender, String[] args) {
+ boolean residenceMigration = Boolean.parseBoolean(args[2]);
+ Dominion.config.setResidenceMigration(residenceMigration);
+ refreshPageOrNot(sender, args);
+ }
}
diff --git a/src/main/java/cn/lunadeer/dominion/controllers/DominionController.java b/src/main/java/cn/lunadeer/dominion/controllers/DominionController.java
index 79ae057..38ca2aa 100644
--- a/src/main/java/cn/lunadeer/dominion/controllers/DominionController.java
+++ b/src/main/java/cn/lunadeer/dominion/controllers/DominionController.java
@@ -38,7 +38,6 @@ public class DominionController {
* @param name 领地名称
* @param loc1 位置1
* @param loc2 位置2
- * @return 创建的领地
*/
public static void create(AbstractOperator operator, String name, Location loc1, Location loc2) {
DominionDTO parent = getPlayerCurrentDominion(operator);
@@ -57,11 +56,26 @@ public class DominionController {
* @param loc1 位置1
* @param loc2 位置2
* @param parent_dominion_name 父领地名称
- * @return 创建的领地
*/
public static void create(AbstractOperator operator, String name,
Location loc1, Location loc2,
String parent_dominion_name) {
+ create(operator, name, loc1, loc2, parent_dominion_name, false);
+ }
+
+ /**
+ * 创建子领地
+ *
+ * @param operator 拥有者
+ * @param name 领地名称
+ * @param loc1 位置1
+ * @param loc2 位置2
+ * @param parent_dominion_name 父领地名称
+ * @param skipEco 是否跳过经济检查
+ */
+ public static void create(AbstractOperator operator, String name,
+ Location loc1, Location loc2,
+ String parent_dominion_name, boolean skipEco) {
AbstractOperator.Result FAIL = new AbstractOperator.Result(AbstractOperator.Result.FAILURE, "创建领地失败");
if (name.isEmpty()) {
operator.setResponse(FAIL.addMessage("领地名称不能为空"));
@@ -143,7 +157,7 @@ public class DominionController {
}
}
// 检查经济
- if (Dominion.config.getEconomyEnable()) {
+ if (Dominion.config.getEconomyEnable() && !skipEco) {
if (!VaultConnect.instance.economyAvailable()) {
operator.setResponse(FAIL.addMessage("没有可用的经济插件系统,请联系服主。"));
return;
@@ -181,7 +195,6 @@ public class DominionController {
*
* @param operator 操作者
* @param size 扩展的大小
- * @return 扩展后的领地
*/
public static void expand(AbstractOperator operator, Integer size) {
DominionDTO dominion = getPlayerCurrentDominion(operator);
@@ -198,7 +211,6 @@ public class DominionController {
* @param operator 操作者
* @param size 扩展的大小
* @param dominion_name 领地名称
- * @return 扩展后的领地
*/
public static void expand(AbstractOperator operator, Integer size, String dominion_name) {
AbstractOperator.Result FAIL = new AbstractOperator.Result(AbstractOperator.Result.FAILURE, "扩展领地失败");
@@ -304,7 +316,6 @@ public class DominionController {
*
* @param operator 操作者
* @param size 缩小的大小
- * @return 缩小后的领地
*/
public static void contract(AbstractOperator operator, Integer size) {
DominionDTO dominion = getPlayerCurrentDominion(operator);
@@ -321,7 +332,6 @@ public class DominionController {
* @param operator 操作者
* @param size 缩小的大小
* @param dominion_name 领地名称
- * @return 缩小后的领地
*/
public static void contract(AbstractOperator operator, Integer size, String dominion_name) {
AbstractOperator.Result FAIL = new AbstractOperator.Result(AbstractOperator.Result.FAILURE, "缩小领地失败");
diff --git a/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java b/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java
index a47c309..156bc88 100644
--- a/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java
+++ b/src/main/java/cn/lunadeer/dominion/dtos/PlayerDTO.java
@@ -4,8 +4,11 @@ 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;
+import javax.annotation.Nullable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
@@ -24,6 +27,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/managers/ConfigManager.java b/src/main/java/cn/lunadeer/dominion/managers/ConfigManager.java
index 42e3c15..a7a87bc 100644
--- a/src/main/java/cn/lunadeer/dominion/managers/ConfigManager.java
+++ b/src/main/java/cn/lunadeer/dominion/managers/ConfigManager.java
@@ -83,6 +83,7 @@ public class ConfigManager {
_economy_only_xz = _file.getBoolean("Economy.OnlyXZ", false);
_economy_refund = (float) _file.getDouble("Economy.Refund", 0.85);
_fly_permission_nodes = _file.getStringList("FlyPermissionNodes");
+ _residence_migration = _file.getBoolean("ResidenceMigration", false);
saveAll(); // 回写文件 防止文件中的数据不完整
Flag.loadFromJson();
}
@@ -111,6 +112,7 @@ public class ConfigManager {
_file.set("Economy.OnlyXZ", _economy_only_xz);
_file.set("Economy.Refund", _economy_refund);
_file.set("FlyPermissionNodes", _fly_permission_nodes);
+ _file.set("ResidenceMigration", _residence_migration);
_plugin.saveConfig();
}
@@ -388,6 +390,16 @@ public class ConfigManager {
_plugin.saveConfig();
}
+ public Boolean getResidenceMigration() {
+ return _residence_migration;
+ }
+
+ public void setResidenceMigration(Boolean residence_migration) {
+ _residence_migration = residence_migration;
+ _file.set("ResidenceMigration", residence_migration);
+ _plugin.saveConfig();
+ }
+
private final Dominion _plugin;
private FileConfiguration _file;
private Boolean _debug;
@@ -426,4 +438,5 @@ public class ConfigManager {
private Boolean _economy_only_xz;
private Float _economy_refund;
private List _fly_permission_nodes;
+ private Boolean _residence_migration;
}
diff --git a/src/main/java/cn/lunadeer/dominion/tuis/DominionConfig.java b/src/main/java/cn/lunadeer/dominion/tuis/DominionConfig.java
index c47547f..cb30b47 100644
--- a/src/main/java/cn/lunadeer/dominion/tuis/DominionConfig.java
+++ b/src/main/java/cn/lunadeer/dominion/tuis/DominionConfig.java
@@ -151,6 +151,15 @@ public class DominionConfig {
.append(NumChanger.create(Dominion.config.getEconomyRefund(), "/dominion set_config economy_refund", 0.01).setPageNumber(page).build());
view.add(refund);
}
+ if (Dominion.config.getResidenceMigration()) {
+ view.add(Line.create()
+ .append("是否允许从Residence迁移数据")
+ .append(Button.createGreen("☑").setExecuteCommand("/dominion set_config residence_migration false " + page).build()));
+ } else {
+ view.add(Line.create()
+ .append("是否允许从Residence迁移数据")
+ .append(Button.createRed("☐").setExecuteCommand("/dominion set_config residence_migration true " + page).build()));
+ }
view.showOn(player, page);
}
}
diff --git a/src/main/java/cn/lunadeer/dominion/tuis/Menu.java b/src/main/java/cn/lunadeer/dominion/tuis/Menu.java
index 014a4a6..1543042 100644
--- a/src/main/java/cn/lunadeer/dominion/tuis/Menu.java
+++ b/src/main/java/cn/lunadeer/dominion/tuis/Menu.java
@@ -1,5 +1,6 @@
package cn.lunadeer.dominion.tuis;
+import cn.lunadeer.dominion.Dominion;
import cn.lunadeer.minecraftpluginutils.stui.ListView;
import cn.lunadeer.minecraftpluginutils.stui.ViewStyles;
import cn.lunadeer.minecraftpluginutils.stui.components.Button;
@@ -38,6 +39,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("查看所有领地");
@@ -58,6 +62,9 @@ public class Menu {
.add(template)
.add(help)
.add(link);
+ if (Dominion.config.getResidenceMigration()) {
+ view.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..9830bf7
--- /dev/null
+++ b/src/main/java/cn/lunadeer/dominion/tuis/MigrateList.java
@@ -0,0 +1,81 @@
+package cn.lunadeer.dominion.tuis;
+
+import cn.lunadeer.dominion.Cache;
+import cn.lunadeer.dominion.Dominion;
+import cn.lunadeer.dominion.utils.ResMigration;
+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.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;
+
+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;
+
+ if (!Dominion.config.getResidenceMigration()) {
+ Notification.error(sender, "Residence 迁移功能没有开启");
+ 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, page));
+ }
+
+ view.showOn(player, page);
+ }
+
+ 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 + " " + page).build();
+ Line line = Line.create();
+ if (depth == 0) {
+ line.append(migrate);
+ } else {
+ 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, 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
new file mode 100644
index 0000000..96adcc4
--- /dev/null
+++ b/src/main/java/cn/lunadeer/dominion/utils/ResMigration.java
@@ -0,0 +1,155 @@
+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.plugin.java.JavaPlugin;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.File;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.*;
+
+public class ResMigration {
+ 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, skipping migration");
+ 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());
+ }
+ }
+ XLogger.info("Extract %d residences", dominions.size());
+ return dominions;
+ }
+
+ private static ResidenceNode parseDominion(String name, World world, Residence res, SaveFile save) {
+ 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;
+ }
+ String[] loc = res.Areas.values().toArray()[0].toString().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]));
+ 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()) {
+ ResidenceNode sub = parseDominion(entry.getKey(), world, entry.getValue(), save);
+ if (sub != null) {
+ dominionNode.children.add(sub);
+ }
+ }
+ }
+ 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);
+ InputStream inputStream = Files.newInputStream(saveFile.toPath());
+
+ 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()) {
+ 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..0ac0004
--- /dev/null
+++ b/src/main/java/cn/lunadeer/dominion/utils/Residence/Residence.java
@@ -0,0 +1,53 @@
+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 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 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
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index fd791f3..a30669e 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -49,6 +49,9 @@ FlyPermissionNodes:
- essentials.fly
- cmi.command.fly
+# 是否允许玩家从 Residence 迁移领地数据
+ResidenceMigration: false
+
BlueMap: true
CheckUpdate: true