Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,14 @@ public void execute(ByteArrayDataInput dataInput) {
Float pitch = Optional.of(dataInput.readUTF()).filter(str -> !str.equals("null")).map(Float::parseFloat).orElse(null);
String worldName = Optional.of(dataInput.readUTF()).filter(str -> !str.equals("null")).orElse(null);
String originServerName = dataInput.readUTF();

this.teleportationHandler.handle(new PendingTpLocation(playerUUID, x, y, z, yaw, pitch, worldName, originServerName, this.plugin));
boolean prepareRegion = false;
try {
prepareRegion = Boolean.parseBoolean(dataInput.readUTF());
} catch (IllegalStateException ignored) {
// Older Velocity messages do not include the optional preparation flag.
}

this.teleportationHandler.handle(new PendingTpLocation(playerUUID, x, y, z, yaw, pitch, worldName, originServerName, prepareRegion, this.plugin));
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,22 @@ public class PendingTpLocation extends PendingTeleportationAbstract {
private final Float yaw;
private final Float pitch;
private final String worldName;
private final boolean prepareRegion;
private final TeleportationBukkit plugin;

public PendingTpLocation(UUID playerUUID, double x, double y, double z, Float yaw, Float pitch, String worldName, String originServerName, TeleportationBukkit plugin) {
this(playerUUID, x, y, z, yaw, pitch, worldName, originServerName, false, plugin);
}

public PendingTpLocation(UUID playerUUID, double x, double y, double z, Float yaw, Float pitch, String worldName, String originServerName, boolean prepareRegion, TeleportationBukkit plugin) {
super(playerUUID, originServerName);
this.x = x;
this.y = y;
this.z = z;
this.yaw = yaw;
this.pitch = pitch;
this.worldName = worldName;
this.prepareRegion = prepareRegion;
this.plugin = plugin;
}

Expand All @@ -38,11 +44,41 @@ public boolean canTeleport() {

@Override
public void teleport() {
Bukkit.getScheduler().runTask(this.plugin, () -> {
Player player = Bukkit.getPlayer(this.playerUUID);
if (player == null || !player.isOnline()) {
return;
}

World world = (worldName == null) ? player.getWorld() : Bukkit.getWorld(worldName);
if (world == null) {
world = Bukkit.getWorld("world");
}
if (world == null) {
player.sendMessage(TeleportationBukkit.getFormattedErrorMessage("Target world not found."));
return;
}

World targetWorld = world;
if (!this.prepareRegion) {
this.teleportPrepared(targetWorld);
return;
}

TerraplusminusRegionPreparer.prepare(this.plugin, player, targetWorld, x, z)
.thenAccept(prepared -> {
if (!Boolean.TRUE.equals(prepared)) {
return;
}
Bukkit.getScheduler().runTask(this.plugin, () -> this.teleportPrepared(targetWorld));
});
});
}

private void teleportPrepared(World world) {
Player player = Bukkit.getPlayer(this.playerUUID);
assert player != null; // canTeleport() checked
World world = (worldName == null) ? player.getWorld() : Bukkit.getWorld(worldName);
if (world == null) {
world = Bukkit.getWorld("world");
if (player == null || !player.isOnline()) {
return;
}

double yWorld = y;
Expand All @@ -53,7 +89,7 @@ public void teleport() {
location.setYaw(yaw != null ? yaw : player.getLocation().getYaw());
location.setPitch(pitch != null ? pitch : player.getLocation().getPitch());

Bukkit.getScheduler().runTask(this.plugin, () -> player.teleport(location));
player.teleport(location);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package de.btegermany.teleportation.TeleportationBukkit.tp;

import de.btegermany.teleportation.TeleportationBukkit.TeleportationBukkit;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

final class TerraplusminusRegionPreparer {

private static final String PLUGIN_NAME = "Terraplusminus";
private static final int TELEPORT_PREP_RADIUS_CHUNKS = 16;

private TerraplusminusRegionPreparer() {
}

static CompletableFuture<Boolean> prepare(TeleportationBukkit owner, Player player, World world, double x, double z) {
Plugin terraplusminus = Bukkit.getPluginManager().getPlugin(PLUGIN_NAME);
if (terraplusminus == null || !terraplusminus.isEnabled()) {
return CompletableFuture.completedFuture(true);
}

try {
Method isTeleportRegionGenerated = terraplusminus.getClass().getMethod(
"isTeleportRegionGenerated",
World.class,
double.class,
double.class,
int.class
);
boolean alreadyGenerated = (boolean) isTeleportRegionGenerated.invoke(
terraplusminus,
world,
x,
z,
TELEPORT_PREP_RADIUS_CHUNKS
);
if (alreadyGenerated) {
return CompletableFuture.completedFuture(true);
}

player.sendMessage(TeleportationBukkit.getFormattedMessage("Die Zielregion wird gerade generiert. Du wirst teleportiert, sobald sie bereit ist."));
Method primeTeleportRegionCache = terraplusminus.getClass().getMethod(
"primeTeleportRegionCache",
World.class,
double.class,
double.class,
int.class
);
Object result = primeTeleportRegionCache.invoke(
terraplusminus,
world,
x,
z,
TELEPORT_PREP_RADIUS_CHUNKS
);

if (!(result instanceof CompletionStage<?> completionStage)) {
owner.getLogger().warning("Terraplusminus primeTeleportRegionCache did not return a CompletionStage.");
return CompletableFuture.completedFuture(false);
}

return completionStage
.thenApply(ignored -> true)
.exceptionally(ex -> {
owner.getLogger().warning("Terraplusminus failed to prepare the target teleport region: " + ex.getMessage());
Bukkit.getScheduler().runTask(owner, () ->
player.sendMessage(TeleportationBukkit.getFormattedErrorMessage("Die Zielregion konnte nicht generiert werden. Bitte versuche es spaeter erneut.")));
return false;
})
.toCompletableFuture();
} catch (NoSuchMethodException e) {
owner.getLogger().fine("Terraplusminus is installed without teleport region preparation API; continuing without cache priming.");
return CompletableFuture.completedFuture(true);
} catch (IllegalAccessException | InvocationTargetException | ClassCastException e) {
owner.getLogger().warning("Could not call Terraplusminus teleport region preparation API: " + e.getMessage());
Bukkit.getScheduler().runTask(owner, () ->
player.sendMessage(TeleportationBukkit.getFormattedErrorMessage("Die Zielregion konnte nicht generiert werden. Bitte versuche es spaeter erneut.")));
return CompletableFuture.completedFuture(false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public void execute(Invocation invocation) {
// send teleport data and the player to the target server
RequestLastLocationMessage requestLastLocationMessage = new RequestLastLocationMessage(player, this.registriesProvider, () -> {
sendMessage(player, Component.text("Teleporting to " + coordinates.getLat() + ", " + coordinates.getLng() + ".", NamedTextColor.GOLD));
this.pluginMessenger.teleportToCoords(player, targetServer, mcCoordinatesFinal[0], mcCoordinatesY, mcCoordinatesFinal[1], yawFinal, pitchFinal, worldFinal);
this.pluginMessenger.teleportToCoords(player, targetServer, mcCoordinatesFinal[0], mcCoordinatesY, mcCoordinatesFinal[1], yawFinal, pitchFinal, worldFinal, true);
});
if (player.getCurrentServer().isEmpty()) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ public void teleportToCoords(Player player, RegisteredServer server, double x, d
this.sendAndConnect(player, server, new TeleportToCoordsMessage(player, x, y, z, yaw, pitch, world));
}

// teleports a player to the specified coordinates after the backend prepared the target region if supported
public void teleportToCoords(Player player, RegisteredServer server, double x, double y, double z, Float yaw, Float pitch, String world, boolean prepareRegion) {
this.sendAndConnect(player, server, new TeleportToCoordsMessage(player, x, y, z, yaw, pitch, world, prepareRegion));
}

// teleports a player to the normen world on the specified server
public void teleportToNormen(Player player, RegisteredServer server, String normenWorld, float yaw, float pitch) {
this.sendAndConnect(player, server, new TeleportToNormenMessage(player, normenWorld, yaw, pitch));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
public class TeleportToCoordsMessage extends PluginMessage {

public TeleportToCoordsMessage(Player player, double x, double y, double z, Float yaw, Float pitch, String world) {
this(player, x, y, z, yaw, pitch, world, false);
}

public TeleportToCoordsMessage(Player player, double x, double y, double z, Float yaw, Float pitch, String world, boolean prepareRegion) {
super("teleport_coords", MessageType.NORMAL);
if (player.getCurrentServer().isEmpty()) {
return;
Expand All @@ -20,7 +24,8 @@ public TeleportToCoordsMessage(Player player, double x, double y, double z, Floa
pitch == null ? "null" : pitch.toString(),
// null to use the player's current world
world == null ? "null" : world,
player.getCurrentServer().get().getServerInfo().getName()));
player.getCurrentServer().get().getServerInfo().getName(),
Boolean.toString(prepareRegion)));
}

}