From f76b9b06705701e7c9d2ff95d5ef430de1d44a7d Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Tue, 28 Mar 2023 12:20:30 +0800 Subject: [PATCH] feat: Add support for async teleport --- build.gradle | 2 + .../MultiverseCore/api/SafeTTeleporter.java | 15 +++++- .../MultiverseCore/api/Teleporter.java | 13 +++++ .../commands/TeleportCommand.java | 21 ++++++--- .../destination/DestinationsProvider.java | 18 +++---- .../teleportation/SimpleSafeTTeleporter.java | 47 +++++++++++++------ 6 files changed, 86 insertions(+), 30 deletions(-) diff --git a/build.gradle b/build.gradle index 03f132ca..6bfdbe20 100644 --- a/build.gradle +++ b/build.gradle @@ -105,6 +105,7 @@ dependencies { relocatedApi 'org.bstats:bstats-bukkit:2.2.1' relocatedApi 'net.minidev:json-smart:2.4.8' relocatedApi 'org.jetbrains:annotations:22.0.0' + relocatedApi 'io.papermc:paperlib:1.0.8' // Tests testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10' @@ -259,6 +260,7 @@ shadowJar { relocate 'org.jvnet', 'com.onarandombox.jvnet' relocate 'org.intellij', 'com.onarandombox.intellij' relocate 'org.jetbrains', 'com.onarandombox.jetbrains' + relocate 'io.papermc.lib', 'com.onarandombox.paperlib' configurations = [project.configurations.api, project.configurations.relocatedApi] diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/SafeTTeleporter.java b/src/main/java/com/onarandombox/MultiverseCore/api/SafeTTeleporter.java index 9bbc06b2..51350238 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/api/SafeTTeleporter.java +++ b/src/main/java/com/onarandombox/MultiverseCore/api/SafeTTeleporter.java @@ -1,5 +1,7 @@ package com.onarandombox.MultiverseCore.api; +import java.util.concurrent.CompletableFuture; + import co.aikar.commands.BukkitCommandIssuer; import com.onarandombox.MultiverseCore.destination.ParsedDestination; import com.onarandombox.MultiverseCore.teleportation.TeleportResult; @@ -39,8 +41,20 @@ public interface SafeTTeleporter extends Teleporter { * @param destination Destination to teleport them to * @return true for success, false for failure */ + @Deprecated TeleportResult safelyTeleport(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination destination); + /** + * Safely teleport the entity to the MVDestination. This will perform checks to see if the place is safe, and if + * it's not, will adjust the final destination accordingly. + * + * @param teleporter Person who performed the teleport command. + * @param teleportee Entity to teleport + * @param destination Destination to teleport them to + * @return true for success, false for failure + */ + CompletableFuture safelyTeleportAsync(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination destination); + /** * Safely teleport the entity to the Location. This may perform checks to * see if the place is safe, and if @@ -70,5 +84,4 @@ public interface SafeTTeleporter extends Teleporter { * @return The next portal-block's {@link Location}. */ Location findPortalBlockNextTo(Location l); - } diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/Teleporter.java b/src/main/java/com/onarandombox/MultiverseCore/api/Teleporter.java index 232b74d7..39795957 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/api/Teleporter.java +++ b/src/main/java/com/onarandombox/MultiverseCore/api/Teleporter.java @@ -1,5 +1,7 @@ package com.onarandombox.MultiverseCore.api; +import java.util.concurrent.CompletableFuture; + import co.aikar.commands.BukkitCommandIssuer; import com.onarandombox.MultiverseCore.destination.ParsedDestination; import com.onarandombox.MultiverseCore.teleportation.TeleportResult; @@ -16,5 +18,16 @@ public interface Teleporter { * @param destination Destination to teleport them to * @return true for success, false for failure */ + @Deprecated TeleportResult teleport(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination destination); + + /** + * Teleport the entity to the Multiverse Destination. + * + * @param teleporter Person who performed the teleport command. + * @param teleportee Entity to teleport + * @param destination Destination to teleport them to + * @return true for success, false for failure + */ + CompletableFuture teleportAsync(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination destination); } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/TeleportCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/TeleportCommand.java index 1bafbcb4..cee3b5c5 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/TeleportCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/TeleportCommand.java @@ -1,5 +1,8 @@ package com.onarandombox.MultiverseCore.commands; +import java.util.Arrays; +import java.util.concurrent.CompletableFuture; + import co.aikar.commands.BukkitCommandIssuer; import co.aikar.commands.CommandIssuer; import co.aikar.commands.annotation.CommandAlias; @@ -45,12 +48,18 @@ public class TeleportCommand extends MultiverseCommand { ParsedDestination destination ) { // TODO Add warning if teleporting too many players at once. - for (Player player : players) { - issuer.sendInfo(MVCorei18n.TELEPORT_SUCCESS, - "{player}", issuer.getPlayer() == player ? "you" : player.getName(), - "{destination}", destination.toString()); - this.destinationsProvider.playerTeleport(issuer, player, destination); - } + + CompletableFuture.allOf(Arrays.stream(players) + .map(player -> this.destinationsProvider.playerTeleportAsync(issuer, player, destination)) + .toArray(CompletableFuture[]::new)) + .thenRun(() -> { + String playerName = players.length == 1 + ? issuer.getPlayer() == players[0] ? "you" : players[0].getName() + : players.length + " players"; + + issuer.sendInfo(MVCorei18n.TELEPORT_SUCCESS, + "{player}", playerName, "{destination}", destination.toString()); + }); } @Override diff --git a/src/main/java/com/onarandombox/MultiverseCore/destination/DestinationsProvider.java b/src/main/java/com/onarandombox/MultiverseCore/destination/DestinationsProvider.java index a891247f..416d2300 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/destination/DestinationsProvider.java +++ b/src/main/java/com/onarandombox/MultiverseCore/destination/DestinationsProvider.java @@ -3,17 +3,17 @@ package com.onarandombox.MultiverseCore.destination; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import co.aikar.commands.BukkitCommandIssuer; import co.aikar.commands.CommandIssuer; -import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.Destination; import com.onarandombox.MultiverseCore.api.DestinationInstance; import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import com.onarandombox.MultiverseCore.api.Teleporter; +import com.onarandombox.MultiverseCore.teleportation.TeleportResult; import jakarta.inject.Inject; -import org.bukkit.Server; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.permissions.Permission; @@ -130,14 +130,14 @@ public class DestinationsProvider { * @param teleportee The teleportee. * @param destination The destination. */ - public void playerTeleport(@NotNull BukkitCommandIssuer teleporter, + public CompletableFuture playerTeleportAsync(@NotNull BukkitCommandIssuer teleporter, @NotNull Player teleportee, @NotNull ParsedDestination destination ) { if (!checkTeleportPermissions(teleporter, teleportee, destination)) { - return; + return CompletableFuture.completedFuture(TeleportResult.FAIL_PERMISSION); } - teleport(teleporter, teleportee, destination); + return teleportAsync(teleporter, teleportee, destination); } /** @@ -147,15 +147,15 @@ public class DestinationsProvider { * @param teleportee The teleportee. * @param destination The destination. */ - public void teleport(@NotNull BukkitCommandIssuer teleporter, - @NotNull Entity teleportee, - @NotNull ParsedDestination destination + public CompletableFuture teleportAsync(@NotNull BukkitCommandIssuer teleporter, + @NotNull Entity teleportee, + @NotNull ParsedDestination destination ) { Teleporter teleportHandler = destination.getDestination().getTeleporter(); if (teleportHandler == null) { teleportHandler = safeTTeleporter; } - teleportHandler.teleport(teleporter, teleportee, destination); + return teleportHandler.teleportAsync(teleporter, teleportee, destination); } /** diff --git a/src/main/java/com/onarandombox/MultiverseCore/teleportation/SimpleSafeTTeleporter.java b/src/main/java/com/onarandombox/MultiverseCore/teleportation/SimpleSafeTTeleporter.java index 4b41fb94..4e08ae2f 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/teleportation/SimpleSafeTTeleporter.java +++ b/src/main/java/com/onarandombox/MultiverseCore/teleportation/SimpleSafeTTeleporter.java @@ -7,6 +7,8 @@ package com.onarandombox.MultiverseCore.teleportation; +import java.util.concurrent.CompletableFuture; + import co.aikar.commands.BukkitCommandIssuer; import com.dumptruckman.minecraft.util.Logging; import com.onarandombox.MultiverseCore.MultiverseCore; @@ -15,6 +17,7 @@ import com.onarandombox.MultiverseCore.api.DestinationInstance; import com.onarandombox.MultiverseCore.api.LocationManipulation; import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import com.onarandombox.MultiverseCore.destination.ParsedDestination; +import io.papermc.lib.PaperLib; import jakarta.inject.Inject; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -204,9 +207,14 @@ public class SimpleSafeTTeleporter implements SafeTTeleporter { */ @Override public TeleportResult safelyTeleport(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination destination) { + return safelyTeleportAsync(teleporter, teleportee, destination).join(); + } + + @Override + public CompletableFuture safelyTeleportAsync(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination destination) { if (destination == null) { Logging.finer("Entity tried to teleport to an invalid destination"); - return TeleportResult.FAIL_INVALID; + return CompletableFuture.completedFuture(TeleportResult.FAIL_INVALID); } Player teleporteePlayer = null; @@ -217,7 +225,7 @@ public class SimpleSafeTTeleporter implements SafeTTeleporter { } if (teleporteePlayer == null) { - return TeleportResult.FAIL_INVALID; + return CompletableFuture.completedFuture(TeleportResult.FAIL_INVALID); } MultiverseCore.addPlayerToTeleportQueue(teleporter.getIssuer().getName(), teleporteePlayer.getName()); @@ -228,20 +236,26 @@ public class SimpleSafeTTeleporter implements SafeTTeleporter { } if (safeLoc == null) { - return TeleportResult.FAIL_UNSAFE; + return CompletableFuture.completedFuture(TeleportResult.FAIL_UNSAFE); } - if (!teleportee.teleport(safeLoc)) { - return TeleportResult.FAIL_OTHER; - } + CompletableFuture future = new CompletableFuture<>(); - Vector v = destination.getDestinationInstance().getVelocity(teleportee); - if (v != null && !DEFAULT_VECTOR.equals(v)) { - Bukkit.getScheduler().runTaskLater(this.plugin, () -> { - teleportee.setVelocity(v); - }, 1); - } - return TeleportResult.SUCCESS; + PaperLib.teleportAsync(teleportee, safeLoc).thenAccept(result -> { + if (!result) { + future.complete(TeleportResult.FAIL_OTHER); + return; + } + Vector v = destination.getDestinationInstance().getVelocity(teleportee); + if (v != null && !DEFAULT_VECTOR.equals(v)) { + Bukkit.getScheduler().runTaskLater(this.plugin, () -> { + teleportee.setVelocity(v); + }, 1); + } + future.complete(TeleportResult.SUCCESS); + }); + + return future; } /** @@ -350,6 +364,11 @@ public class SimpleSafeTTeleporter implements SafeTTeleporter { @Override public TeleportResult teleport(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination destination) { - return this.safelyTeleport(teleporter, teleportee, destination); + return safelyTeleport(teleporter, teleportee, destination); + } + + @Override + public CompletableFuture teleportAsync(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination destination) { + return safelyTeleportAsync(teleporter, teleportee, destination); } }