From eaa83a89d15d9efa90d792abd16a736bdb27aa60 Mon Sep 17 00:00:00 2001 From: carm Date: Tue, 14 Feb 2023 01:34:35 +0800 Subject: [PATCH] =?UTF-8?q?feat(delay):=20=E6=94=AF=E6=8C=81=E5=BB=B6?= =?UTF-8?q?=E8=BF=9F=E8=BF=9B=E8=A1=8C=E7=8E=A9=E5=AE=B6=E4=BC=A0=E9=80=81?= =?UTF-8?q?=E3=80=82#8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +- .../java/cc/carm/plugin/moeteleport/Main.java | 10 +- .../carm/plugin/moeteleport/MoeTeleport.java | 6 + .../command/home/HomeTeleportCommand.java | 4 +- .../command/parent/BackCommand.java | 3 +- .../command/parent/TeleportCommands.java | 10 +- .../command/sub/TeleportSubCommand.java | 12 +- .../teleport/TeleportCancelCommand.java | 48 ++++++ .../teleport/TeleportHandleCommand.java | 27 ++-- .../teleport/TeleportRequestCommand.java | 12 +- .../command/warp/WarpTeleportCommand.java | 3 +- .../plugin/moeteleport/conf/PluginConfig.java | 49 ++++-- .../moeteleport/conf/PluginMessages.java | 31 +++- .../listener/TeleportListener.java | 50 ++++++ .../moeteleport/manager/RequestManager.java | 127 +++++++++------- .../moeteleport/manager/TeleportManager.java | 143 +++++++++++++----- .../moeteleport/model/TeleportRequest.java | 73 --------- .../plugin/moeteleport/storage/UserData.java | 13 +- .../moeteleport/teleport/TeleportQueue.java | 55 +++++++ .../moeteleport/teleport/TeleportRequest.java | 89 +++++++++++ .../target/TeleportLocationTarget.java | 39 +++++ .../teleport/target/TeleportPlayerTarget.java | 25 +++ .../teleport/target/TeleportTarget.java | 43 ++++++ 23 files changed, 649 insertions(+), 229 deletions(-) create mode 100644 src/main/java/cc/carm/plugin/moeteleport/command/teleport/TeleportCancelCommand.java delete mode 100644 src/main/java/cc/carm/plugin/moeteleport/model/TeleportRequest.java create mode 100644 src/main/java/cc/carm/plugin/moeteleport/teleport/TeleportQueue.java create mode 100644 src/main/java/cc/carm/plugin/moeteleport/teleport/TeleportRequest.java create mode 100644 src/main/java/cc/carm/plugin/moeteleport/teleport/target/TeleportLocationTarget.java create mode 100644 src/main/java/cc/carm/plugin/moeteleport/teleport/target/TeleportPlayerTarget.java create mode 100644 src/main/java/cc/carm/plugin/moeteleport/teleport/target/TeleportTarget.java diff --git a/README.md b/README.md index 9e69021..767c7cc 100644 --- a/README.md +++ b/README.md @@ -25,12 +25,14 @@ - 多种存储格式,按需选择。 - 支持 YAML、JSON 与 MySQL/MariaDB 存储方式 - - 支持直接调用 [EssentialsX](https://github.com/EssentialsX/Essentials) 数据,无缝切换 + - 支持直接调用 [EssentialsX](https://github.com/EssentialsX/Essentials) / CMI 数据,无缝切换 - 可点击的消息(如“点击同意”) - 基于MineDown语法,可自定义配置 - 玩家间的传送请求 - 支持指定处理某位玩家的请求 -- 设置家与回家 (可以理解为私人地标) +- 设置地标点 + - 支持依照权限设定不同数量的地标点作为VIP附加内容 +- 设置家位置 (可以理解为私人地标) - 支持依照权限设定不同数量的家作为VIP附加内容 - 回到死亡地点、上一传送地点 diff --git a/src/main/java/cc/carm/plugin/moeteleport/Main.java b/src/main/java/cc/carm/plugin/moeteleport/Main.java index d157fe4..c4a8156 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/Main.java +++ b/src/main/java/cc/carm/plugin/moeteleport/Main.java @@ -9,10 +9,7 @@ import cc.carm.plugin.moeteleport.conf.PluginConfig; import cc.carm.plugin.moeteleport.conf.PluginMessages; import cc.carm.plugin.moeteleport.listener.TeleportListener; import cc.carm.plugin.moeteleport.listener.UserListener; -import cc.carm.plugin.moeteleport.manager.CommandManager; -import cc.carm.plugin.moeteleport.manager.RequestManager; -import cc.carm.plugin.moeteleport.manager.UserManager; -import cc.carm.plugin.moeteleport.manager.WarpManager; +import cc.carm.plugin.moeteleport.manager.*; import cc.carm.plugin.moeteleport.storage.DataStorage; import cc.carm.plugin.moeteleport.storage.StorageMethod; import org.bstats.bukkit.Metrics; @@ -29,6 +26,7 @@ public class Main extends EasyPlugin { protected WarpManager warpManager; protected UserManager userManager; protected RequestManager requestManager; + protected TeleportManager teleportManager; protected CommandManager commandManager; public Main() { @@ -72,6 +70,9 @@ public class Main extends EasyPlugin { log("加载请求管理器..."); this.requestManager = new RequestManager(this); + log("加载传送管理器..."); + this.teleportManager = new TeleportManager(this); + log("注册监听器..."); registerListener(new UserListener()); registerListener(new TeleportListener()); @@ -115,6 +116,7 @@ public class Main extends EasyPlugin { log("关闭所有请求..."); this.requestManager.shutdown(); + this.teleportManager.shutdown(); log("保存用户数据..."); this.userManager.unloadAll(true); diff --git a/src/main/java/cc/carm/plugin/moeteleport/MoeTeleport.java b/src/main/java/cc/carm/plugin/moeteleport/MoeTeleport.java index 3d7d0f4..ef9a4f2 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/MoeTeleport.java +++ b/src/main/java/cc/carm/plugin/moeteleport/MoeTeleport.java @@ -1,6 +1,7 @@ package cc.carm.plugin.moeteleport; import cc.carm.plugin.moeteleport.manager.RequestManager; +import cc.carm.plugin.moeteleport.manager.TeleportManager; import cc.carm.plugin.moeteleport.manager.UserManager; import cc.carm.plugin.moeteleport.manager.WarpManager; import cc.carm.plugin.moeteleport.storage.DataStorage; @@ -24,6 +25,11 @@ public class MoeTeleport { return Main.getInstance().requestManager; } + public static TeleportManager getTeleportManager() { + return Main.getInstance().teleportManager; + } + + public void setStorage(DataStorage storage) { Main.getInstance().storage = storage; } diff --git a/src/main/java/cc/carm/plugin/moeteleport/command/home/HomeTeleportCommand.java b/src/main/java/cc/carm/plugin/moeteleport/command/home/HomeTeleportCommand.java index 58b0585..f82413d 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/command/home/HomeTeleportCommand.java +++ b/src/main/java/cc/carm/plugin/moeteleport/command/home/HomeTeleportCommand.java @@ -1,10 +1,10 @@ package cc.carm.plugin.moeteleport.command.home; +import cc.carm.plugin.moeteleport.MoeTeleport; import cc.carm.plugin.moeteleport.command.parent.HomeCommands; import cc.carm.plugin.moeteleport.command.sub.HomeSubCommand; import cc.carm.plugin.moeteleport.conf.PluginMessages; import cc.carm.plugin.moeteleport.conf.location.DataLocation; -import cc.carm.plugin.moeteleport.manager.TeleportManager; import cc.carm.plugin.moeteleport.storage.UserData; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -36,7 +36,7 @@ public class HomeTeleportCommand extends HomeSubCommand { if (locationInfo == null) { PluginMessages.HOME.NOT_FOUND.send(player); } else { - TeleportManager.teleport(player, locationInfo.getValue(), false); + MoeTeleport.getTeleportManager().queueTeleport(player, locationInfo.getValue()); } return null; diff --git a/src/main/java/cc/carm/plugin/moeteleport/command/parent/BackCommand.java b/src/main/java/cc/carm/plugin/moeteleport/command/parent/BackCommand.java index 0a8a1f9..6b0f62c 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/command/parent/BackCommand.java +++ b/src/main/java/cc/carm/plugin/moeteleport/command/parent/BackCommand.java @@ -5,7 +5,6 @@ import cc.carm.plugin.moeteleport.MoeTeleport; import cc.carm.plugin.moeteleport.command.MainCommands; import cc.carm.plugin.moeteleport.conf.PluginConfig; import cc.carm.plugin.moeteleport.conf.PluginMessages; -import cc.carm.plugin.moeteleport.manager.TeleportManager; import cc.carm.plugin.moeteleport.storage.UserData; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -36,7 +35,7 @@ public class BackCommand extends SubCommand { PluginMessages.BACK.NO_LAST_LOCATION.send(player); return null; } - TeleportManager.teleport(player, data.getLastLocation(), false); + MoeTeleport.getTeleportManager().queueTeleport(player, data.getLastLocation()); return null; } diff --git a/src/main/java/cc/carm/plugin/moeteleport/command/parent/TeleportCommands.java b/src/main/java/cc/carm/plugin/moeteleport/command/parent/TeleportCommands.java index d11df5f..0cdac94 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/command/parent/TeleportCommands.java +++ b/src/main/java/cc/carm/plugin/moeteleport/command/parent/TeleportCommands.java @@ -2,10 +2,11 @@ package cc.carm.plugin.moeteleport.command.parent; import cc.carm.lib.easyplugin.command.CommandHandler; import cc.carm.plugin.moeteleport.command.MainCommands; +import cc.carm.plugin.moeteleport.command.teleport.TeleportCancelCommand; import cc.carm.plugin.moeteleport.command.teleport.TeleportHandleCommand; import cc.carm.plugin.moeteleport.command.teleport.TeleportRequestCommand; import cc.carm.plugin.moeteleport.conf.PluginMessages; -import cc.carm.plugin.moeteleport.model.TeleportRequest; +import cc.carm.plugin.moeteleport.teleport.TeleportRequest; import org.bukkit.command.CommandSender; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; @@ -19,10 +20,11 @@ public class TeleportCommands extends CommandHandler { super(plugin, cmd, aliases); this.main = main; - registerSubCommand(new TeleportRequestCommand(this, TeleportRequest.RequestType.TPA, "to")); - registerSubCommand(new TeleportRequestCommand(this, TeleportRequest.RequestType.TPA_HERE, "here")); - registerSubCommand(new TeleportHandleCommand(this, true, "accept")); + registerSubCommand(new TeleportRequestCommand(this, TeleportRequest.Type.TPA_TO, "to")); + registerSubCommand(new TeleportRequestCommand(this, TeleportRequest.Type.TPA_HERE, "here")); + registerSubCommand(new TeleportHandleCommand(this, true, "cancel")); registerSubCommand(new TeleportHandleCommand(this, false, "deny", "refuse")); + registerSubCommand(new TeleportCancelCommand(this, "cancel")); } @Override diff --git a/src/main/java/cc/carm/plugin/moeteleport/command/sub/TeleportSubCommand.java b/src/main/java/cc/carm/plugin/moeteleport/command/sub/TeleportSubCommand.java index d9065c7..bf97ee4 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/command/sub/TeleportSubCommand.java +++ b/src/main/java/cc/carm/plugin/moeteleport/command/sub/TeleportSubCommand.java @@ -4,6 +4,7 @@ import cc.carm.lib.easyplugin.command.SubCommand; import cc.carm.plugin.moeteleport.MoeTeleport; import cc.carm.plugin.moeteleport.command.parent.TeleportCommands; import cc.carm.plugin.moeteleport.storage.UserData; +import cc.carm.plugin.moeteleport.teleport.TeleportRequest; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.HumanEntity; @@ -12,10 +13,7 @@ import org.bukkit.util.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.UUID; +import java.util.*; import java.util.stream.Collectors; public abstract class TeleportSubCommand extends SubCommand { @@ -34,10 +32,14 @@ public abstract class TeleportSubCommand extends SubCommand { public @NotNull List listRequests(CommandSender sender, String input) { if (!(sender instanceof Player)) return Collections.emptyList(); - return getData((Player) sender).getReceivedRequests().keySet().stream() + return getReceivedRequests((Player) sender).keySet().stream() .map(Bukkit::getPlayer).filter(Objects::nonNull).map(HumanEntity::getName) .filter(s -> StringUtil.startsWithIgnoreCase(s, input)) .limit(10).collect(Collectors.toList()); } + public @NotNull Map getReceivedRequests(Player player) { + return MoeTeleport.getRequestManager().getUserReceivedRequests(player.getUniqueId()); + } + } \ No newline at end of file diff --git a/src/main/java/cc/carm/plugin/moeteleport/command/teleport/TeleportCancelCommand.java b/src/main/java/cc/carm/plugin/moeteleport/command/teleport/TeleportCancelCommand.java new file mode 100644 index 0000000..1606638 --- /dev/null +++ b/src/main/java/cc/carm/plugin/moeteleport/command/teleport/TeleportCancelCommand.java @@ -0,0 +1,48 @@ +package cc.carm.plugin.moeteleport.command.teleport; + +import cc.carm.plugin.moeteleport.MoeTeleport; +import cc.carm.plugin.moeteleport.command.parent.TeleportCommands; +import cc.carm.plugin.moeteleport.command.sub.TeleportSubCommand; +import cc.carm.plugin.moeteleport.conf.PluginMessages; +import cc.carm.plugin.moeteleport.teleport.TeleportRequest; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class TeleportCancelCommand extends TeleportSubCommand { + + public TeleportCancelCommand(@NotNull TeleportCommands parent, String name, String... aliases) { + super(parent, name, aliases); + } + + @Override + public Void execute(JavaPlugin plugin, CommandSender sender, String[] args) throws Exception { + if (!(sender instanceof Player)) { + PluginMessages.NOT_PLAYER.send(sender); + return null; + } + + Player player = (Player) sender; + + TeleportRequest request = MoeTeleport.getRequestManager().getRequest(player.getUniqueId()); + if (request == null) { + PluginMessages.REQUESTS.EMPTY_REQUESTS.send(player); + return null; + } + + MoeTeleport.getRequestManager().cancelRequest(request); + return null; + } + + @Override + public List tabComplete(JavaPlugin plugin, CommandSender sender, String[] args) { + if (args.length == 1) { + return listRequests(sender, args[args.length - 1]); + } else return Collections.emptyList(); + } + +} diff --git a/src/main/java/cc/carm/plugin/moeteleport/command/teleport/TeleportHandleCommand.java b/src/main/java/cc/carm/plugin/moeteleport/command/teleport/TeleportHandleCommand.java index 39d480c..6b2c2c2 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/command/teleport/TeleportHandleCommand.java +++ b/src/main/java/cc/carm/plugin/moeteleport/command/teleport/TeleportHandleCommand.java @@ -4,17 +4,15 @@ import cc.carm.plugin.moeteleport.MoeTeleport; import cc.carm.plugin.moeteleport.command.parent.TeleportCommands; import cc.carm.plugin.moeteleport.command.sub.TeleportSubCommand; import cc.carm.plugin.moeteleport.conf.PluginMessages; -import cc.carm.plugin.moeteleport.model.TeleportRequest; import cc.carm.plugin.moeteleport.storage.UserData; +import cc.carm.plugin.moeteleport.teleport.TeleportRequest; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; +import java.util.*; public class TeleportHandleCommand extends TeleportSubCommand { @@ -34,7 +32,9 @@ public class TeleportHandleCommand extends TeleportSubCommand { Player player = (Player) sender; UserData data = MoeTeleport.getUserManager().getData(player); - if (data.getReceivedRequests().isEmpty()) { + + Map receivedRequests = getReceivedRequests(player); + if (receivedRequests.isEmpty()) { PluginMessages.REQUESTS.EMPTY_REQUESTS.send(player); return null; } @@ -44,18 +44,23 @@ public class TeleportHandleCommand extends TeleportSubCommand { if (targetName != null) { Player target = Bukkit.getPlayer(targetName); - if (target == null || !data.getReceivedRequests().containsKey(target.getUniqueId())) { + TeleportRequest request = target == null ? null : receivedRequests.get(target.getUniqueId()); + + if (request == null) { PluginMessages.REQUESTS.NO_REQUEST_FROM.send(player, target == null ? targetName : target.getName()); } else { - handle(data.getReceivedRequests().get(target.getUniqueId())); // 交给Manager处理 + handle(request); // 交给Manager处理 } } else { - if (data.getReceivedRequests().size() == 1 || data.isEnableAutoSelect()) { - data.getReceivedRequests().values().stream() - .min(Comparator.comparingLong(TeleportRequest::getActiveTime)) + if (receivedRequests.size() == 1 || data.isEnableAutoSelect()) { + receivedRequests.values().stream() + .min(Comparator.comparingLong(TeleportRequest::getActiveMillis)) .ifPresent(this::handle); } else { - PluginMessages.REQUESTS.MULTI.send(player, data.getReceivedRequests().size(), (accept ? "tpaccept" : "tpdeny")); + PluginMessages.REQUESTS.MULTI.send(player, + receivedRequests.size(), + "moeteleport teleport " + (accept ? "tpAccept" : "tpDeny").toLowerCase() + ); data.setEnableAutoSelect(true); } } diff --git a/src/main/java/cc/carm/plugin/moeteleport/command/teleport/TeleportRequestCommand.java b/src/main/java/cc/carm/plugin/moeteleport/command/teleport/TeleportRequestCommand.java index 1824fb5..53942e7 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/command/teleport/TeleportRequestCommand.java +++ b/src/main/java/cc/carm/plugin/moeteleport/command/teleport/TeleportRequestCommand.java @@ -5,7 +5,7 @@ import cc.carm.plugin.moeteleport.MoeTeleport; import cc.carm.plugin.moeteleport.command.parent.TeleportCommands; import cc.carm.plugin.moeteleport.command.sub.TeleportSubCommand; import cc.carm.plugin.moeteleport.conf.PluginMessages; -import cc.carm.plugin.moeteleport.model.TeleportRequest; +import cc.carm.plugin.moeteleport.teleport.TeleportRequest; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -17,10 +17,10 @@ import java.util.List; public class TeleportRequestCommand extends TeleportSubCommand { - private final @NotNull TeleportRequest.RequestType type; + private final @NotNull TeleportRequest.Type type; public TeleportRequestCommand(@NotNull TeleportCommands parent, - @NotNull TeleportRequest.RequestType type, + @NotNull TeleportRequest.Type type, String name, String... aliases) { super(parent, name, aliases); this.type = type; @@ -48,9 +48,9 @@ public class TeleportRequestCommand extends TeleportSubCommand { return null; } - TeleportRequest request = MoeTeleport.getUserManager().getData(target).getReceivedRequests().get(player.getUniqueId()); - if (request != null) { - PluginMessages.REQUESTS.DUPLICATE.send(sender, target.getName(), request.getRemainSeconds()); + TeleportRequest sent = MoeTeleport.getRequestManager().getRequest(player.getUniqueId()); + if (sent != null) { + PluginMessages.REQUESTS.DUPLICATE.send(sender, target.getName(), sent.getRemainSeconds()); return null; } diff --git a/src/main/java/cc/carm/plugin/moeteleport/command/warp/WarpTeleportCommand.java b/src/main/java/cc/carm/plugin/moeteleport/command/warp/WarpTeleportCommand.java index 49afd6f..47ae4b5 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/command/warp/WarpTeleportCommand.java +++ b/src/main/java/cc/carm/plugin/moeteleport/command/warp/WarpTeleportCommand.java @@ -1,5 +1,6 @@ package cc.carm.plugin.moeteleport.command.warp; +import cc.carm.plugin.moeteleport.MoeTeleport; import cc.carm.plugin.moeteleport.command.parent.WarpCommands; import cc.carm.plugin.moeteleport.command.sub.WarpSubCommand; import cc.carm.plugin.moeteleport.conf.PluginMessages; @@ -36,7 +37,7 @@ public class WarpTeleportCommand extends WarpSubCommand { return null; } - TeleportManager.teleport(player, info.getLocation(), false); + MoeTeleport.getTeleportManager().queueTeleport(player, info.getLocation()); return null; } diff --git a/src/main/java/cc/carm/plugin/moeteleport/conf/PluginConfig.java b/src/main/java/cc/carm/plugin/moeteleport/conf/PluginConfig.java index 7cd9792..15dcfe2 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/conf/PluginConfig.java +++ b/src/main/java/cc/carm/plugin/moeteleport/conf/PluginConfig.java @@ -5,9 +5,9 @@ import cc.carm.lib.configuration.core.ConfigurationRoot; import cc.carm.lib.configuration.core.annotation.HeaderComment; import cc.carm.lib.configuration.core.util.MapFactory; import cc.carm.lib.configuration.core.value.ConfigValue; -import cc.carm.lib.configuration.core.value.type.ConfiguredList; import cc.carm.lib.configuration.core.value.type.ConfiguredMap; import cc.carm.lib.configuration.core.value.type.ConfiguredValue; +import cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredSound; import cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredTitle; public class PluginConfig extends ConfigurationRoot { @@ -33,7 +33,7 @@ public class PluginConfig extends ConfigurationRoot { @HeaderComment({"是否启用简化指令"}) public static final ConfigValue ENABLE = ConfiguredValue.of(Boolean.class, true); - + @HeaderComment({ "简化指令表,配置以方便玩家使用。", "格式: 简短指令: 本插件子指令(不含前缀)", @@ -45,6 +45,9 @@ public class PluginConfig extends ConfigurationRoot { map.put("back", "back"); map.put("tpa", "teleport to"); map.put("tpaHere", "teleport here"); + map.put("tpAccept", "teleport accept"); + map.put("tpDeny", "teleport deny"); + map.put("tpCancel", "teleport cancel"); map.put("home", "home to"); map.put("setHome", "home set"); @@ -73,17 +76,19 @@ public class PluginConfig extends ConfigurationRoot { @HeaderComment("传送的相关配置") public static final class TELEPORTATION extends ConfigurationRoot { + /* Will be supported again in the future @HeaderComment("危险的方块类型,将判断目的地脚下的方块的类型是否在这个列表中") public static final ConfiguredList DANGEROUS_TYPES = ConfiguredList.builder(String.class) .fromString() .defaults("LAVA", "AIR") .build(); + */ @HeaderComment("传送的引导时间,单位为秒") public static final ConfigValue WAIT_TIME = ConfiguredValue.of(Integer.class, 3); @HeaderComment("打断传送引导的方式") - public static final class INTERRUPT { + public static final class INTERRUPT extends ConfigurationRoot { @HeaderComment("在传送引导时是否会因为移动打断传送") public static final ConfigValue MOVE = ConfiguredValue.of(Boolean.class, true); @@ -96,22 +101,32 @@ public class PluginConfig extends ConfigurationRoot { } - @HeaderComment("传送引导过程中的标题") - public static final class TITLE { + @HeaderComment("传送过程中的标题") + public static final class TITLE extends ConfigurationRoot { - public static final ConfiguredTitle CHANNELING = ConfiguredTitle.create().defaults( - "&d&l传送中...", + public static final ConfiguredTitle CHANNELING = PluginMessages.title().defaults( + "&d&l将在 %(time) 秒后传送", "&7传送过程中请不要移动" - ).params("location").fadeIn(0).stay(10).fadeOut(0).build(); + ).params("time", "target").fadeIn(0).stay(25).fadeOut(0).build(); - public static final ConfiguredTitle TELEPORTED = ConfiguredTitle.create().defaults( + public static final ConfiguredTitle TELEPORTED = PluginMessages.title().defaults( "&d&l传送完成", - "&7已将您传送到 %(location)" - ).params("location").fadeIn(0).stay(20).fadeOut(10).build(); + "&7已将您传送到 %(target)" + ).params("target").fadeIn(0).stay(20).fadeOut(10).build(); } - @HeaderComment("传送引导特效与音效") + @HeaderComment("传送引导过程中的音效") + public static final class SOUND extends ConfigurationRoot { + + public static final ConfiguredSound CHANNELING = ConfiguredSound.of("UI_BUTTON_CLICK", 0.5f, 1.0f); + public static final ConfiguredSound TELEPORTED = ConfiguredSound.of("ENTITY_ENDERMAN_TELEPORT", 0.5f, 1.0f); + public static final ConfiguredSound FAILED = ConfiguredSound.of("ENTITY_VILLAGER_NO", 0.5f, 1.0f); + public static final ConfiguredSound INTERRUPTED = ConfiguredSound.of("BLOCK_NOTE_BLOCK_BASEDRUM", 1f, 1.0f); + + } + + @HeaderComment("传送引导特效") public static final ConfigValue EFFECTS = ConfiguredValue.of(Boolean.class, true); } @@ -123,8 +138,14 @@ public class PluginConfig extends ConfigurationRoot { @HeaderComment("请求的过期时间,单位为秒") public static final ConfigValue EXPIRE_TIME = ConfiguredValue.of(Integer.class, 30); - @HeaderComment("一个玩家同时能发出的最大请求数量") - public static final ConfigValue MAX = ConfiguredValue.of(Integer.class, 3); + + public static final class SOUND extends ConfigurationRoot { + + public static final ConfiguredSound SENT = ConfiguredSound.of("UI_BUTTON_CLICK", 0.5f, 1.0f); + public static final ConfiguredSound RECEIVED = ConfiguredSound.of("ENTITY_EXPERIENCE_ORB_PICKUP", 0.5f, 1.0f); + public static final ConfiguredSound CANCELLED = ConfiguredSound.of("ENTITY_VILLAGER_NO", 0.5f, 1.0f); + + } } diff --git a/src/main/java/cc/carm/plugin/moeteleport/conf/PluginMessages.java b/src/main/java/cc/carm/plugin/moeteleport/conf/PluginMessages.java index 730444b..c3f7446 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/conf/PluginMessages.java +++ b/src/main/java/cc/carm/plugin/moeteleport/conf/PluginMessages.java @@ -4,8 +4,10 @@ import cc.carm.lib.configuration.core.ConfigurationRoot; import cc.carm.lib.easyplugin.utils.ColorParser; import cc.carm.lib.mineconfiguration.bukkit.builder.message.CraftMessageListBuilder; import cc.carm.lib.mineconfiguration.bukkit.builder.message.CraftMessageValueBuilder; +import cc.carm.lib.mineconfiguration.bukkit.builder.title.TitleConfigBuilder; import cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredMessage; import cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredMessageList; +import cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredTitle; import de.themoep.minedown.MineDown; import me.clip.placeholderapi.PlaceholderAPI; import net.md_5.bungee.api.chat.BaseComponent; @@ -27,6 +29,10 @@ public class PluginMessages extends ConfigurationRoot { .whenSend((sender, message) -> sender.spigot().sendMessage(message)); } + public static @NotNull TitleConfigBuilder title() { + return ConfiguredTitle.create().whenSend((player, in, stay, out, line1, line2) -> player.sendTitle(line1, line2, in, stay, out)); + } + public static @NotNull BiFunction getParser() { return (sender, message) -> { if (sender instanceof Player) message = PlaceholderAPI.setPlaceholders((Player) sender, message); @@ -73,7 +79,9 @@ public class PluginMessages extends ConfigurationRoot { "&8#&f teleport accept &d[玩家]", "&8-&7 同意一个传送请求(可具体指定玩家的请求)。", "&8#&f teleport deny &d[玩家]", - "&8-&7 拒绝一个传送请求(可具体指定玩家的请求)。" + "&8-&7 拒绝一个传送请求(可具体指定玩家的请求)。", + "&8#&f teleport cancel", + "&8-&7 取消已经发出的传送请求。" ).build(); public static final ConfiguredMessageList WARPS = list().defaults( @@ -136,9 +144,9 @@ public class PluginMessages extends ConfigurationRoot { } public static class TELEPORT extends ConfigurationRoot { - public static final ConfiguredMessageList TELEPORTING = list().defaults( - "&f正在将您传送到 &d%(location) &f..." - ).params("location").build(); + public static final ConfiguredMessageList TELEPORTED = list().defaults( + "&f正在将您传送到 &d%(target) &f..." + ).params("target").build(); public static final ConfiguredMessageList NOT_SAFE = list().defaults( "&f目标地点 &d%(location) &f可能并不安全,因此传送被暂缓执行。", @@ -149,6 +157,10 @@ public class PluginMessages extends ConfigurationRoot { "&f目标地点丢失,暂时无法前往,传送被取消。" ).build(); + public static final ConfiguredMessageList INTERRUPTED = list().defaults( + "&c&l传送中断!&f传送过程中请不要移动。" + ).build(); + } public static class REQUESTS extends ConfigurationRoot { @@ -177,7 +189,8 @@ public class PluginMessages extends ConfigurationRoot { ).params("player", "expire").build(); public static final ConfiguredMessageList DUPLICATE = list().defaults( - "&f您已经向 &d%(player) &f发送过传送请求,对方仍有 &5%(expire)秒 &f的时间回应该请求。" + "&f您已经向 &d%(player) &f发送过传送请求,对方仍有 &5%(expire)秒 &f的时间回应该请求。", + "&f如您想要取消该请求,请输入 [&e&l[点击取消]](show_text=点击同意请求 run_command=/moeteleport teleport cancel %(player)) &f或输入 &5/tpCancel &f取消该请求。" ).params("player", "expire").build(); public static final ConfiguredMessageList RECEIVED_TP_HERE = list().defaults( @@ -217,6 +230,14 @@ public class PluginMessages extends ConfigurationRoot { "&f来自 &d%(player) &f的传送请求已超时。" ).params("player").build(); + public static final ConfiguredMessageList SENT_CANCELLED = list().defaults( + "&f发往 &d%(player) &f的传送请求已取消。" + ).params("player").build(); + + public static final ConfiguredMessageList RECEIVED_CANCELLED = list().defaults( + "&f来自 &d%(player) &f的传送请求已被取消。" + ).params("player").build(); + } diff --git a/src/main/java/cc/carm/plugin/moeteleport/listener/TeleportListener.java b/src/main/java/cc/carm/plugin/moeteleport/listener/TeleportListener.java index 010118c..a114b94 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/listener/TeleportListener.java +++ b/src/main/java/cc/carm/plugin/moeteleport/listener/TeleportListener.java @@ -1,6 +1,56 @@ package cc.carm.plugin.moeteleport.listener; +import cc.carm.plugin.moeteleport.MoeTeleport; +import cc.carm.plugin.moeteleport.conf.PluginConfig; +import cc.carm.plugin.moeteleport.teleport.TeleportQueue; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerToggleSneakEvent; public class TeleportListener implements Listener { + + @EventHandler + public void onMove(PlayerMoveEvent event) { + if (!PluginConfig.TELEPORTATION.INTERRUPT.MOVE.getNotNull()) return; + + 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; + } + + TeleportQueue queue = MoeTeleport.getTeleportManager().getQueue(event.getPlayer()); + if (queue == null) return; + + MoeTeleport.getTeleportManager().interruptQueue(queue); + } + + @EventHandler + public void onDamage(EntityDamageByEntityEvent event) { + if (!PluginConfig.TELEPORTATION.INTERRUPT.ATTACK.getNotNull()) return; + if (!(event.getEntity() instanceof Player)) return; + + TeleportQueue queue = MoeTeleport.getTeleportManager().getQueue((Player) event.getEntity()); + if (queue == null) return; + + MoeTeleport.getTeleportManager().interruptQueue(queue); + } + + @EventHandler + public void onSnake(PlayerToggleSneakEvent event) { + if (!PluginConfig.TELEPORTATION.INTERRUPT.SNAKE.getNotNull()) return; + TeleportQueue queue = MoeTeleport.getTeleportManager().getQueue(event.getPlayer()); + if (queue == null) return; + + MoeTeleport.getTeleportManager().interruptQueue(queue); + } + } diff --git a/src/main/java/cc/carm/plugin/moeteleport/manager/RequestManager.java b/src/main/java/cc/carm/plugin/moeteleport/manager/RequestManager.java index 2989408..70903ee 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/manager/RequestManager.java +++ b/src/main/java/cc/carm/plugin/moeteleport/manager/RequestManager.java @@ -4,59 +4,83 @@ import cc.carm.plugin.moeteleport.Main; import cc.carm.plugin.moeteleport.MoeTeleport; import cc.carm.plugin.moeteleport.conf.PluginConfig; import cc.carm.plugin.moeteleport.conf.PluginMessages; -import cc.carm.plugin.moeteleport.model.TeleportRequest; -import cc.carm.plugin.moeteleport.storage.UserData; -import org.bukkit.Bukkit; +import cc.carm.plugin.moeteleport.teleport.TeleportRequest; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; -import java.util.Objects; +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; public class RequestManager { - public BukkitRunnable checkRunnable; + protected final Map requests = new ConcurrentHashMap<>(); + protected BukkitRunnable runnable; public RequestManager(Main main) { - this.checkRunnable = new BukkitRunnable() { + this.runnable = new BukkitRunnable() { @Override public void run() { - checkRequests(); + tickRequests(); } }; - this.checkRunnable.runTaskTimerAsynchronously(main, 100L, 20L); + this.runnable.runTaskTimerAsynchronously(main, 100L, 20L); } public void shutdown() { - if (!this.checkRunnable.isCancelled()) { - this.checkRunnable.cancel(); + if (!this.runnable.isCancelled()) { + this.runnable.cancel(); } } - public void checkRequests() { - MoeTeleport.getUserManager().getUserDataMap().values() - .forEach(data -> data.getReceivedRequests().entrySet().stream() - .filter(entry -> entry.getValue().isExpired()) - .peek(entry -> { - Player sender = entry.getValue().getSender(); - Player receiver = entry.getValue().getReceiver(); - PluginMessages.REQUESTS.SENT_TIMEOUT.send(sender, receiver.getName()); - PluginMessages.REQUESTS.RECEIVED_TIMEOUT.send(receiver, sender.getName()); - }) - .peek(entry -> MoeTeleport.getUserManager() - .getData(entry.getValue().getSender()).getSentRequests() - .remove(entry.getKey())) - .forEach(entry -> data.getReceivedRequests().remove(entry.getKey())) - ); + @Unmodifiable + public Map getRequests() { + return Collections.unmodifiableMap(requests); } - public void sendRequest(Player sender, Player receiver, TeleportRequest.RequestType type) { + public @Nullable TeleportRequest getRequest(UUID senderUUID) { + return requests.get(senderUUID); + } + + @Unmodifiable + public @NotNull Map getUserReceivedRequests(@NotNull UUID receiverUUID) { + return requests.values().stream() + .filter(request -> request.getReceiver().getUniqueId().equals(receiverUUID)) + .collect(Collectors.toMap(request -> request.getSender().getUniqueId(), request -> request)); + } + + public void tickRequests() { + Iterator> requestIterator = requests.entrySet().iterator(); + while (requestIterator.hasNext()) { + Map.Entry entry = requestIterator.next(); + TeleportRequest request = entry.getValue(); + if (!request.isExpired()) continue; + + requestIterator.remove(); // 移除过期的请求 + + // 发送提示 + PluginMessages.REQUESTS.SENT_TIMEOUT.send(request.getSender(), request.getReceiver().getName()); + PluginMessages.REQUESTS.RECEIVED_TIMEOUT.send(request.getReceiver(), request.getSender().getName()); + } + } + + public void sendRequest(Player sender, Player receiver, TeleportRequest.Type type) { int expireTime = PluginConfig.REQUEST.EXPIRE_TIME.getNotNull(); - PluginMessages.REQUESTS.SENT.send(sender, receiver.getName(), expireTime); + PluginConfig.REQUEST.SOUND.SENT.playTo(sender); + PluginConfig.REQUEST.SOUND.RECEIVED.playTo(receiver); + PluginMessages.REQUESTS.SENT.send(sender, receiver.getName(), expireTime); switch (type) { - case TPA: { + case TPA_TO: { PluginMessages.REQUESTS.RECEIVED_TP_HERE.send(receiver, sender.getName(), expireTime); break; } @@ -66,17 +90,26 @@ public class RequestManager { } } - TeleportRequest request = new TeleportRequest(sender, receiver, type); - MoeTeleport.getUserManager().getData(receiver).getReceivedRequests().put(sender.getUniqueId(), request); - MoeTeleport.getUserManager().getData(sender).getSentRequests().add(receiver.getUniqueId()); - + requests.put(sender.getUniqueId(), new TeleportRequest(type, sender, receiver)); } public void acceptRequest(TeleportRequest request) { PluginMessages.REQUESTS.WAS_ACCEPTED.send(request.getSender(), request.getReceiver().getName()); PluginMessages.REQUESTS.ACCEPTED.send(request.getReceiver(), request.getSender().getName()); - TeleportManager.teleport(request.getTeleportPlayer(), request.getTeleportLocation(), true); + removeRequests(request); + MoeTeleport.getTeleportManager().queueTeleport(request.createQueue( + Duration.of(PluginConfig.TELEPORTATION.WAIT_TIME.getNotNull(), ChronoUnit.SECONDS) + )); + } + + public void cancelRequest(TeleportRequest request) { + PluginMessages.REQUESTS.WAS_ACCEPTED.send(request.getSender(), request.getReceiver().getName()); + PluginMessages.REQUESTS.ACCEPTED.send(request.getReceiver(), request.getSender().getName()); + PluginConfig.REQUEST.SOUND.CANCELLED.playTo(request.getSender()); + PluginConfig.REQUEST.SOUND.CANCELLED.playTo(request.getReceiver()); + removeRequests(request); + MoeTeleport.getTeleportManager().queueTeleport(request); } public void denyRequest(TeleportRequest request) { @@ -86,31 +119,21 @@ public class RequestManager { } public void removeRequests(TeleportRequest request) { - MoeTeleport.getUserManager().getData(request.getSender()) - .getSentRequests() - .remove(request.getReceiver().getUniqueId()); - MoeTeleport.getUserManager().getData(request.getReceiver()) - .getReceivedRequests() - .remove(request.getSender().getUniqueId()); + this.requests.remove(request.getSender().getUniqueId()); } public void cancelAllRequests(Player player) { UUID playerUUID = player.getUniqueId(); - UserData data = MoeTeleport.getUserManager().getData(player); - data.getReceivedRequests().keySet().stream() - .peek(senderUUID -> PluginMessages.REQUESTS.OFFLINE.send(Bukkit.getPlayer(senderUUID), player.getName())) - .map(senderUUID -> MoeTeleport.getUserManager().getData(senderUUID)) - .filter(Objects::nonNull).map(UserData::getSentRequests) - .forEach(receivers -> receivers.remove(playerUUID)); - data.getSentRequests().stream() - .peek(receiverUUID -> PluginMessages.REQUESTS.OFFLINE.send(Bukkit.getPlayer(receiverUUID), player.getName())) - .map(receiverUUID -> MoeTeleport.getUserManager().getData(receiverUUID)) - .filter(Objects::nonNull).map(UserData::getReceivedRequests) - .forEach(senders -> senders.remove(playerUUID)); + TeleportRequest sent = requests.remove(playerUUID); + if (sent != null) { + PluginMessages.REQUESTS.OFFLINE.send(sent.getReceiver(), player.getName()); + } - data.getSentRequests().clear(); - data.getReceivedRequests().clear(); + for (TeleportRequest received : getUserReceivedRequests(playerUUID).values()) { + PluginMessages.REQUESTS.OFFLINE.send(received.getSender(), player.getName()); + removeRequests(received); + } } } diff --git a/src/main/java/cc/carm/plugin/moeteleport/manager/TeleportManager.java b/src/main/java/cc/carm/plugin/moeteleport/manager/TeleportManager.java index 4b0798c..a20d093 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/manager/TeleportManager.java +++ b/src/main/java/cc/carm/plugin/moeteleport/manager/TeleportManager.java @@ -1,52 +1,123 @@ package cc.carm.plugin.moeteleport.manager; -import cc.carm.plugin.moeteleport.MoeTeleport; +import cc.carm.plugin.moeteleport.Main; import cc.carm.plugin.moeteleport.conf.PluginConfig; import cc.carm.plugin.moeteleport.conf.PluginMessages; import cc.carm.plugin.moeteleport.conf.location.DataLocation; +import cc.carm.plugin.moeteleport.teleport.TeleportQueue; +import cc.carm.plugin.moeteleport.teleport.TeleportRequest; +import cc.carm.plugin.moeteleport.teleport.target.TeleportLocationTarget; +import cc.carm.plugin.moeteleport.teleport.target.TeleportTarget; import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.Nullable; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.util.Iterator; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; public class TeleportManager { + protected final Map teleportQueue = new ConcurrentHashMap<>(); + protected BukkitRunnable runnable; - public static void teleport(Player player, DataLocation targetLocation, boolean onlySafety) { - Location location = targetLocation.getBukkitLocation(); - if (location == null) { - PluginMessages.TELEPORT.NOT_AVAILABLE.send(player, targetLocation.toFlatString()); - } else { - teleport(player, location, onlySafety); - } - } - - public static void teleport(Player player, Location targetLocation, boolean onlySafety) { - if (targetLocation.isWorldLoaded()) { - if (!onlySafety || TeleportManager.isSafeLocation(targetLocation)) { - MoeTeleport.getUserManager().getData(player).setLastLocation(player.getLocation()); - player.teleport(targetLocation); - PluginMessages.TELEPORT.TELEPORTING.send(player, new DataLocation(targetLocation).toFlatString()); - } else { - PluginMessages.TELEPORT.NOT_SAFE.send(player, new DataLocation(targetLocation).toFlatString()); + public TeleportManager(Main main) { + this.runnable = new BukkitRunnable() { + @Override + public void run() { + tickQueue(); } + }; + this.runnable.runTaskTimerAsynchronously(main, 20L, 20L); + } + + public void shutdown() { + if (!this.runnable.isCancelled()) { + this.runnable.cancel(); + } + } + + public void tickQueue() { + Iterator> queueIterator = teleportQueue.entrySet().iterator(); + while (queueIterator.hasNext()) { + Map.Entry entry = queueIterator.next(); + TeleportQueue queue = entry.getValue(); + if (!queue.checkTime()) { + PluginConfig.TELEPORTATION.SOUND.CHANNELING.playTo(queue.getPlayer()); + PluginConfig.TELEPORTATION.TITLE.CHANNELING.send( + queue.getPlayer(), + queue.getRemainSeconds() + 1, queue.getTarget().getText() + ); + continue; + } + + queueIterator.remove(); + executeTeleport(queue); + } + } + + public void interruptQueue(TeleportQueue queue) { + teleportQueue.remove(queue.getPlayer().getUniqueId()); + PluginMessages.TELEPORT.INTERRUPTED.send(queue.getPlayer()); + PluginConfig.TELEPORTATION.SOUND.INTERRUPTED.playTo(queue.getPlayer()); + } + + public TeleportQueue getQueue(UUID uuid) { + return teleportQueue.get(uuid); + } + + public TeleportQueue getQueue(Player player) { + return getQueue(player.getUniqueId()); + } + + public @Nullable Duration getDelayDuration() { + return Duration.of(PluginConfig.TELEPORTATION.WAIT_TIME.getNotNull(), ChronoUnit.SECONDS); + } + + public void queueTeleport(@Nullable TeleportQueue queue) { + if (queue == null) return; + if (queue.checkTime()) { // 直接满足传送条件 + executeTeleport(queue); + return; + } + teleportQueue.put(queue.getPlayer().getUniqueId(), queue); + } + + public void queueTeleport(TeleportRequest request) { + queueTeleport(request.createQueue(getDelayDuration())); + } + + public void queueTeleport(Player player, TeleportTarget target) { + queueTeleport(new TeleportQueue(player, target, getDelayDuration())); + } + + public void queueTeleport(Player player, DataLocation target) { + queueTeleport(player, new TeleportLocationTarget(target)); + } + + public void queueTeleport(Player player, Location target) { + queueTeleport(player, new TeleportLocationTarget(target)); + } + + protected void executeTeleport(TeleportQueue queue) { + Player player = queue.getPlayer(); + queue.getUser().setLastLocation(player.getLocation()); + + Location location = queue.getTarget().prepare(); + if (location == null) { + PluginMessages.TELEPORT.NOT_AVAILABLE.send(player, queue.getTarget().getText()); + PluginConfig.TELEPORTATION.SOUND.FAILED.playTo(player); } else { - PluginMessages.TELEPORT.NOT_SAFE.send(player, new DataLocation(targetLocation).toFlatString()); + PluginMessages.TELEPORT.TELEPORTED.send(player, queue.getTarget().getText()); + PluginConfig.TELEPORTATION.TITLE.TELEPORTED.send(player, queue.getTarget().getText()); + Main.getInstance().getScheduler().run(() -> { + player.teleport(location); + PluginConfig.TELEPORTATION.SOUND.TELEPORTED.playTo(player); + }); } } - - public static boolean isSafeLocation(Location location) { - Block leg = location.getBlock(); - if (!leg.getType().isAir()) { - return false; // not transparent (will suffocate) - } - Block head = leg.getRelative(BlockFace.UP); - if (!head.getType().isAir()) { - return false; // not transparent (will suffocate) - } - Block ground = leg.getRelative(BlockFace.DOWN); - return !PluginConfig.TELEPORTATION.DANGEROUS_TYPES.getNotNull().contains(ground.getType().name()); - } - - } diff --git a/src/main/java/cc/carm/plugin/moeteleport/model/TeleportRequest.java b/src/main/java/cc/carm/plugin/moeteleport/model/TeleportRequest.java deleted file mode 100644 index b389afe..0000000 --- a/src/main/java/cc/carm/plugin/moeteleport/model/TeleportRequest.java +++ /dev/null @@ -1,73 +0,0 @@ -package cc.carm.plugin.moeteleport.model; - -import cc.carm.plugin.moeteleport.conf.PluginConfig; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -public class TeleportRequest { - - final @NotNull Player sender; - final @NotNull Player receiver; - final @NotNull RequestType type; - - final long createTime; - - boolean confirmed; // 当目的地危险时,需要确认 - - public TeleportRequest(@NotNull Player sender, - @NotNull Player receiver, - @NotNull RequestType type) { - this.sender = sender; - this.receiver = receiver; - this.type = type; - this.createTime = System.currentTimeMillis(); - } - - public @NotNull Player getSender() { - return sender; - } - - public @NotNull Player getReceiver() { - return receiver; - } - - public @NotNull Player getTeleportPlayer() { - return getType() == RequestType.TPA ? getSender() : getReceiver(); - } - - public @NotNull Location getTeleportLocation() { - return getType() == RequestType.TPA_HERE ? getSender().getLocation() : getReceiver().getLocation(); - } - - public @NotNull RequestType getType() { - return type; - } - - public long getCreateTime() { - return createTime; - } - - public long getActiveTime() { - return System.currentTimeMillis() - getCreateTime(); - } - - public long getRemainTime() { - return PluginConfig.REQUEST.EXPIRE_TIME.getNotNull() * 1000 - getActiveTime(); - } - - public long getRemainSeconds() { - return getRemainTime() / 1000; - } - - public boolean isExpired() { - return getActiveTime() > PluginConfig.REQUEST.EXPIRE_TIME.getNotNull() * 1000; - } - - public enum RequestType { - TPA, - TPA_HERE - } - - -} diff --git a/src/main/java/cc/carm/plugin/moeteleport/storage/UserData.java b/src/main/java/cc/carm/plugin/moeteleport/storage/UserData.java index d2d8114..9fa35e0 100644 --- a/src/main/java/cc/carm/plugin/moeteleport/storage/UserData.java +++ b/src/main/java/cc/carm/plugin/moeteleport/storage/UserData.java @@ -2,20 +2,17 @@ package cc.carm.plugin.moeteleport.storage; import cc.carm.plugin.moeteleport.MoeTeleport; import cc.carm.plugin.moeteleport.conf.location.DataLocation; -import cc.carm.plugin.moeteleport.model.TeleportRequest; import org.bukkit.Location; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; public class UserData { protected final @NotNull UUID userUUID; private final LinkedHashMap homeLocations; - private final HashSet sentRequests = new HashSet<>(); // 记录发出的请求 - private final ConcurrentHashMap receivedRequests = new ConcurrentHashMap<>(); // 记录收到的传送请求 + public boolean enableAutoSelect = false; private @Nullable Location lastLocation; @@ -74,14 +71,6 @@ public class UserData { this.lastLocation = lastLocation; } - public HashSet getSentRequests() { - return sentRequests; - } - - public ConcurrentHashMap getReceivedRequests() { - return receivedRequests; - } - public boolean isEnableAutoSelect() { return enableAutoSelect; } diff --git a/src/main/java/cc/carm/plugin/moeteleport/teleport/TeleportQueue.java b/src/main/java/cc/carm/plugin/moeteleport/teleport/TeleportQueue.java new file mode 100644 index 0000000..96fd55c --- /dev/null +++ b/src/main/java/cc/carm/plugin/moeteleport/teleport/TeleportQueue.java @@ -0,0 +1,55 @@ +package cc.carm.plugin.moeteleport.teleport; + +import cc.carm.plugin.moeteleport.MoeTeleport; +import cc.carm.plugin.moeteleport.storage.UserData; +import cc.carm.plugin.moeteleport.teleport.target.TeleportTarget; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.time.Duration; + +public class TeleportQueue { + + private final @NotNull Player player; + private final @NotNull TeleportTarget target; + + private final long createMillis; + private final long executeMillis; + + public TeleportQueue(@NotNull Player player, @NotNull TeleportTarget target, @Nullable Duration delay) { + this.player = player; + this.target = target; + this.createMillis = System.currentTimeMillis(); + this.executeMillis = delay == null ? 0 : System.currentTimeMillis() + delay.toMillis(); + } + + public @NotNull Player getPlayer() { + return player; + } + + public @NotNull UserData getUser() { + return MoeTeleport.getUserManager().getData(getPlayer()); + } + + public @NotNull TeleportTarget getTarget() { + return target; + } + + public long getCreateMillis() { + return createMillis; + } + + public long getExecuteMillis() { + return executeMillis; + } + + public long getRemainSeconds() { + return (executeMillis - System.currentTimeMillis()) / 1000; + } + + public boolean checkTime() { + return System.currentTimeMillis() >= executeMillis; + } + +} diff --git a/src/main/java/cc/carm/plugin/moeteleport/teleport/TeleportRequest.java b/src/main/java/cc/carm/plugin/moeteleport/teleport/TeleportRequest.java new file mode 100644 index 0000000..7243624 --- /dev/null +++ b/src/main/java/cc/carm/plugin/moeteleport/teleport/TeleportRequest.java @@ -0,0 +1,89 @@ +package cc.carm.plugin.moeteleport.teleport; + +import cc.carm.plugin.moeteleport.MoeTeleport; +import cc.carm.plugin.moeteleport.conf.PluginConfig; +import cc.carm.plugin.moeteleport.storage.UserData; +import cc.carm.plugin.moeteleport.teleport.target.TeleportPlayerTarget; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.time.Duration; + +public class TeleportRequest { + + public enum Type {TPA_TO, TPA_HERE} + + private final @NotNull Type type; + + private final @NotNull Player sender; + private final @NotNull Player receiver; + + private final long createMillis; + + public TeleportRequest(@NotNull Type type, @NotNull Player sender, @NotNull Player receiver) { + this.type = type; + this.sender = sender; + this.receiver = receiver; + this.createMillis = System.currentTimeMillis(); + } + + public @NotNull Type getRequestType() { + return type; + } + + public @NotNull Player getReceiver() { + return receiver; + } + + public @NotNull UserData getReceiverUser() { + return MoeTeleport.getUserManager().getData(getReceiver()); + } + + public @NotNull Player getSender() { + return sender; + } + + public @NotNull UserData getSenderUser() { + return MoeTeleport.getUserManager().getData(getSender()); + } + + public long getCreateMillis() { + return createMillis; + } + + public long getActiveMillis() { + return System.currentTimeMillis() - getCreateMillis(); + } + + public long getRemainMillis() { + return PluginConfig.REQUEST.EXPIRE_TIME.getNotNull() * 1000 - getActiveMillis(); + } + + public long getRemainSeconds() { + return getRemainMillis() / 1000; + } + + public boolean isExpired() { + return getActiveMillis() > PluginConfig.REQUEST.EXPIRE_TIME.getNotNull() * 1000; + } + + public @Nullable TeleportQueue createQueue(@Nullable Duration delay) { + Player player; + TeleportPlayerTarget destination; + + if (type == Type.TPA_TO) { + destination = new TeleportPlayerTarget(receiver); + player = sender; + } else if (type == Type.TPA_HERE) { + destination = new TeleportPlayerTarget(sender); + player = receiver; + } else { + return null; + } + + return new TeleportQueue(player, destination, delay); + } + + +} diff --git a/src/main/java/cc/carm/plugin/moeteleport/teleport/target/TeleportLocationTarget.java b/src/main/java/cc/carm/plugin/moeteleport/teleport/target/TeleportLocationTarget.java new file mode 100644 index 0000000..cac63e1 --- /dev/null +++ b/src/main/java/cc/carm/plugin/moeteleport/teleport/target/TeleportLocationTarget.java @@ -0,0 +1,39 @@ +package cc.carm.plugin.moeteleport.teleport.target; + +import cc.carm.plugin.moeteleport.conf.location.DataLocation; +import org.bukkit.Location; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class TeleportLocationTarget implements TeleportTarget { + + private final @NotNull DataLocation location; + + public TeleportLocationTarget(@NotNull DataLocation location) { + this.location = location; + } + + public TeleportLocationTarget(@NotNull Location location) { + this(new DataLocation(location)); + } + + public @NotNull DataLocation getDataLocation() { + return location; + } + + public @Nullable Location getLocation() { + return getDataLocation().getBukkitLocation(); + } + + @Override + public Location prepare() { + Location loc = getLocation(); + if (loc == null || !loc.isWorldLoaded()) return null; + return loc; + } + + @Override + public String getText() { + return getDataLocation().toFlatString(); + } +} diff --git a/src/main/java/cc/carm/plugin/moeteleport/teleport/target/TeleportPlayerTarget.java b/src/main/java/cc/carm/plugin/moeteleport/teleport/target/TeleportPlayerTarget.java new file mode 100644 index 0000000..8e073d0 --- /dev/null +++ b/src/main/java/cc/carm/plugin/moeteleport/teleport/target/TeleportPlayerTarget.java @@ -0,0 +1,25 @@ +package cc.carm.plugin.moeteleport.teleport.target; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class TeleportPlayerTarget implements TeleportTarget { + + protected final @NotNull Player target; + + public TeleportPlayerTarget(@NotNull Player target) { + this.target = target; + } + + @Override + public Location prepare() { + return target.isOnline() ? target.getLocation() : null; + } + + @Override + public String getText() { + return target.getName(); + } + +} diff --git a/src/main/java/cc/carm/plugin/moeteleport/teleport/target/TeleportTarget.java b/src/main/java/cc/carm/plugin/moeteleport/teleport/target/TeleportTarget.java new file mode 100644 index 0000000..5e9bc30 --- /dev/null +++ b/src/main/java/cc/carm/plugin/moeteleport/teleport/target/TeleportTarget.java @@ -0,0 +1,43 @@ +package cc.carm.plugin.moeteleport.teleport.target; + +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.jetbrains.annotations.Nullable; + +public interface TeleportTarget { + + /** + * 准备可传送的目的地 + * + * @return 准备传送目的地 + */ + @Nullable Location prepare(); + + /** + * @return 目标的文字介绍 + */ + String getText(); + + /** + * 检查一个位置是否安全 + * + * @param location 位置 + * @return 是否安全 + */ + @Deprecated + static boolean checkLocation(Location location) { + Block leg = location.getBlock(); + if (!leg.getType().isAir()) { + return false; // not transparent (will suffocate) + } + Block head = leg.getRelative(BlockFace.UP); + if (!head.getType().isAir()) { + return false; // not transparent (will suffocate) + } + Block ground = leg.getRelative(BlockFace.DOWN); +// return !PluginConfig.TELEPORTATION.DANGEROUS_TYPES.getNotNull().contains(ground.getType().name()); + return !ground.isPassable(); + } + +}