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 'org.bstats:bstats-bukkit:2.2.1'
relocatedApi 'net.minidev:json-smart:2.4.8' relocatedApi 'net.minidev:json-smart:2.4.8'
relocatedApi 'org.jetbrains:annotations:22.0.0' relocatedApi 'org.jetbrains:annotations:22.0.0'
relocatedApi 'io.papermc:paperlib:1.0.8'
// Tests // Tests
testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10' testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10'
@ -260,6 +261,7 @@ shadowJar {
relocate 'org.jvnet', 'com.onarandombox.jvnet' relocate 'org.jvnet', 'com.onarandombox.jvnet'
relocate 'org.intellij', 'com.onarandombox.intellij' relocate 'org.intellij', 'com.onarandombox.intellij'
relocate 'org.jetbrains', 'com.onarandombox.jetbrains' relocate 'org.jetbrains', 'com.onarandombox.jetbrains'
relocate 'io.papermc.lib', 'com.onarandombox.paperlib'
configurations = [project.configurations.api, project.configurations.relocatedApi] configurations = [project.configurations.api, project.configurations.relocatedApi]

View File

@ -1,5 +1,7 @@
package com.onarandombox.MultiverseCore.api; package com.onarandombox.MultiverseCore.api;
import java.util.concurrent.CompletableFuture;
import co.aikar.commands.BukkitCommandIssuer; import co.aikar.commands.BukkitCommandIssuer;
import com.onarandombox.MultiverseCore.destination.ParsedDestination; import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.teleportation.TeleportResult; import com.onarandombox.MultiverseCore.teleportation.TeleportResult;
@ -39,8 +41,20 @@ public interface SafeTTeleporter extends Teleporter {
* @param destination Destination to teleport them to * @param destination Destination to teleport them to
* @return true for success, false for failure * @return true for success, false for failure
*/ */
@Deprecated
TeleportResult safelyTeleport(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination); 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 * Safely teleport the entity to the Location. This may perform checks to
* see if the place is safe, and if * 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}. * @return The next portal-block's {@link Location}.
*/ */
Location findPortalBlockNextTo(Location l); Location findPortalBlockNextTo(Location l);
} }

View File

