Merge pull request #2898 from Multiverse/async-teleport

feat: Add support for async teleport
This commit is contained in:
Ben Woo 2023-03-30 23:32:37 +08:00 committed by GitHub
commit d9cf933d14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 86 additions and 28 deletions

View File

@ -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'
@ -260,6 +261,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]

View File

@ -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<TeleportResult> 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);
}

View File

@ -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<TeleportResult> teleportAsync(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination);
}

View File

@ -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

View File

@ -3,6 +3,7 @@ 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;
@ -11,6 +12,7 @@ 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.entity.Entity;
import org.bukkit.entity.Player;
@ -128,14 +130,14 @@ public class DestinationsProvider {
* @param teleportee The teleportee.
* @param destination The destination.
*/
public void playerTeleport(@NotNull BukkitCommandIssuer teleporter,
public CompletableFuture<TeleportResult> 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);
}
/**
@ -145,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<TeleportResult> 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);
}
/**

View File

@ -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;
@ -207,9 +210,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<TeleportResult> 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;
@ -220,7 +228,7 @@ public class SimpleSafeTTeleporter implements SafeTTeleporter {
}
if (teleporteePlayer == null) {
return TeleportResult.FAIL_INVALID;
return CompletableFuture.completedFuture(TeleportResult.FAIL_INVALID);
}
teleportQueue.addToQueue(teleporter.getIssuer().getName(), teleporteePlayer.getName());
@ -231,20 +239,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<TeleportResult> 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;
}
/**
@ -353,6 +367,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<TeleportResult> teleportAsync(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination) {
return safelyTeleportAsync(teleporter, teleportee, destination);
}
}