初步实现了从residence迁移数据的功能

This commit is contained in:
zhangyuheng 2024-06-25 17:38:28 +08:00
parent d28d20757b
commit 98093f2532
10 changed files with 144 additions and 101 deletions

View File

@ -6,7 +6,7 @@
<groupId>cn.lunadeer</groupId> <groupId>cn.lunadeer</groupId>
<artifactId>Dominion</artifactId> <artifactId>Dominion</artifactId>
<version>1.32.0-beta</version> <version>1.32.0-res-migrate-beta</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Dominion</name> <name>Dominion</name>

View File

@ -28,13 +28,6 @@ public class Cache {
player_current_dominion_id = new HashMap<>(); player_current_dominion_id = new HashMap<>();
loadDominions(); loadDominions();
loadPlayerPrivileges(); loadPlayerPrivileges();
List<ResMigration.ResidenceNode> 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<ResMigration.ResidenceNode> getResidenceData(UUID player_uuid) { public List<ResMigration.ResidenceNode> getResidenceData(UUID player_uuid) {
if (residence_data == null) {
residence_data = new HashMap<>();
List<ResMigration.ResidenceNode> 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); return residence_data.get(player_uuid);
} }
@ -331,5 +339,5 @@ public class Cache {
public final Map<UUID, LocalDateTime> NextTimeAllowTeleport = new java.util.HashMap<>(); public final Map<UUID, LocalDateTime> NextTimeAllowTeleport = new java.util.HashMap<>();
private final Map<UUID, List<ResMigration.ResidenceNode>> residence_data = new HashMap<>(); private Map<UUID, List<ResMigration.ResidenceNode>> residence_data = null;
} }

View File