@ -1,5 +1,7 @@
package com.onarandombox.MultiverseCore.api; package com.onarandombox.MultiverseCore.api;
import java.util.concurrent.CompletableFuture;
import co.aikar.commands.BukkitCommandIssuer; import co.aikar.commands.BukkitCommandIssuer;
import com.onarandombox.MultiverseCore.destination.ParsedDestination; import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import com.onarandombox.MultiverseCore.teleportation.TeleportResult; import com.onarandombox.MultiverseCore.teleportation.TeleportResult;
@ -16,5 +18,16 @@ public interface Teleporter {
* @param destination Destination to teleport them to * @param destination Destination to teleport them to
* @return true for success, false for failure * @return true for success, false for failure
*/ */
@Deprecated
TeleportResult teleport(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination); 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; package com.onarandombox.MultiverseCore.commands;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import co.aikar.commands.BukkitCommandIssuer; import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.CommandIssuer; import co.aikar.commands.CommandIssuer;
import co.aikar.commands.annotation.CommandAlias; import co.aikar.commands.annotation.CommandAlias;
@ -45,12 +48,18 @@ public class TeleportCommand extends MultiverseCommand {
ParsedDestination<?> destination ParsedDestination<?> destination
) { ) {
// TODO Add warning if teleporting too many players at once. // TODO Add warning if teleporting too many players at once.
for (Player player : players) {
issuer.sendInfo(MVCorei18n.TELEPORT_SUCCESS, CompletableFuture.allOf(Arrays.stream(players)
"{player}", issuer.getPlayer() == player ? "you" : player.getName(), .map(player -> this.destinationsProvider.playerTeleportAsync(issuer, player, destination))
"{destination}", destination.toString()); .toArray(CompletableFuture[]::new))
this.destinationsProvider.playerTeleport(issuer, player, destination); .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 @Override

View File

@ -3,6 +3,7 @@ package com.onarandombox.MultiverseCore.destination;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import co.aikar.commands.BukkitCommandIssuer; 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.DestinationInstance;
import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
import com.onarandombox.MultiverseCore.api.Teleporter; import com.onarandombox.MultiverseCore.api.Teleporter;
import com.onarandombox.MultiverseCore.teleportation.TeleportResult;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -128,14 +130,14 @@ public class DestinationsProvider {
* @param teleportee The teleportee. * @param teleportee The teleportee.
* @param destination The destination. * @param destination The destination.
*/ */
public void playerTeleport(@NotNull BukkitCommandIssuer teleporter, public CompletableFuture<TeleportResult> playerTeleportAsync(@NotNull BukkitCommandIssuer teleporter,
@NotNull Player teleportee, @NotNull Player teleportee,
@NotNull ParsedDestination<?> destination @NotNull ParsedDestination<?> destination
) { ) {
if (!checkTeleportPermissions(teleporter, teleportee, 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 teleportee The teleportee.
* @param destination The destination. * @param destination The destination.
*/ */
public void teleport(@NotNull BukkitCommandIssuer teleporter, public CompletableFuture<TeleportResult> teleportAsync(@NotNull BukkitCommandIssuer teleporter,
@NotNull Entity teleportee, @NotNull Entity teleportee,
@NotNull ParsedDestination<?> destination @NotNull ParsedDestination<?> destination
) { ) {
Teleporter teleportHandler = destination.getDestination().getTeleporter(); Teleporter teleportHandler = destination.getDestination().getTeleporter();
if (teleportHandler == null) { if (teleportHandler == null) {
teleportHandler = safeTTeleporter; teleportHandler = safeTTeleporter;
} }
teleportHandler.teleport(teleporter, teleportee, destination); return teleportHandler.teleportAsync(teleporter, teleportee, destination);
} }
/** /**

View File

@ -7,6 +7,8 @@
package com.onarandombox.MultiverseCore.teleportation; package com.onarandombox.MultiverseCore.teleportation;
import java.util.concurrent.CompletableFuture;
import co.aikar.commands.BukkitCommandIssuer; import co.aikar.commands.BukkitCommandIssuer;
import com.dumptruckman.minecraft.util.Logging; import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore; 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.LocationManipulation;
import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
import com.onarandombox.MultiverseCore.destination.ParsedDestination; import com.onarandombox.MultiverseCore.destination.ParsedDestination;
import io.papermc.lib.PaperLib;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
@ -207,9 +210,14 @@ public class SimpleSafeTTeleporter implements SafeTTeleporter {
*/ */
@Override @Override
public TeleportResult safelyTeleport(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination) { 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) { if (destination == null) {
Logging.finer("Entity tried to teleport to an invalid destination"); Logging.finer("Entity tried to teleport to an invalid destination");
return TeleportResult.FAIL_INVALID; return CompletableFuture.completedFuture(TeleportResult.FAIL_INVALID);
} }
Player teleporteePlayer = null; Player teleporteePlayer = null;
@ -220,7 +228,7 @@ public class SimpleSafeTTeleporter implements SafeTTeleporter {
} }
if (teleporteePlayer == null) { if (teleporteePlayer == null) {
return TeleportResult.FAIL_INVALID; return CompletableFuture.completedFuture(TeleportResult.FAIL_INVALID);
} }
teleportQueue.addToQueue(teleporter.getIssuer().getName(), teleporteePlayer.getName()); teleportQueue.addToQueue(teleporter.getIssuer().getName(), teleporteePlayer.getName());
@ -231,20 +239,26 @@ public class SimpleSafeTTeleporter implements SafeTTeleporter {
} }
if (safeLoc == null) { if (safeLoc == null) {
return TeleportResult.FAIL_UNSAFE; return CompletableFuture.completedFuture(TeleportResult.FAIL_UNSAFE);
} }
if (!teleportee.teleport(safeLoc)) { CompletableFuture<TeleportResult> future = new CompletableFuture<>();
return TeleportResult.FAIL_OTHER;
}
Vector v = destination.getDestinationInstance().getVelocity(teleportee); PaperLib.teleportAsync(teleportee, safeLoc).thenAccept(result -> {
if (v != null && !DEFAULT_VECTOR.equals(v)) { if (!result) {
Bukkit.getScheduler().runTaskLater(this.plugin, () -> { future.complete(TeleportResult.FAIL_OTHER);
teleportee.setVelocity(v); return;
}, 1); }
} Vector v = destination.getDestinationInstance().getVelocity(teleportee);
return TeleportResult.SUCCESS; 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 @Override
public TeleportResult teleport(BukkitCommandIssuer teleporter, Entity teleportee, ParsedDestination<?> destination) { 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);
} }
} }