diff --git a/pom.xml b/pom.xml index 51a623d..a77388a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ cn.lunadeer EssentialsD - 2.0.3 + 2.1.0 jar EssentialsD diff --git a/src/main/java/cn/lunadeer/essentialsd/commands/warp/DelWarp.java b/src/main/java/cn/lunadeer/essentialsd/commands/warp/DelWarp.java index 6a792ac..ba39c04 100644 --- a/src/main/java/cn/lunadeer/essentialsd/commands/warp/DelWarp.java +++ b/src/main/java/cn/lunadeer/essentialsd/commands/warp/DelWarp.java @@ -1,14 +1,35 @@ package cn.lunadeer.essentialsd.commands.warp; +import cn.lunadeer.essentialsd.dtos.WarpPoint; +import cn.lunadeer.minecraftpluginutils.Notification; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -public class DelWarp implements CommandExecutor { +import java.util.List; + +public class DelWarp implements TabExecutor { + + /** + * /delwarp + */ @Override public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) { - // todo - return false; + WarpPoint point = WarpPoint.selectByName(strings[0]); + if (point == null) { + Notification.error(commandSender, "传送点 %s 不存在", strings[0]); + return true; + } + WarpPoint.delete(point); + Notification.info(commandSender, "传送点 %s 已删除", strings[0]); + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + return WarpPoint.selectAllNames(); } } diff --git a/src/main/java/cn/lunadeer/essentialsd/commands/warp/SetWarp.java b/src/main/java/cn/lunadeer/essentialsd/commands/warp/SetWarp.java index 4aca849..b17aa9b 100644 --- a/src/main/java/cn/lunadeer/essentialsd/commands/warp/SetWarp.java +++ b/src/main/java/cn/lunadeer/essentialsd/commands/warp/SetWarp.java @@ -1,14 +1,86 @@ package cn.lunadeer.essentialsd.commands.warp; +import cn.lunadeer.essentialsd.EssentialsD; +import cn.lunadeer.essentialsd.dtos.WarpPoint; +import cn.lunadeer.minecraftpluginutils.Notification; +import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -public class SetWarp implements CommandExecutor { +import java.util.ArrayList; +import java.util.List; + +public class SetWarp implements TabExecutor { + /** + * /setwarp + * /setwarp + */ @Override public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) { - // todo - return false; + if (strings.length != 1 && strings.length != 5) { + Notification.error(commandSender, "用法: /setwarp 或 /setwarp "); + return true; + } + String name = strings[0]; + Location location; + if (strings.length == 1) { + if (commandSender instanceof Player) { + location = ((Player) commandSender).getLocation(); + } else { + Notification.error(commandSender, "请指定坐标 /setwarp "); + return true; + } + } else { + try { + double x = Double.parseDouble(strings[1]); + double y = Double.parseDouble(strings[2]); + double z = Double.parseDouble(strings[3]); + World world = EssentialsD.instance.getServer().getWorld(strings[0]); + if (world == null) { + Notification.error(commandSender, "世界 %s 不存在", strings[0]); + return true; + } + location = new Location(world, x, y, z); + } catch (NumberFormatException e) { + Notification.error(commandSender, "坐标必须是数字"); + return true; + } + } + WarpPoint existing = WarpPoint.selectByName(name); + if (existing != null) { + Notification.error(commandSender, "传送点 %s 已存在", name); + return true; + } + WarpPoint point = new WarpPoint(name, location); + WarpPoint.insert(point); + Notification.info(commandSender, "传送点 %s 已设置", name); + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + List res = new ArrayList<>(); + if (args.length == 1) { + res.add("传送点名称"); + } + if (args.length == 2) { + res.add("世界名称"); + } + if (args.length == 3) { + res.add("x"); + } + if (args.length == 4) { + res.add("y"); + } + if (args.length == 5) { + res.add("z"); + } + return res; } } diff --git a/src/main/java/cn/lunadeer/essentialsd/commands/warp/Warp.java b/src/main/java/cn/lunadeer/essentialsd/commands/warp/Warp.java index 1dd8fe1..4fc3a5a 100644 --- a/src/main/java/cn/lunadeer/essentialsd/commands/warp/Warp.java +++ b/src/main/java/cn/lunadeer/essentialsd/commands/warp/Warp.java @@ -1,14 +1,50 @@ package cn.lunadeer.essentialsd.commands.warp; +import cn.lunadeer.essentialsd.EssentialsD; +import cn.lunadeer.essentialsd.dtos.WarpPoint; +import cn.lunadeer.essentialsd.managers.TeleportManager; +import cn.lunadeer.minecraftpluginutils.Notification; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -public class Warp implements CommandExecutor { +import java.util.List; + +public class Warp implements TabExecutor { + + /** + * /warp + */ @Override public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) { - // todo - return false; + if (!(commandSender instanceof Player)) { + Notification.warn(commandSender, "只有玩家可以使用此命令"); + return true; + } + Player player = (Player) commandSender; + WarpPoint point = WarpPoint.selectByName(strings[0]); + if (point == null) { + Notification.error(commandSender, "传送点 %s 不存在", strings[0]); + return true; + } + try { + EssentialsD.tpManager.doTeleportDelayed(player, point.getLocation(), EssentialsD.config.getTpDelay(), () -> { + Notification.info(player, "正在传送到 %s", strings[0]); + }, () -> { + Notification.info(player, "已传送到 %s", strings[0]); + }); + } catch (RuntimeException e) { + Notification.error(player, e.getMessage()); + } + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + return WarpPoint.selectAllNames(); } } diff --git a/src/main/java/cn/lunadeer/essentialsd/commands/warp/Warps.java b/src/main/java/cn/lunadeer/essentialsd/commands/warp/Warps.java index 969b6bd..2739f45 100644 --- a/src/main/java/cn/lunadeer/essentialsd/commands/warp/Warps.java +++ b/src/main/java/cn/lunadeer/essentialsd/commands/warp/Warps.java @@ -1,5 +1,6 @@ package cn.lunadeer.essentialsd.commands.warp; +import cn.lunadeer.essentialsd.tuis.WarpList; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -8,7 +9,7 @@ import org.jetbrains.annotations.NotNull; public class Warps implements CommandExecutor { @Override public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) { - // todo - return false; + WarpList.show(commandSender, strings); + return true; } } diff --git a/src/main/java/cn/lunadeer/essentialsd/dtos/WarpPoint.java b/src/main/java/cn/lunadeer/essentialsd/dtos/WarpPoint.java new file mode 100644 index 0000000..8336484 --- /dev/null +++ b/src/main/java/cn/lunadeer/essentialsd/dtos/WarpPoint.java @@ -0,0 +1,100 @@ +package cn.lunadeer.essentialsd.dtos; + +import cn.lunadeer.essentialsd.EssentialsD; +import cn.lunadeer.essentialsd.utils.LocUtil; +import org.bukkit.Location; + +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; + +public class WarpPoint { + private Integer id; + private final String name; + private final Location location; + + public WarpPoint(Integer id, String name, Location location) { + this.id = id; + this.name = name; + this.location = location; + } + + public WarpPoint(String name, Location location) { + this.name = name; + this.location = location; + } + + public Integer getId() { + return id; + } + + public String getName() { + return name; + } + + public Location getLocation() { + return location; + } + + public static void insert(WarpPoint point) { + String sql = "INSERT INTO warp_point (warp_name, location) VALUES (?, ?);"; + try (ResultSet rs = EssentialsD.database.query(sql, point.getName(), LocUtil.toString(point.getLocation()))) { + if (rs == null) return; + } catch (Exception e) { + EssentialsD.database.handleDatabaseError("插入传送点失败", e, sql); + } + } + + public static void delete(WarpPoint point) { + String sql = "DELETE FROM warp_point WHERE warp_name = ?;"; + try (ResultSet rs = EssentialsD.database.query(sql, point.getName())) { + if (rs == null) return; + } catch (Exception e) { + EssentialsD.database.handleDatabaseError("删除传送点失败", e, sql); + } + } + + public static WarpPoint selectByName(String name) { + String sql = "SELECT * FROM warp_point WHERE warp_name = ?;"; + try (ResultSet rs = EssentialsD.database.query(sql, name)) { + if (rs == null) return null; + if (rs.next()) { + return new WarpPoint(rs.getInt("id"), rs.getString("warp_name"), LocUtil.fromString(rs.getString("location"))); + } + } catch (Exception e) { + EssentialsD.database.handleDatabaseError("查询传送点失败", e, sql); + return null; + } + return null; + } + + public static List selectAllNames() { + List names = new ArrayList<>(); + String sql = "SELECT DISTINCT warp_name FROM warp_point;"; + try (ResultSet rs = EssentialsD.database.query(sql)) { + if (rs == null) return names; + while (rs.next()) { + names.add(rs.getString("warp_name")); + } + } catch (Exception e) { + EssentialsD.database.handleDatabaseError("查询传送点名字失败", e, sql); + return names; + } + return names; + } + + public static List selectAll() { + List points = new ArrayList<>(); + String sql = "SELECT * FROM warp_point;"; + try (ResultSet rs = EssentialsD.database.query(sql)) { + if (rs == null) return points; + while (rs.next()) { + points.add(new WarpPoint(rs.getInt("id"), rs.getString("warp_name"), LocUtil.fromString(rs.getString("location")))); + } + } catch (Exception e) { + EssentialsD.database.handleDatabaseError("查询传送点失败", e, sql); + return points; + } + return points; + } +} diff --git a/src/main/java/cn/lunadeer/essentialsd/managers/DatabaseTables.java b/src/main/java/cn/lunadeer/essentialsd/managers/DatabaseTables.java index 5b4f290..4454092 100644 --- a/src/main/java/cn/lunadeer/essentialsd/managers/DatabaseTables.java +++ b/src/main/java/cn/lunadeer/essentialsd/managers/DatabaseTables.java @@ -84,5 +84,13 @@ public class DatabaseTables { " FOREIGN KEY (uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" + ");"; EssentialsD.database.query(sql); + + // warp info + sql = "CREATE TABLE IF NOT EXISTS warp_point (" + + " id SERIAL PRIMARY KEY," + + " warp_name TEXT NOT NULL," + + " location TEXT NOT NULL" + + ");"; + EssentialsD.database.query(sql); } } diff --git a/src/main/java/cn/lunadeer/essentialsd/tuis/HomeList.java b/src/main/java/cn/lunadeer/essentialsd/tuis/HomeList.java index 2e93d74..17840fc 100644 --- a/src/main/java/cn/lunadeer/essentialsd/tuis/HomeList.java +++ b/src/main/java/cn/lunadeer/essentialsd/tuis/HomeList.java @@ -19,7 +19,7 @@ public class HomeList { } Player player = (Player) sender; List homes = HomeInfo.getHomesOf(((Player) sender).getUniqueId()); - if (homes.size() == 0) { + if (homes.isEmpty()) { Notification.warn(player, "你还没有设置家"); return; } diff --git a/src/main/java/cn/lunadeer/essentialsd/tuis/WarpList.java b/src/main/java/cn/lunadeer/essentialsd/tuis/WarpList.java new file mode 100644 index 0000000..7539a8b --- /dev/null +++ b/src/main/java/cn/lunadeer/essentialsd/tuis/WarpList.java @@ -0,0 +1,45 @@ +package cn.lunadeer.essentialsd.tuis; + +import cn.lunadeer.essentialsd.dtos.HomeInfo; +import cn.lunadeer.essentialsd.dtos.WarpPoint; +import cn.lunadeer.essentialsd.utils.LocUtil; +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 org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.List; + +public class WarpList { + public static void show(CommandSender sender, String[] args) { + if (!(sender instanceof Player)) { + Notification.warn(sender, "只有玩家可以使用此命令"); + return; + } + Player player = (Player) sender; + List points = WarpPoint.selectAll(); + if (points.isEmpty()) { + Notification.warn(player, "没有传送点"); + return; + } + int page = 1; + if (args.length == 1) { + try { + page = Integer.parseInt(args[0]); + } catch (Exception ignored) { + } + } + ListView view = ListView.create(5, "/warps"); + view.title("Warp 列表"); + for (WarpPoint point : points) { + Line line = Line.create() + .append(Component.text(point.getName()).hoverEvent(Component.text(LocUtil.toString(point.getLocation())))) + .append(Button.create("传送").setExecuteCommand("/warp " + point.getName()).build()); + view.add(line); + } + view.showOn(player, page); + } +} diff --git a/src/main/java/cn/lunadeer/essentialsd/utils/LocUtil.java b/src/main/java/cn/lunadeer/essentialsd/utils/LocUtil.java new file mode 100644 index 0000000..d100ae5 --- /dev/null +++ b/src/main/java/cn/lunadeer/essentialsd/utils/LocUtil.java @@ -0,0 +1,23 @@ +package cn.lunadeer.essentialsd.utils; + +import org.bukkit.Location; + +public class LocUtil { + + public static String toString(Location loc) { + return String.format("[%s, %.2f, %.2f, %.2f, %.2f, %.2f]", loc.getWorld().getName(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); + } + + public static Location fromString(String str) { + String[] parts = str.substring(1, str.length() - 1).split(", "); + return new Location( + org.bukkit.Bukkit.getWorld(parts[0]), + Double.parseDouble(parts[1]), + Double.parseDouble(parts[2]), + Double.parseDouble(parts[3]), + Float.parseFloat(parts[4]), + Float.parseFloat(parts[5]) + ); + } + +}