@ -178,7 +178,7 @@ public class Commands implements TabExecutor {
case "migrate_list": case "migrate_list":
MigrateList.show(sender, args); MigrateList.show(sender, args);
break; break;
case "migration": case "migrate":
Migration.migrate(sender, args); Migration.migrate(sender, args);
break; break;
// ---=== CUI ===--- // ---=== CUI ===---

View File

@ -4,6 +4,7 @@ import cn.lunadeer.dominion.Cache;
import cn.lunadeer.dominion.controllers.BukkitPlayerOperator; import cn.lunadeer.dominion.controllers.BukkitPlayerOperator;
import cn.lunadeer.dominion.controllers.DominionController; import cn.lunadeer.dominion.controllers.DominionController;
import cn.lunadeer.dominion.dtos.DominionDTO; import cn.lunadeer.dominion.dtos.DominionDTO;
import cn.lunadeer.dominion.tuis.MigrateList;
import cn.lunadeer.dominion.utils.ResMigration; import cn.lunadeer.dominion.utils.ResMigration;
import cn.lunadeer.minecraftpluginutils.Notification; import cn.lunadeer.minecraftpluginutils.Notification;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -17,28 +18,43 @@ import static cn.lunadeer.dominion.commands.Apis.playerOnly;
public class Migration { public class Migration {
public static void migrate(CommandSender sender, String[] args) { public static void migrate(CommandSender sender, String[] args) {
Player player = playerOnly(sender); try {
if (player == null) return; Player player = playerOnly(sender);
if (args.length != 2) { if (player == null) return;
Notification.error(sender, "用法: /dominion migrate <res领地名称>"); if (args.length < 2) {
return; Notification.error(sender, "用法: /dominion migrate <res领地名称>");
return;
}
String resName = args[1];
List<ResMigration.ResidenceNode> 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<ResMigration.ResidenceNode> 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) { private static void create(Player player, ResMigration.ResidenceNode node, String parentName) {
BukkitPlayerOperator operator = BukkitPlayerOperator.create(player); BukkitPlayerOperator operator = new BukkitPlayerOperator(player);
operator.getResponse().thenAccept(result -> { operator.getResponse().thenAccept(result -> {
if (Objects.equals(result.getStatus(), BukkitPlayerOperator.Result.SUCCESS)) { if (Objects.equals(result.getStatus(), BukkitPlayerOperator.Result.SUCCESS)) {
DominionDTO dominion = DominionDTO.select(node.name); DominionDTO dominion = DominionDTO.select(node.name);
@ -51,9 +67,10 @@ public class Migration {
for (String msg : result.getMessages()) { for (String msg : result.getMessages()) {
Notification.info(player, msg); Notification.info(player, msg);
} }
Notification.info(player, "领地 " + node.name + " 已从 Residence 迁移至 Dominion");
if (node.children != null) { if (node.children != null) {
for (ResMigration.ResidenceNode child : node.children) { for (ResMigration.ResidenceNode child : node.children) {
create(player, child); create(player, child, node.name);
} }
} }
} else if (Objects.equals(result.getStatus(), BukkitPlayerOperator.Result.WARNING)) { } 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);
} }
} }

View File

@ -411,7 +411,11 @@ public class DominionDTO {
} }
public DominionDTO setTpLocation(Location loc) { 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); return update(this);
} }

View File

@ -1,8 +1,10 @@
package cn.lunadeer.dominion.dtos; package cn.lunadeer.dominion.dtos;
import cn.lunadeer.dominion.Dominion; import cn.lunadeer.dominion.Dominion;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
@ -19,6 +21,17 @@ public class PlayerDTO {
return re; 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<PlayerDTO> all() { public static List<PlayerDTO> all() {
String sql = "SELECT * FROM player_name WHERE id > 0;"; String sql = "SELECT * FROM player_name WHERE id > 0;";
return query(sql); return query(sql);

View File

@ -5,7 +5,11 @@ import cn.lunadeer.dominion.utils.ResMigration;
import cn.lunadeer.minecraftpluginutils.stui.ListView; import cn.lunadeer.minecraftpluginutils.stui.ListView;
import cn.lunadeer.minecraftpluginutils.stui.components.Button; import cn.lunadeer.minecraftpluginutils.stui.components.Button;
import cn.lunadeer.minecraftpluginutils.stui.components.Line; import cn.lunadeer.minecraftpluginutils.stui.components.Line;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent; 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.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -38,29 +42,32 @@ public class MigrateList {
if (res_data == null) { if (res_data == null) {
view.add(Line.create().append("你没有可迁移的数据")); view.add(Line.create().append("你没有可迁移的数据"));
} else { } else {
view.addLines(BuildTreeLines(res_data, 0)); view.addLines(BuildTreeLines(res_data, 0, page));
} }
view.showOn(player, page); view.showOn(player, page);
} }
public static List<Line> BuildTreeLines(List<ResMigration.ResidenceNode> dominionTree, Integer depth) { public static List<Line> BuildTreeLines(List<ResMigration.ResidenceNode> dominionTree, Integer depth, int page) {
List<Line> lines = new ArrayList<>(); List<Line> lines = new ArrayList<>();
StringBuilder prefix = new StringBuilder(); StringBuilder prefix = new StringBuilder();
for (int i = 0; i < depth; i++) { for (int i = 0; i < depth; i++) {
prefix.append(" | "); prefix.append(" | ");
} }
for (ResMigration.ResidenceNode node : dominionTree) { 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(); Line line = Line.create();
if (depth == 0) { if (depth == 0) {
line.append(migrate); line.append(migrate);
} else { } else {
line.append(" "); line.append(Component.text("[迁移]",
Style.style(TextColor.color(190, 190, 190),
TextDecoration.STRIKETHROUGH))
.hoverEvent(Component.text("子领地无法手动迁移,会随父领地自动迁移")));
} }
line.append(prefix + node.name); line.append(prefix + node.name);
lines.add(line); lines.add(line);
lines.addAll(BuildTreeLines(node.children, depth + 1)); lines.addAll(BuildTreeLines(node.children, depth + 1, page));
} }
return lines; return lines;
} }

View File

@ -2,22 +2,21 @@ package cn.lunadeer.dominion.utils;
import cn.lunadeer.dominion.Dominion; import cn.lunadeer.dominion.Dominion;
import cn.lunadeer.dominion.dtos.PlayerDTO; 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.Residence;
import cn.lunadeer.dominion.utils.Residence.SaveFile; import cn.lunadeer.dominion.utils.Residence.SaveFile;
import cn.lunadeer.minecraftpluginutils.XLogger; import cn.lunadeer.minecraftpluginutils.XLogger;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class ResMigration { public class ResMigration {
@ -70,7 +69,7 @@ Residences:
resSave = new File(resSave, "Save"); resSave = new File(resSave, "Save");
resSave = new File(resSave, "Worlds"); resSave = new File(resSave, "Worlds");
if (!resSave.exists()) { if (!resSave.exists()) {
XLogger.info("Residence Save not found"); XLogger.info("Residence Save not found, skipping migration");
return dominions; return dominions;
} }
// list .yml files // list .yml files
@ -86,17 +85,18 @@ Residences:
XLogger.err("Failed to process file: %s, %s", file.getName(), e.getMessage()); XLogger.err("Failed to process file: %s, %s", file.getName(), e.getMessage());
} }
} }
XLogger.info("Extract %d residences", dominions.size());
return dominions; return dominions;
} }
private static ResidenceNode parseDominion(String name, World world, Residence res, SaveFile save) { private static ResidenceNode parseDominion(String name, World world, Residence res, SaveFile save) {
Player bukkitOwner = Dominion.instance.getServer().getPlayer(res.Permissions.OwnerUUID); OfflinePlayer bukkitOwner = Dominion.instance.getServer().getOfflinePlayer(UUID.fromString(res.Permissions.OwnerUUID));
if (bukkitOwner == null) { PlayerDTO owner = PlayerDTO.get(bukkitOwner);
if (owner == null) {
XLogger.warn("Owner not found: " + res.Permissions.OwnerUUID); XLogger.warn("Owner not found: " + res.Permissions.OwnerUUID);
return null; return null;
} }
PlayerDTO owner = PlayerDTO.get(bukkitOwner); String[] loc = res.Areas.values().toArray()[0].toString().split(":");
String[] loc = res.Areas.get("main").split(":");
if (loc.length != 6) { if (loc.length != 6) {
XLogger.warn("Invalid location: " + res.Areas.get("main")); XLogger.warn("Invalid location: " + res.Areas.get("main"));
return null; return null;
@ -109,9 +109,11 @@ Residences:
dominionNode.leaveMessage = save.Messages.get(res.Messages).LeaveMessage; 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.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])); dominionNode.loc2 = new Location(world, Double.parseDouble(loc[3]), Double.parseDouble(loc[4]), Double.parseDouble(loc[5]));
String[] tpLocStr = res.TPLoc.split(":"); if (res.TPLoc != null) {
if (tpLocStr.length == 3) { String[] tpLocStr = res.TPLoc.split(":");
dominionNode.tpLoc = new Location(world, Double.parseDouble(tpLocStr[0]), Double.parseDouble(tpLocStr[1]), Double.parseDouble(tpLocStr[2])); 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) { if (res.Subzones != null) {
for (Map.Entry<String, Residence> entry : res.Subzones.entrySet()) { for (Map.Entry<String, Residence> entry : res.Subzones.entrySet()) {
@ -124,12 +126,53 @@ Residences:
return dominionNode; return dominionNode;
} }
private static Map<String, Residence> parseResYml(Map<String, Object> zones) {
Map<String, Residence> res = new HashMap<>();
for (Map.Entry<String, Object> entry : zones.entrySet()) {
Map<String, Object> zone = (Map<String, Object>) 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<String, Object>) zone.get("Permissions")).get("OwnerUUID").toString();
permission.OwnerLastKnownName = ((Map<String, Object>) zone.get("Permissions")).get("OwnerLastKnownName").toString();
residence.setPermissions(permission);
residence.setAreas((Map<String, String>) zone.get("Areas"));
if (zone.containsKey("Subzones")) {
residence.setSubzones(parseResYml((Map<String, Object>) zone.get("Subzones")));
}
res.put(entry.getKey(), residence);
}
return res;
}
private static List<ResidenceNode> processWorld(File saveFile) throws Exception { private static List<ResidenceNode> processWorld(File saveFile) throws Exception {
XLogger.debug("=====================================");
XLogger.debug("Processing file: %s", saveFile.getName());
String worldName = saveFile.getName().replace("res_", "").replace(".yml", ""); String worldName = saveFile.getName().replace("res_", "").replace(".yml", "");
World world = Dominion.instance.getServer().getWorld(worldName); World world = Dominion.instance.getServer().getWorld(worldName);
Yaml yaml = new Yaml();
InputStream inputStream = Files.newInputStream(saveFile.toPath()); InputStream inputStream = Files.newInputStream(saveFile.toPath());
SaveFile save = yaml.loadAs(inputStream, SaveFile.class);
Map<String, Object> yaml = new Yaml().load(inputStream);
SaveFile save = new SaveFile();
Map<Integer, Object> Messages = (Map<Integer, Object>) yaml.get("Messages");
Map<Integer, Message> messages = new HashMap<>();
for (Map.Entry<Integer, Object> entry : Messages.entrySet()) {
Map<String, String> message = (Map<String, String>) 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<String, Object> Residences = (Map<String, Object>) yaml.get("Residences");
save.Residences = parseResYml(Residences);
inputStream.close(); inputStream.close();
List<ResidenceNode> dominions = new ArrayList<>(); List<ResidenceNode> dominions = new ArrayList<>();
for (Map.Entry<String, Residence> entry : save.Residences.entrySet()) { for (Map.Entry<String, Residence> entry : save.Residences.entrySet()) {

View File

@ -7,7 +7,6 @@ public class Residence {
public Map<String, Residence> Subzones; public Map<String, Residence> Subzones;
public int Messages; public int Messages;
public Permission Permissions; public Permission Permissions;
public long CreatedOn;
public Map<String, String> Areas; public Map<String, String> Areas;
// getters and setters // getters and setters
@ -44,14 +43,6 @@ public class Residence {
Permissions = permissions; Permissions = permissions;
} }
public long getCreatedOn() {
return CreatedOn;
}
public void setCreatedOn(long createdOn) {
CreatedOn = createdOn;
}
public Map<String, String> getAreas() { public Map<String, String> getAreas() {
return Areas; return Areas;
} }

View File

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