初步实现了迁移

This commit is contained in:
zhangyuheng 2024-06-12 15:08:22 +08:00
parent 8613feda90
commit d28d20757b
12 changed files with 456 additions and 8 deletions

View File

@ -6,7 +6,7 @@
<groupId>cn.lunadeer</groupId>
<artifactId>Dominion</artifactId>
<version>1.31.1-beta</version>
<version>1.32.0-beta</version>
<packaging>jar</packaging>
<name>Dominion</name>
@ -90,5 +90,10 @@
<version>v2.6.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
</project>

View File

@ -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<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);
}
}
/**
@ -301,6 +309,10 @@ public class Cache {
return count;
}
public List<ResMigration.ResidenceNode> getResidenceData(UUID player_uuid) {
return residence_data.get(player_uuid);
}
public List<DominionDTO> 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<UUID, LocalDateTime> NextTimeAllowTeleport = new java.util.HashMap<>();
private final Map<UUID, List<ResMigration.ResidenceNode>> residence_data = new HashMap<>();
}

View File

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

View File

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

View File

@ -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<DominionDTO> 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<Flag, Boolean> flags = new HashMap<>();
private String tp_location;
private String tp_location = "default";
// getters and setters
public Integer getId() {

View File

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

View File

@ -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<ResMigration.ResidenceNode> 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<Line> BuildTreeLines(List<ResMigration.ResidenceNode> dominionTree, Integer depth) {
List<Line> 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;
}
}

View File

@ -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<ResidenceNode> children = new ArrayList<>();
}
public static List<ResidenceNode> extractFromResidence(JavaPlugin plugin) {
List<ResidenceNode> 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<String, Residence> 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<ResidenceNode> 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<ResidenceNode> dominions = new ArrayList<>();
for (Map.Entry<String, Residence> entry : save.Residences.entrySet()) {
String name = entry.getKey();
Residence residence = entry.getValue();
ResidenceNode dominion = parseDominion(name, world, residence, save);
dominions.add(dominion);
}
return dominions;
}
}

View File

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

View File

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

View File

@ -0,0 +1,62 @@
package cn.lunadeer.dominion.utils.Residence;
import java.util.Map;
public class Residence {
public String TPLoc;
public Map<String, Residence> Subzones;
public int Messages;
public Permission Permissions;
public long CreatedOn;
public Map<String, String> Areas;
// getters and setters
public String getTPLoc() {
return TPLoc;
}
public void setTPLoc(String TPLoc) {
this.TPLoc = TPLoc;
}
public Map<String, Residence> getSubzones() {
return Subzones;
}
public void setSubzones(Map<String, Residence> 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<String, String> getAreas() {
return Areas;
}
public void setAreas(Map<String, String> areas) {
Areas = areas;
}
}

View File

@ -0,0 +1,25 @@
package cn.lunadeer.dominion.utils.Residence;
import java.util.Map;
public class SaveFile {
public Map<String, Residence> Residences;
public Map<Integer, Message> Messages;
// getters and setters
public Map<String, Residence> getResidences() {
return Residences;
}
public void setResidences(Map<String, Residence> residences) {
Residences = residences;
}
public Map<Integer, Message> getMessages() {
return Messages;
}
public void setMessages(Map<Integer, Message> messages) {
Messages = messages;
}
}