From 60b567ffa9afc2e70652609c0ff63e6573d48eac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=BB=E9=AD=82=E5=9C=A3=E4=BD=BF?= Date: Wed, 25 Dec 2024 04:16:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=81=E8=AE=B8=E7=8E=A9=E5=AE=B6=E9=97=B4?= =?UTF-8?q?=E4=BA=92=E7=9B=B8=E4=BC=A0=E9=80=81=EF=BC=8C=E5=85=81=E8=AE=B8?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=8E=A9=E5=AE=B6=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Commands/ZbCommand.java | 202 +++++++++++++++++- .../java/ling/coordinateRecorder/Config.java | 13 ++ .../CoordinateRecorder.java | 13 +- .../Listener/InterruptTransmit.java | 30 +++ .../coordinateRecorder/Service/Service.java | 5 + .../Service/ServiceManager.java | 23 ++ .../Service/TransmitService.java | 198 +++++++++++++++++ .../coordinateRecorder/data/PlayerData.java | 103 +++++---- .../coordinateRecorder/data/TransmitData.java | 92 ++++++++ 9 files changed, 631 insertions(+), 48 deletions(-) create mode 100644 src/main/java/ling/coordinateRecorder/Listener/InterruptTransmit.java create mode 100644 src/main/java/ling/coordinateRecorder/Service/Service.java create mode 100644 src/main/java/ling/coordinateRecorder/Service/ServiceManager.java create mode 100644 src/main/java/ling/coordinateRecorder/Service/TransmitService.java create mode 100644 src/main/java/ling/coordinateRecorder/data/TransmitData.java diff --git a/src/main/java/ling/coordinateRecorder/Commands/ZbCommand.java b/src/main/java/ling/coordinateRecorder/Commands/ZbCommand.java index c54f879..beff402 100644 --- a/src/main/java/ling/coordinateRecorder/Commands/ZbCommand.java +++ b/src/main/java/ling/coordinateRecorder/Commands/ZbCommand.java @@ -3,10 +3,10 @@ package ling.coordinateRecorder.Commands; import ling.coordinateRecorder.CoordinateRecorder; import ling.coordinateRecorder.Listener.PlayerMap; import ling.coordinateRecorder.data.PlayerData; +import ling.coordinateRecorder.data.TransmitData; import ling.database.tables.records.LocationnotepadPO; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Material; +import ling.database.tables.records.PlayersettingsPO; +import org.bukkit.*; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -17,6 +17,8 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; import org.jetbrains.annotations.NotNull; +import org.jooq.Record; +import org.jooq.UpdateSetMoreStep; import org.jooq.impl.DSL; import java.sql.SQLException; @@ -25,12 +27,13 @@ import java.util.Arrays; import java.util.List; import static ling.database.tables.LocationnotepadTB.LOCATIONNOTEPAD; +import static ling.database.tables.PlayersettingsTB.PLAYERSETTINGS; /// zb命令处理器 public class ZbCommand implements CommandExecutor, TabCompleter { protected final static List TAB_1 = Arrays.asList("add", "remove", "help", "reload", "list", "fixed", - "unfixed", "unlock", "sb"); + "unfixed", "unlock", "sb", "tp", "yes", "no", "setting"); public ZbCommand() { @@ -292,6 +295,152 @@ public class ZbCommand implements CommandExecutor, TabCompleter { player.sendMessage("从侧边栏取消固定 " + name); } + protected void playerTp(PlayerData data, Player toPlayer) { + PlayerData to = PlayerMap.getCurrent().getPlayerData(toPlayer); + if (to == null) { + data.getPlayer().sendMessage("目标玩家没有注册"); + return; + } + if (to.getTransmitData() != null) { + data.getPlayer().sendMessage("目标玩家正在传送引导中,请稍后再试"); + return; + } + if (to.getToMeTransmitData() != null) { + data.getPlayer().sendMessage("有人正在向目标玩家传送,请稍后再试"); + return; + } + TransmitData transmitData = new TransmitData(data, to); + CoordinateRecorder.getTransmitService().addTransmit(transmitData); + } + + protected void locationTp(PlayerData data, String name) throws SQLException { + var ctx = CoordinateRecorder.getDatabase().getDSL(); + Record result = ctx.select().from(LOCATIONNOTEPAD).where( + LOCATIONNOTEPAD.UID.eq(data.getPlayer().getUniqueId().toString()) + .and(LOCATIONNOTEPAD.ISDELETE.eq(false).and(LOCATIONNOTEPAD.NAME.eq(name)))).fetchOne(); + if (result == null) { + data.getPlayer().sendMessage(ChatColor.RED + "目标不存在"); + return; + } + LocationnotepadPO res = result.into(LocationnotepadPO.class); + World world = Bukkit.getWorld(res.getWorld()); + if (world == null) { + data.getPlayer().sendMessage(ChatColor.RED + "世界不存在"); + return; + } + Location target = new Location(world, res.getX(), res.getY(), res.getZ()); + CoordinateRecorder.getTransmitService().addTransmit(new TransmitData(data, target)); + //data.getPlayer().teleport(target); + //data.getPlayer().sendMessage("已将您送达 " + name); + } + + protected void tp(Player player, String[] strings) throws SQLException { + if (strings.length > 2) { + player.sendMessage(ChatColor.RED + "命令过长"); + return; + } + if (strings.length != 2) { + player.sendMessage(ChatColor.RED + "请指定目标"); + return; + } + PlayerData data = PlayerMap.getCurrent().getPlayerData(player); + if (data == null) { + player.sendMessage(ChatColor.RED + "玩家未注册"); + return; + } + if (data.getTransmitData() != null) { + player.sendMessage(ChatColor.RED + "你已经在引导传送了"); + return; + } + if (data.getToMeTransmitData() != null) { + player.sendMessage(ChatColor.RED + "有人正在向你传送"); + return; + } + + String targetName = strings[1]; + Player targetPlayer = Bukkit.getPlayer(targetName); + if (targetPlayer == null) { + locationTp(data, targetName); + return; + } else { + playerTp(data, targetPlayer); + } + } + + protected void yesOnNo(Player player, String[] strings) { + if (strings.length != 1) { + player.sendMessage(ChatColor.RED + "命令过长!"); + return; + } + PlayerData data = PlayerMap.getCurrent().getPlayerData(player); + if (data == null) { + player.sendMessage(ChatColor.RED + "玩家没有登录"); + return; + } + if (data.getToMeTransmitData() == null) { + player.sendMessage(ChatColor.RED + "没有找到指向你的传送请求"); + return; + } + if (strings[0].equals("yes")) { + CoordinateRecorder.getTransmitService().confirmTransmit(data.getToMeTransmitData()); + } else { + CoordinateRecorder.getTransmitService().rejectTransmit(data.getToMeTransmitData()); + } + } + + protected void settingTp(Player player, String[] strings) { + PlayerData data = PlayerMap.getCurrent().getPlayerData(player); + if (data == null) { + player.sendMessage(ChatColor.RED + "玩家没有注册"); + return; + } + if (strings.length > 4) { + player.sendMessage(ChatColor.RED + "命令过长!"); + return; + } + if (strings.length < 3) { + player.sendMessage(ChatColor.RED + "命令过短:使用true/false表示是否允许他人向你传送!"); + return; + } + boolean isTp; + if (strings[2].equals("true")) + isTp = true; + else if (strings[2].equals("false")) + isTp = false; + else { + player.sendMessage(ChatColor.RED + "语法错误,在" + strings[2] + "上"); + return; + } + String message = null; + if (strings.length == 4) { + message = strings[3]; + } + try { + var ctx = CoordinateRecorder.getDatabase().getDSL(); + UpdateSetMoreStep update = ctx.update(PLAYERSETTINGS).set(PLAYERSETTINGS.TPME, isTp); + if (message != null) + update = update.set(PLAYERSETTINGS.SETTINGSREJECTTPMESSAGE, message); + update.where(PLAYERSETTINGS.UID.eq(player.getUniqueId().toString())).execute(); + data.loadPlayerSettings(); + player.sendMessage("设置已经成功更新!"); + } catch (SQLException e) { + System.out.println("修改设置失败:" + e.getMessage()); + player.sendMessage(ChatColor.RED + "修改设置失败:服务器内部错误!"); + } + } + + protected void setting(Player player, String[] strings) { + if (strings.length < 2) { + player.sendMessage(ChatColor.RED + "命令过短。"); + return; + } + if (strings[1].equals("tp")) { + settingTp(player, strings); + } else { + player.sendMessage(ChatColor.RED + "未知的选项:" + strings[1]); + } + } + protected boolean execute(Player player, String[] strings) { if (strings.length < 1) { player.sendMessage(ChatColor.RED + "语法错误:需要 [选项]"); @@ -326,6 +475,16 @@ public class ZbCommand implements CommandExecutor, TabCompleter { case "sb": sb(player, strings); break; + case "tp": + tp(player, strings); + break; + case "yes": + case "no": + yesOnNo(player, strings); + break; + case "setting": + setting(player, strings); + break; default: player.sendMessage(ChatColor.RED + "未知的选项:" + strings[0]); break; @@ -382,6 +541,35 @@ public class ZbCommand implements CommandExecutor, TabCompleter { return list; } + protected List onTpTab(Player player, String latest, String[] strings) { + var data = PlayerMap.getCurrent().getPlayerData(player); + if (data == null) return List.of(); + List list = new ArrayList<>(); + var locations = data.getLocationList(); + for (LocationnotepadPO location : locations) { + list.add(location.getName()); + } + var playerList = Bukkit.getOnlinePlayers(); + for (Player obj : playerList) { + if (obj.getUniqueId().equals(player.getUniqueId())) continue; + list.add(obj.getName()); + } + return filter(latest, list); + } + + protected List onSettingTab(Player player, String latest, String[] strings) { + if (strings.length == 2) { + return filter(latest, new ArrayList<>(List.of("tp"))); + } + if (strings.length == 3) { + return List.of("<是否允许向你传送,true 或 false>"); + } + if (strings.length == 4) { + return List.of("<拒绝玩家的理由>"); + } + return List.of(); + } + @Override public List onTabComplete(CommandSender commandSender, Command command, String s, String[] strings) { if (!(commandSender instanceof Player player)) { @@ -409,11 +597,17 @@ public class ZbCommand implements CommandExecutor, TabCompleter { case "sb" -> { return onSbTab(player, latest, strings); } + case "tp" -> { + return onTpTab(player, latest, strings); + } } } if (strings[0].equals("add")) { return onAddTab(player, latest, strings); } + if (strings[0].equals("setting")) { + return onSettingTab(player, latest, strings); + } return List.of(); } diff --git a/src/main/java/ling/coordinateRecorder/Config.java b/src/main/java/ling/coordinateRecorder/Config.java index 40c7f95..c2699b1 100644 --- a/src/main/java/ling/coordinateRecorder/Config.java +++ b/src/main/java/ling/coordinateRecorder/Config.java @@ -1,5 +1,6 @@ package ling.coordinateRecorder; +import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; @@ -13,8 +14,20 @@ public class Config { public static final int TOMBSTONE_PUNISHMENT = 3; /// 禁止解锁墓碑阈值 public static final int UNLOCK_PROHIBITED = 24; + /// 禁止传送阈值 + public static final int TRANSMIT_PROHIBITED = 48; + /// 传送引导时间 + public static final int TRANSMIT_GUIDE_TIME = 8000; + /// 传送请求失效时间 + public static final int TRANSMIT_EXPIRATION_TIME = 45000; + /// 跨世界传送惩罚 + public static final int CROSS_WORLD_TELEPORTATION_PENALTY = 10; public static final HashMap ITEM_VALUE_MAP = new HashMap<>(); + public static String getFractionTimeMessage(long value) { + return "" + ChatColor.YELLOW + value + ChatColor.WHITE; + } + /// 计算物品堆的价值 public static int getItemStackValue(List stack) { double[] value = {0d}; diff --git a/src/main/java/ling/coordinateRecorder/CoordinateRecorder.java b/src/main/java/ling/coordinateRecorder/CoordinateRecorder.java index 12c5076..e634f9e 100644 --- a/src/main/java/ling/coordinateRecorder/CoordinateRecorder.java +++ b/src/main/java/ling/coordinateRecorder/CoordinateRecorder.java @@ -1,12 +1,14 @@ package ling.coordinateRecorder; import ling.coordinateRecorder.Commands.ZbCommand; +import ling.coordinateRecorder.Listener.InterruptTransmit; import ling.coordinateRecorder.Listener.PlayerAuthMeLoginEventListener; import ling.coordinateRecorder.Listener.PlayerEventListener; import ling.coordinateRecorder.Listener.PlayerLoginEventListener; +import ling.coordinateRecorder.Service.ServiceManager; +import ling.coordinateRecorder.Service.TransmitService; import ling.coordinateRecorder.data.Database; import org.bukkit.Bukkit; -import org.bukkit.NamespacedKey; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; @@ -17,6 +19,7 @@ public final class CoordinateRecorder extends JavaPlugin { private static CoordinateRecorder current; private static Database database; private static Plugin authMePlugin; + private static TransmitService transmitService; private static void start() throws SQLException { database.installPlugin(); @@ -24,6 +27,7 @@ public final class CoordinateRecorder extends JavaPlugin { private void loadListener() { Bukkit.getPluginManager().registerEvents(new PlayerEventListener(), this); + Bukkit.getPluginManager().registerEvents(new InterruptTransmit(), this); if (authMePlugin != null && authMePlugin.isEnabled()) { getLogger().info("找到AuthMe插件,将使用AuthMe兼容接口"); Bukkit.getPluginManager().registerEvents(new PlayerAuthMeLoginEventListener(), this); @@ -47,12 +51,19 @@ public final class CoordinateRecorder extends JavaPlugin { assert command != null; command.setExecutor(zb); command.setTabCompleter(zb); + transmitService = (TransmitService) ServiceManager.getCurrent().startService(TransmitService.class, 4L); getLogger().info("加载完毕"); } catch (SQLException e) { throw new RuntimeException("插件初始化失败", e); + } catch (ReflectiveOperationException e) { + throw new RuntimeException("启动服务失败"); } } + public static TransmitService getTransmitService() { + return transmitService; + } + @Override public void onDisable() { // Plugin shutdown logic diff --git a/src/main/java/ling/coordinateRecorder/Listener/InterruptTransmit.java b/src/main/java/ling/coordinateRecorder/Listener/InterruptTransmit.java new file mode 100644 index 0000000..0aa5dfa --- /dev/null +++ b/src/main/java/ling/coordinateRecorder/Listener/InterruptTransmit.java @@ -0,0 +1,30 @@ +package ling.coordinateRecorder.Listener; + +import ling.coordinateRecorder.data.PlayerData; +import org.bukkit.Location; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerMoveEvent; + +public class InterruptTransmit implements Listener { + + /// 当玩家移动了自己的位置时,打断传送引导 + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + Location from = event.getFrom(); + Location to = event.getTo(); + if (to == null) + return; + + if (from.getBlockX() == to.getBlockX() && from.getBlockY() == to.getBlockY() && from.getBlockZ() == to.getBlockZ()) + return; + + PlayerData data = PlayerMap.getCurrent().getPlayerData(event.getPlayer()); + if (data == null) + return; + if (data.getTransmitData() != null) + data.getTransmitData().interrupt("传送来源的位置发生了变化"); + if (data.getToMeTransmitData() != null && data.getToMeTransmitData().isConfirm()) + data.getToMeTransmitData().interrupt("传送目标的位置发生了变化"); + } +} diff --git a/src/main/java/ling/coordinateRecorder/Service/Service.java b/src/main/java/ling/coordinateRecorder/Service/Service.java new file mode 100644 index 0000000..c27be29 --- /dev/null +++ b/src/main/java/ling/coordinateRecorder/Service/Service.java @@ -0,0 +1,5 @@ +package ling.coordinateRecorder.Service; + +public interface Service { + void start(); +} diff --git a/src/main/java/ling/coordinateRecorder/Service/ServiceManager.java b/src/main/java/ling/coordinateRecorder/Service/ServiceManager.java new file mode 100644 index 0000000..53e04a1 --- /dev/null +++ b/src/main/java/ling/coordinateRecorder/Service/ServiceManager.java @@ -0,0 +1,23 @@ +package ling.coordinateRecorder.Service; + +import ling.coordinateRecorder.CoordinateRecorder; +import org.bukkit.Bukkit; + +public final class ServiceManager { + private static final ServiceManager current = new ServiceManager(); + + private ServiceManager() { + + } + + public static ServiceManager getCurrent() { + return current; + } + + /// 启动一个服务 + public Service startService(Class server,long tick) throws ReflectiveOperationException { + Service service = server.getDeclaredConstructor().newInstance(); + Bukkit.getScheduler().runTaskTimer(CoordinateRecorder.getCurrent(), service::start, 0L, tick); + return service; + } +} diff --git a/src/main/java/ling/coordinateRecorder/Service/TransmitService.java b/src/main/java/ling/coordinateRecorder/Service/TransmitService.java new file mode 100644 index 0000000..14bd778 --- /dev/null +++ b/src/main/java/ling/coordinateRecorder/Service/TransmitService.java @@ -0,0 +1,198 @@ +package ling.coordinateRecorder.Service; + +import ling.coordinateRecorder.Config; +import ling.coordinateRecorder.data.TransmitData; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +/// 传送服务 +public final class TransmitService implements Service { + private final AtomicBoolean lockFlag = new AtomicBoolean(false); + private final HashMap list = new HashMap<>(); + + public TransmitService() { + + } + + private void lock() { + while (!lockFlag.compareAndSet(false, true)) { + } + } + + private void unlock() { + lockFlag.set(false); + } + + /// 输出传送提示信息 + private void sendTransmitMessage(TransmitData data) { + Player player = data.getPlayer().getPlayer(); + Location from = player.getLocation(); + Location to = data.getTarget(); + if (to == null) + to = data.getTargetPlayer().getPlayer().getLocation(); + if (data.isConfirm()) { + player.sendMessage( + "传送引导中...(将带来" + Config.getFractionTimeMessage( + getTransmitCost(from, to)) + + "点沙雕值惩罚,当前" + Config.getFractionTimeMessage(data.getPlayer().getFraction()) + + ")"); + } else { + player.sendMessage("正在等待目标玩家响应..."); + data.getTargetPlayer().getPlayer().sendMessage("玩家 " + player.getName() + " 正在请求向你传送\n使用" + + ChatColor.YELLOW + "/zb yes" + ChatColor.WHITE + "同意该请求,使用" + ChatColor.YELLOW + "/zb no" + ChatColor.WHITE + "拒绝"); + } + } + + /// 检查沙雕值是否超出阈值 + private boolean isFractionTransmit(TransmitData data) { + return data.getPlayer().getFraction() <= Config.TRANSMIT_PROHIBITED; + } + + /// 同意一个传送请求 + public void confirmTransmit(TransmitData data) { + data.confirm(); + sendTransmitMessage(data); + } + + /// 拒绝一个传送请求 + public void rejectTransmit(TransmitData data) { + lock(); + data.getPlayer().getPlayer().sendMessage("目标玩家拒绝了你的传送请求"); + data.getTargetPlayer().getPlayer().sendMessage("已拒绝"); + list.remove(data.getPlayer().getPlayer()); + clearTransmitData(data); + unlock(); + } + + public void addTransmit(TransmitData data) { + if (!isFractionTransmit(data)) { + data.getPlayer().getPlayer().sendMessage( + "你的沙雕值过高,被禁止传送!( >" + Config.getFractionTimeMessage(data.getPlayer().getFraction()) + + " )"); + return; + } + // 如果目标玩家不允许任何人向它传送 + if (data.getTargetPlayer() != null && !data.getTargetPlayer().isTpMe()) { + data.getPlayer().getPlayer().sendMessage( + "目标玩家拒绝了你的传送请求,因为:" + data.getTargetPlayer().rejectMessage()); + data.getTargetPlayer().getPlayer().sendMessage("玩家 " + data.getPlayer().getPlayer().getName() + " " + + "试图向你传送,已根据设置自动拒绝。"); + clearTransmitData(data); + return; + } + lock(); + sendTransmitMessage(data); + data.getPlayer().setTransmitData(data); + if (data.getTargetPlayer() != null) + data.getTargetPlayer().setToMeTransmitData(data); + list.put(data.getPlayer().getPlayer(), data); + unlock(); + } + + /// 计算传送将要带来的沙雕值惩罚 + /// + /// 两千米内每五百米带来一点沙雕值惩罚 + /// 两万米内每两千米带来一点沙雕值惩罚 + /// 两万米后每两万米带来一点沙雕值惩罚 + /// 单次传送封顶带来 Config.UNLOCK_PROHIBITED 点沙雕值惩罚 + public static int getTransmitCost(Location from, Location to) { + assert from.getWorld() != null; + assert to.getWorld() != null; + //不在同一世界的传送,使用统一沙雕值惩罚 + if (!from.getWorld().toString().equals(to.getWorld().toString())) { + return Config.CROSS_WORLD_TELEPORTATION_PENALTY; + } + double distance = from.distance(to); + int value = 0; + { + //两千米 + double dis = Math.min(distance, 2000); + value += (int) ((dis + 500 + 1) / 500); + } + if (distance > 2000) { + //两万米 + double dis = Math.min(distance, 20000) - 2000; + value += (int) ((dis + 2000 + 1) / 2000); + } + if (distance > 20000) { + double dis = distance - 20000; + value += (int) ((dis + 20000 + 1) / 20000); + } + return Math.min(value, Config.UNLOCK_PROHIBITED); + } + + /// 处理一个传送请求 + private void success(TransmitData data) { + Location from = data.getPlayer().getPlayer().getLocation(); + Location to = data.getTarget(); + if (to == null) + to = data.getTargetPlayer().getPlayer().getLocation(); + int value = getTransmitCost(from, to); + try { + data.getPlayer().addFraction(value); + data.getPlayer().getPlayer().teleport(to); + data.getPlayer().getPlayer().sendMessage( + "传送完毕!您受到了" + Config.getFractionTimeMessage(value) + "点沙雕值惩罚!(当前:" + + Config.getFractionTimeMessage(data.getPlayer().getFraction()) + ")"); + } catch (SQLException e) { + data.getPlayer().getPlayer().sendMessage(ChatColor.RED + "传送失败:施加沙雕值惩罚出错!"); + } + } + + /// 使一个传送请求失效 + private void clearTransmitData(TransmitData data) { + data.getPlayer().setTransmitData(null); + if (data.getTargetPlayer() != null) + data.getTargetPlayer().setToMeTransmitData(null); + data.clear(); + } + + @Override + public void start() { + lock(); + Iterator> iterator = list.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + var data = entry.getValue(); + //移除失效请求 + if (!data.isConfirm() && data.getTime() + Config.TRANSMIT_EXPIRATION_TIME < System.currentTimeMillis()) { + data.getPlayer().getPlayer().sendMessage("对方超时未响应,传送取消。"); + data.getTargetPlayer().getPlayer().sendMessage("超时未响应,已自动拒绝对方!"); + clearTransmitData(data); + iterator.remove(); + continue; + } + //删除已经被取消的传送请求 + if (data.isInterrupt()) { + data.getPlayer().getPlayer().sendMessage("传送取消!因为" + data.getInterruptMessage()); + if (data.getTargetPlayer() != null) + data.getTargetPlayer().getPlayer().sendMessage( + "玩家 " + data.getPlayer().getPlayer() + .getName() + " " + "的传送已取消,因为" + data.getInterruptMessage()); + clearTransmitData(data); + iterator.remove(); + continue; + } + if (!data.isConfirm()) + continue; + //处理已经引导完毕的传送请求 + if (data.getTime() + Config.TRANSMIT_GUIDE_TIME < System.currentTimeMillis()) { + success(data); + iterator.remove(); + clearTransmitData(data); + continue; + } + //计算其余传送请求的引导时间 + long time = System.currentTimeMillis() - data.getTime(); + data.getBossBar().setProgress((double) time / Config.TRANSMIT_GUIDE_TIME); + } + unlock(); + } +} diff --git a/src/main/java/ling/coordinateRecorder/data/PlayerData.java b/src/main/java/ling/coordinateRecorder/data/PlayerData.java index ef90288..4fc5690 100644 --- a/src/main/java/ling/coordinateRecorder/data/PlayerData.java +++ b/src/main/java/ling/coordinateRecorder/data/PlayerData.java @@ -37,6 +37,8 @@ public class PlayerData { protected PlayerDeathData death; //上次计分时间 protected long fractionTime; + protected TransmitData transmitData = null; + protected TransmitData toMeTransmitData = null; public PlayerData(Player player) throws SQLException { @@ -60,19 +62,49 @@ public class PlayerData { return settings.getFraction(); } + + /// 是否允许其他玩家向自己传送 + public boolean isTpMe() { + return settings.getTpme(); + } + + /// 拒绝传送消息 + public String rejectMessage() { + return settings.getSettingsrejecttpmessage(); + } + public void setTombstoneBlock(Block tombstone) { this.tombstoneBlock = tombstone; } + public TransmitData getTransmitData() { + return transmitData; + } + + public void setTransmitData(TransmitData transmitData) { + this.transmitData = transmitData; + } + + public TransmitData getToMeTransmitData() { + return toMeTransmitData; + } + + public void setToMeTransmitData(TransmitData toMeTransmitData) { + this.toMeTransmitData = toMeTransmitData; + } + /// 检查两个地点是否位于同一个世界 public static boolean isSameWorld(Location l1, Location l2) { World w1 = l1.getWorld(); World w2 = l2.getWorld(); - if (w1 == null || w2 == null) - return false; + if (w1 == null || w2 == null) return false; return w1.getName().equals(w2.getName()); } + public Player getPlayer() { + return player; + } + /// 解锁墓碑 public void unlockTombstoneBlock() { if (tombstoneBlock == null) { @@ -201,12 +233,17 @@ public class PlayerData { protected Record loadPlayerSettingsRecord() throws SQLException { return CoordinateRecorder.getDatabase().getDSL().select().from(PLAYERSETTINGS).where( - PLAYERSETTINGS.UID.eq(player.getUniqueId().toString()) - ).fetchOne(); + PLAYERSETTINGS.UID.eq(player.getUniqueId().toString())).fetchOne(); } /// 关闭ui public void closeUI() { + if (this.transmitData != null) { + this.transmitData.interrupt("玩家离线"); + } + if (this.toMeTransmitData != null) { + this.toMeTransmitData.interrupt("玩家离线"); + } ui.closeUI(); } @@ -220,9 +257,8 @@ public class PlayerData { return false; } var ctx = CoordinateRecorder.getDatabase().getDSL(); - int rows = ctx.update(PLAYERSETTINGS).set( - PLAYERSETTINGS.FRACTION, - DSL.greatest(PLAYERSETTINGS.FRACTION.plus(fraction), DSL.val(0))) + int rows = ctx.update(PLAYERSETTINGS).set(PLAYERSETTINGS.FRACTION, + DSL.greatest(PLAYERSETTINGS.FRACTION.plus(fraction), DSL.val(0))) .where(PLAYERSETTINGS.UID.eq(player.getUniqueId().toString())).execute(); loadPlayerSettings(); return rows == 1; @@ -231,11 +267,9 @@ public class PlayerData { /// 删除一个地标 public boolean removeLocation(String name) throws SQLException { var ctx = CoordinateRecorder.getDatabase().getDSL(); - int rows = ctx.update(LOCATIONNOTEPAD).set(LOCATIONNOTEPAD.ISDELETE, true) - .where(LOCATIONNOTEPAD.UID.eq(player.getUniqueId().toString()) - .and(LOCATIONNOTEPAD.NAME.eq(name) - .and(LOCATIONNOTEPAD.ISDELETE.eq(false))) - ).execute(); + int rows = ctx.update(LOCATIONNOTEPAD).set(LOCATIONNOTEPAD.ISDELETE, true).where( + LOCATIONNOTEPAD.UID.eq(player.getUniqueId().toString()) + .and(LOCATIONNOTEPAD.NAME.eq(name).and(LOCATIONNOTEPAD.ISDELETE.eq(false)))).execute(); if (rows == 0) { player.sendMessage(ChatColor.RED + "操作失败:记录不存在"); return false; @@ -251,35 +285,21 @@ public class PlayerData { return false; } var ctx = CoordinateRecorder.getDatabase().getDSL(); - Record record = ctx.select().from(LOCATIONNOTEPAD).where( - LOCATIONNOTEPAD.UID.eq(player.getUniqueId().toString()) - .and(LOCATIONNOTEPAD.NAME.eq(name)) - .and(LOCATIONNOTEPAD.ISDELETE.eq(false)) - ).fetchOne(); + Record record = ctx.select().from(LOCATIONNOTEPAD).where(LOCATIONNOTEPAD.UID.eq(player.getUniqueId().toString()) + .and(LOCATIONNOTEPAD.NAME.eq(name)) + .and(LOCATIONNOTEPAD.ISDELETE.eq(false))) + .fetchOne(); if (record != null) { player.sendMessage(ChatColor.RED + "该名称的地点已经存在"); return false; } Location location = player.getLocation(); - ctx.insertInto(LOCATIONNOTEPAD).columns( - LOCATIONNOTEPAD.UID, - LOCATIONNOTEPAD.WORLD, - LOCATIONNOTEPAD.NAME, - LOCATIONNOTEPAD.X, - LOCATIONNOTEPAD.Y, - LOCATIONNOTEPAD.Z, - LOCATIONNOTEPAD.TIME, - LOCATIONNOTEPAD.ISFIXED - ).values( - player.getUniqueId().toString(), - Objects.requireNonNull(location.getWorld()).getName(), - name, - (int) location.getX(), - (int) location.getY(), - (int) location.getZ(), - BigDecimal.valueOf(System.currentTimeMillis()), - isFixed - ).execute(); + ctx.insertInto(LOCATIONNOTEPAD).columns(LOCATIONNOTEPAD.UID, LOCATIONNOTEPAD.WORLD, LOCATIONNOTEPAD.NAME, + LOCATIONNOTEPAD.X, LOCATIONNOTEPAD.Y, LOCATIONNOTEPAD.Z, + LOCATIONNOTEPAD.TIME, LOCATIONNOTEPAD.ISFIXED).values( + player.getUniqueId().toString(), Objects.requireNonNull(location.getWorld()).getName(), name, + (int) location.getX(), (int) location.getY(), (int) location.getZ(), + BigDecimal.valueOf(System.currentTimeMillis()), isFixed).execute(); locationListUpdate(); return true; } @@ -289,10 +309,8 @@ public class PlayerData { var record = loadPlayerSettingsRecord(); if (record == null) { //设置不存在,新建一行 - CoordinateRecorder.getDatabase().getDSL().insertInto(PLAYERSETTINGS) - .columns(PLAYERSETTINGS.UID) - .values(player.getUniqueId().toString()) - .execute(); + CoordinateRecorder.getDatabase().getDSL().insertInto(PLAYERSETTINGS).columns(PLAYERSETTINGS.UID).values( + player.getUniqueId().toString()).execute(); record = loadPlayerSettingsRecord(); assert record != null; } @@ -302,9 +320,8 @@ public class PlayerData { /// 重新载入玩家的固定地点数据 public void locationListUpdate() throws SQLException { Result result = CoordinateRecorder.getDatabase().getDSL().select().from(LOCATIONNOTEPAD).where( - LOCATIONNOTEPAD.UID.eq(player.getUniqueId().toString()).and(LOCATIONNOTEPAD.ISFIXED.eq(true)) - .and(LOCATIONNOTEPAD.ISDELETE.eq(false))).orderBy(LOCATIONNOTEPAD.ID.desc()) - .limit(10).fetch(); + LOCATIONNOTEPAD.UID.eq(player.getUniqueId().toString()).and(LOCATIONNOTEPAD.ISFIXED.eq(true)) + .and(LOCATIONNOTEPAD.ISDELETE.eq(false))).orderBy(LOCATIONNOTEPAD.ID.desc()).limit(10).fetch(); locationList = result.into(LocationnotepadPO.class); ui.flashLocations(); } diff --git a/src/main/java/ling/coordinateRecorder/data/TransmitData.java b/src/main/java/ling/coordinateRecorder/data/TransmitData.java new file mode 100644 index 0000000..932e824 --- /dev/null +++ b/src/main/java/ling/coordinateRecorder/data/TransmitData.java @@ -0,0 +1,92 @@ +package ling.coordinateRecorder.data; + +import ling.coordinateRecorder.CoordinateRecorder; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.NamespacedKey; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarFlag; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; +import org.jetbrains.annotations.Nullable; + +/// 传送数据 +public class TransmitData { + protected final PlayerData player; + protected final Location target; + protected final PlayerData targetPlayer; + protected long time; + protected boolean isInterrupt = false; + protected boolean isConfirm = true; + protected BossBar bossBar = Bukkit.createBossBar(new NamespacedKey(CoordinateRecorder.getCurrent(), "transmitBar"), + "正在准备传送", BarColor.BLUE, BarStyle.SOLID, BarFlag.DARKEN_SKY); + protected String interruptMessage = "未知原因"; + + public TransmitData(PlayerData player, Location target) { + this.target = target; + this.player = player; + this.targetPlayer = null; + time = System.currentTimeMillis(); + bossBar.addPlayer(player.getPlayer()); + } + + public TransmitData(PlayerData player, PlayerData target) { + this.targetPlayer = target; + this.target = null; + this.player = player; + this.time = System.currentTimeMillis(); + isConfirm = false; + bossBar.setTitle("等待目标玩家响应"); + bossBar.addPlayer(player.getPlayer()); + } + + public boolean isConfirm() { + return isConfirm; + } + + public void confirm() { + isConfirm = true; + bossBar.setTitle("正在准备传送"); + time = System.currentTimeMillis(); + bossBar.addPlayer(targetPlayer.getPlayer()); + } + + public void clear() { + bossBar.removeAll(); + } + + /// 打断传送 + public void interrupt(@Nullable String message) { + this.isInterrupt = true; + if (message != null) + this.interruptMessage = message; + } + + public String getInterruptMessage() { + return interruptMessage; + } + + public BossBar getBossBar() { + return bossBar; + } + + public boolean isInterrupt() { + return isInterrupt; + } + + public long getTime() { + return time; + } + + public PlayerData getTargetPlayer() { + return targetPlayer; + } + + public PlayerData getPlayer() { + return player; + } + + public Location getTarget() { + return target; + } +}