diff --git a/pom.xml b/pom.xml index 83926d4..13f7b38 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ cn.lunadeer EssentialsD - 1.18.0 + 1.18.11 jar EssentialsD diff --git a/src/main/java/cn/lunadeer/essentialsd/Events.java b/src/main/java/cn/lunadeer/essentialsd/Events.java index 3542fc6..4120bd1 100644 --- a/src/main/java/cn/lunadeer/essentialsd/Events.java +++ b/src/main/java/cn/lunadeer/essentialsd/Events.java @@ -5,6 +5,8 @@ import cn.lunadeer.essentialsd.recipes.Crowbar; import cn.lunadeer.essentialsd.recipes.InvisibleGlowItemFrame; import cn.lunadeer.essentialsd.recipes.InvisibleItemFrame; import cn.lunadeer.essentialsd.utils.Notification; +import cn.lunadeer.essentialsd.utils.XLogger; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.block.Block; @@ -16,11 +18,13 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.ExpBottleEvent; +import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.hanging.HangingBreakByEntityEvent; import org.bukkit.event.hanging.HangingPlaceEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; @@ -192,4 +196,11 @@ public class Events implements Listener { } event.setExperience((int) (exp * EssentialsD.config.getExpBottleRatio())); } + + // on player death update tpManager + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerDeath(PlayerDeathEvent event) { + Player player = event.getEntity(); + EssentialsD.tpManager.updateLastTpLocation(player); + } } diff --git a/src/main/java/cn/lunadeer/essentialsd/TeleportManager.java b/src/main/java/cn/lunadeer/essentialsd/TeleportManager.java index 550ef4d..1c38557 100644 --- a/src/main/java/cn/lunadeer/essentialsd/TeleportManager.java +++ b/src/main/java/cn/lunadeer/essentialsd/TeleportManager.java @@ -2,21 +2,26 @@ package cn.lunadeer.essentialsd; import cn.lunadeer.essentialsd.utils.Notification; import cn.lunadeer.essentialsd.utils.STUI.Button; +import cn.lunadeer.essentialsd.utils.XLogger; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.TextColor; +import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerTeleportEvent; import java.time.LocalDateTime; -import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; public class TeleportManager { private static final TextColor main_color = TextColor.color(0, 233, 255); - private final Map _tasks = new java.util.HashMap<>(); - private final Map _next_time_allow_tp = new java.util.HashMap<>(); + private final ConcurrentHashMap _tasks = new ConcurrentHashMap<>(); + private final ConcurrentHashMap _next_time_allow_tp = new ConcurrentHashMap<>(); + private final ConcurrentHashMap _last_tp_location = new ConcurrentHashMap<>(); private static class TpTask { public Player initiator; @@ -102,21 +107,64 @@ public class TeleportManager { return; } Notification.info(task.target, "已接受 " + task.initiator.getName() + " 的传送请求"); - Notification.info(task.initiator, "玩家 " + task.target.getName() + " 已接受你的传送请求,传送将在 " + EssentialsD.config.getTpDelay() + " 秒后进行"); + if (EssentialsD.config.getTpDelay() > 0) { + Notification.info(task.initiator, "玩家 " + task.target.getName() + " 已接受你的传送请求,传送将在 " + EssentialsD.config.getTpDelay() + " 秒后进行"); + } EssentialsD.scheduler.global.runDelayed(EssentialsD.instance, (instance) -> { if (task.initiator.isOnline() && task.target.isOnline()) { - task.initiator.teleportAsync(task.target.getLocation()); + doTeleportSafely(task.initiator, task.target.getLocation()); Notification.info(task.initiator, "已传送到 " + task.target.getName() + " 的位置"); Notification.info(task.target, "玩家 " + task.initiator.getName() + " 已传送到你的位置"); } - }, EssentialsD.config.getTpDelay() == 0 ? 1 : 20L * EssentialsD.config.getTpDelay()); + }, EssentialsD.config.getTpDelay() <= 0 ? 1 : 20L * EssentialsD.config.getTpDelay()); } public void back(Player player) { - // todo: implement back teleport + if (!_last_tp_location.containsKey(player.getUniqueId())) { + Notification.error(player, "没有找到可返回的位置"); + return; + } + if (EssentialsD.config.getTpDelay() > 0) { + Notification.info(player, "将在 " + EssentialsD.config.getTpDelay() + " 秒后返回上次传送的位置"); + } + EssentialsD.scheduler.global.runDelayed(EssentialsD.instance, (instance) -> { + doTeleportSafely(player, _last_tp_location.get(player.getUniqueId())); + Notification.info(player, "已返回上次传送的位置"); + }, EssentialsD.config.getTpDelay() <= 0 ? 1 : 20L * EssentialsD.config.getTpDelay()); } public void rtp(Player player) { - // todo: implement rtp teleport + int radius = EssentialsD.config.getTpRtpRadius(); + World world = player.getWorld(); + int x = (int) (Math.random() * radius * 2) - radius; + int z = (int) (Math.random() * radius * 2) - radius; + XLogger.debug("RTP: " + x + " " + z); + Location location = new Location(world, x, player.getY(), z); + if (EssentialsD.config.getTpDelay() > 0) { + Notification.info(player, "将在 " + EssentialsD.config.getTpDelay() + " 秒后传送到随机位置"); + } + EssentialsD.scheduler.global.runDelayed(EssentialsD.instance, (instance) -> { + doTeleportSafely(player, location); + Notification.info(player, "已传送到随机位置"); + }, EssentialsD.config.getTpDelay() <= 0 ? 1 : 20L * EssentialsD.config.getTpDelay()); + } + + /** + * 把玩家传送到指定位置 并更新上次传送的位置 + * 需要使用 schedule 传送 + * + * @param player 玩家 + * @param location 位置 + */ + private void doTeleportSafely(Player player, Location location) { + location.getWorld().getChunkAtAsyncUrgently(location).thenAccept((chunk) -> { + location.setY(chunk.getWorld().getHighestBlockYAt(location) + 1); + player.teleportAsync(location, PlayerTeleportEvent.TeleportCause.PLUGIN); + _last_tp_location.put(player.getUniqueId(), location); + }); + } + + public void updateLastTpLocation(Player player) { + _last_tp_location.put(player.getUniqueId(), player.getLocation()); } } diff --git a/src/main/java/cn/lunadeer/essentialsd/commands/Back.java b/src/main/java/cn/lunadeer/essentialsd/commands/Back.java index 5174147..a0bbe76 100644 --- a/src/main/java/cn/lunadeer/essentialsd/commands/Back.java +++ b/src/main/java/cn/lunadeer/essentialsd/commands/Back.java @@ -1,6 +1,7 @@ package cn.lunadeer.essentialsd.commands; import cn.lunadeer.essentialsd.EssentialsD; +import cn.lunadeer.essentialsd.TeleportManager; import cn.lunadeer.essentialsd.utils.Notification; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -23,8 +24,7 @@ public class Back implements TabExecutor { return false; } Player player = (Player) sender; - // todo: implement this command - Notification.error(player, "这个命令还没有实现"); + EssentialsD.tpManager.back(player); return true; } diff --git a/src/main/java/cn/lunadeer/essentialsd/commands/Rtp.java b/src/main/java/cn/lunadeer/essentialsd/commands/Rtp.java index 86765ad..3a11476 100644 --- a/src/main/java/cn/lunadeer/essentialsd/commands/Rtp.java +++ b/src/main/java/cn/lunadeer/essentialsd/commands/Rtp.java @@ -23,8 +23,7 @@ public class Rtp implements TabExecutor { return false; } Player player = (Player) sender; - // todo: implement this command - Notification.error(player, "这个命令还没有实现"); + EssentialsD.tpManager.rtp(player); return true; } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 23671b0..357002d 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -2,7 +2,7 @@ ExpBottleRatio: 1.0 # 强加载区块列表 -ForceLoadChunks: +ForceLoadChunks: [] # - world:0:0 # - world_the_end:-12:12 @@ -11,14 +11,14 @@ ForceLoadChunks: # -1 为禁用强加载区块操作 ChunkOperateDelay: 10 -# 特殊合成表 +# 扩展合成表 Recipes: CrowBar: true # 撬棍 InvisibleItemFrame: true # 隐形(发光)物品展示框 LightBlock: true # 光源方块 StackedEnchantBook: true # 附魔书堆叠 -# 特殊指令 +# 扩展指令 Commands: EnderChest: true # 快速末影箱 Suicide: true # 自杀 @@ -36,6 +36,7 @@ Teleport: TpaExpire: 30 # 传送请求有效期 秒 RtpRadius: 1000 # 随机传送最大半径 +# 把楼梯当作椅子使用 Chair: Enable: true MaxWidth: 4