2022-07-22 21:36:43 +02:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sun, 5 Sep 2021 12:15:59 -0400
Subject: [PATCH] More Teleport API
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
2024-10-31 17:25:52 +01:00
index bc8f9bd50de3894e6262e13ed55252c98f22ed8a..10f7e45f192ef50b9d9bf5fc83a8090efb2b1042 100644
2022-07-22 21:36:43 +02:00
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
2024-10-31 17:25:52 +01:00
@@ -1585,11 +1585,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
2024-06-15 18:28:18 +02:00
return true; // CraftBukkit - Return event status
2022-07-22 21:36:43 +02:00
}
- PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), cause);
+ // Paper start - Teleport API
2024-10-31 17:25:52 +01:00
+ final Set<io.papermc.paper.entity.TeleportFlag.Relative> relativeFlags = java.util.EnumSet.noneOf(io.papermc.paper.entity.TeleportFlag.Relative.class);
+ for (final Relative relativeArgument : set) {
+ final io.papermc.paper.entity.TeleportFlag.Relative flag = org.bukkit.craftbukkit.entity.CraftPlayer.deltaRelativeToAPI(relativeArgument);
+ if (flag != null) relativeFlags.add(flag);
2022-07-22 21:36:43 +02:00
+ }
2023-03-15 00:10:18 +01:00
+ PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), cause, java.util.Set.copyOf(relativeFlags));
2024-01-18 15:56:25 +01:00
+ // Paper end - Teleport API
2022-07-22 21:36:43 +02:00
this.cserver.getPluginManager().callEvent(event);
if (event.isCancelled() || !to.equals(event.getTo())) {
2024-08-17 21:39:11 +02:00
- set = Collections.emptySet(); // Can't relative teleport
+ // set = Collections.emptySet(); // Can't relative teleport // Paper - Teleport API; Now you can!
2022-07-22 21:36:43 +02:00
to = event.isCancelled() ? event.getFrom() : event.getTo();
2024-10-23 23:12:09 +02:00
positionmoverotation = new PositionMoveRotation(CraftLocation.toVec3D(to), Vec3.ZERO, to.getYaw(), to.getPitch());
}
2022-07-22 21:36:43 +02:00
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
2024-10-25 21:24:15 +02:00
index 4e6afa243d6108cb946a8a7cf96c4036a3c2ac0c..a314e401ee8a306dc12a2d98a3d400ae611a6e5a 100644
2022-07-22 21:36:43 +02:00
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
2024-10-23 23:12:09 +02:00
@@ -222,15 +222,36 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
2022-07-22 21:36:43 +02:00
@Override
public boolean teleport(Location location, TeleportCause cause) {
+ // Paper start - Teleport passenger API
2023-03-04 23:07:23 +01:00
+ return teleport(location, cause, new io.papermc.paper.entity.TeleportFlag[0]);
2022-07-22 21:36:43 +02:00
+ }
+
+ @Override
2023-03-04 23:07:23 +01:00
+ public boolean teleport(Location location, TeleportCause cause, io.papermc.paper.entity.TeleportFlag... flags) {
2022-07-22 21:36:43 +02:00
+ // Paper end
Preconditions.checkArgument(location != null, "location cannot be null");
location.checkFinite();
+ // Paper start - Teleport passenger API
2023-03-04 23:07:23 +01:00
+ Set<io.papermc.paper.entity.TeleportFlag> flagSet = Set.of(flags);
+ boolean dismount = !flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_VEHICLE);
+ boolean ignorePassengers = flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS);
2022-07-22 21:36:43 +02:00
+ // Don't allow teleporting between worlds while keeping passengers
2023-03-04 23:07:23 +01:00
+ if (flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS) && this.entity.isVehicle() && location.getWorld() != this.getWorld()) {
2022-07-22 21:36:43 +02:00
+ return false;
+ }
2023-03-23 22:57:03 +01:00
+
2022-07-22 21:36:43 +02:00
+ // Don't allow to teleport between worlds if remaining on vehicle
+ if (!dismount && this.entity.isPassenger() && location.getWorld() != this.getWorld()) {
+ return false;
+ }
+ // Paper end
2023-03-23 22:57:03 +01:00
- if (this.entity.isVehicle() || this.entity.isRemoved()) {
2022-07-22 21:36:43 +02:00
+ if ((!ignorePassengers && this.entity.isVehicle()) || this.entity.isRemoved()) { // Paper - Teleport passenger API
return false;
}
// If this entity is riding another entity, we must dismount before teleporting.
- this.entity.stopRiding();
+ if (dismount) this.entity.stopRiding(); // Paper - Teleport passenger API
// Let the server handle cross world teleports
if (location.getWorld() != null && !location.getWorld().equals(this.getWorld())) {
2024-10-23 23:12:09 +02:00
@@ -976,6 +997,39 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
2024-04-06 22:38:37 +02:00
return CraftEntity.perm;
}
+ // Paper start - more teleport API / async chunk API
+ @Override
+ public java.util.concurrent.CompletableFuture<Boolean> teleportAsync(final Location location, final TeleportCause cause, final io.papermc.paper.entity.TeleportFlag... teleportFlags) {
+ Preconditions.checkArgument(location != null, "location");
+ location.checkFinite();
+ Location locationClone = location.clone(); // clone so we don't need to worry about mutations after this call.
+
+ net.minecraft.server.level.ServerLevel world = ((CraftWorld)locationClone.getWorld()).getHandle();
+ java.util.concurrent.CompletableFuture<Boolean> ret = new java.util.concurrent.CompletableFuture<>();
+
+ world.loadChunksForMoveAsync(getHandle().getBoundingBoxAt(locationClone.getX(), locationClone.getY(), locationClone.getZ()),
2024-10-25 21:24:15 +02:00
+ this instanceof CraftPlayer ? ca.spottedleaf.concurrentutil.util.Priority.HIGHER : ca.spottedleaf.concurrentutil.util.Priority.NORMAL, (list) -> {
2024-04-06 22:38:37 +02:00
+ net.minecraft.server.level.ServerChunkCache chunkProviderServer = world.getChunkSource();
+ for (net.minecraft.world.level.chunk.ChunkAccess chunk : list) {
+ chunkProviderServer.addTicketAtLevel(net.minecraft.server.level.TicketType.POST_TELEPORT, chunk.getPos(), 33, CraftEntity.this.getEntityId());
+ }
+ net.minecraft.server.MinecraftServer.getServer().scheduleOnMain(() -> {
+ try {
+ ret.complete(CraftEntity.this.teleport(locationClone, cause, teleportFlags) ? Boolean.TRUE : Boolean.FALSE);
+ } catch (Throwable throwable) {
+ if (throwable instanceof ThreadDeath) {
+ throw (ThreadDeath)throwable;
+ }
+ net.minecraft.server.MinecraftServer.LOGGER.error("Failed to teleport entity " + CraftEntity.this, throwable);
+ ret.completeExceptionally(throwable);
+ }
+ });
+ });
+
+ return ret;
+ }
+ // Paper end - more teleport API / async chunk API
+
// Spigot start
private final org.bukkit.entity.Entity.Spigot spigot = new org.bukkit.entity.Entity.Spigot()
{
2022-07-22 21:36:43 +02:00
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
2024-10-31 17:25:52 +01:00
index fe0c355f8203c9bfa30d2ec48392a5a1a3d616ae..59a95187d04d3f1578e05a7f9d18f617eac95278 100644
2022-07-22 21:36:43 +02:00
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
2024-10-31 17:25:52 +01:00
@@ -1303,13 +1303,94 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
2022-07-22 21:36:43 +02:00
@Override
public void setRotation(float yaw, float pitch) {
- throw new UnsupportedOperationException("Cannot set rotation of players. Consider teleporting instead.");
+ // Paper start - Teleport API
2024-10-28 17:14:00 +01:00
+ if (this.getHandle().connection == null) return;
+ this.getHandle().forceSetRotation(yaw, pitch);
+ // Paper end - Teleportation API
2022-07-22 21:36:43 +02:00
}
@Override
public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) {
+ // Paper start - Teleport API
2023-03-04 23:07:23 +01:00
+ return this.teleport(location, cause, new io.papermc.paper.entity.TeleportFlag[0]);
2022-07-22 21:36:43 +02:00
+ }
+
+ @Override
+ public void lookAt(@NotNull org.bukkit.entity.Entity entity, @NotNull io.papermc.paper.entity.LookAnchor playerAnchor, @NotNull io.papermc.paper.entity.LookAnchor entityAnchor) {
+ this.getHandle().lookAt(toNmsAnchor(playerAnchor), ((CraftEntity) entity).getHandle(), toNmsAnchor(entityAnchor));
+ }
+
+ @Override
+ public void lookAt(double x, double y, double z, @NotNull io.papermc.paper.entity.LookAnchor playerAnchor) {
2024-06-14 14:11:52 +02:00
+ this.getHandle().lookAt(toNmsAnchor(playerAnchor), new net.minecraft.world.phys.Vec3(x, y, z));
2022-07-22 21:36:43 +02:00
+ }
+
+ public static net.minecraft.commands.arguments.EntityAnchorArgument.Anchor toNmsAnchor(io.papermc.paper.entity.LookAnchor nmsAnchor) {
+ return switch (nmsAnchor) {
+ case EYES -> net.minecraft.commands.arguments.EntityAnchorArgument.Anchor.EYES;
+ case FEET -> net.minecraft.commands.arguments.EntityAnchorArgument.Anchor.FEET;
+ };
+ }
+
+ public static io.papermc.paper.entity.LookAnchor toApiAnchor(net.minecraft.commands.arguments.EntityAnchorArgument.Anchor playerAnchor) {
+ return switch (playerAnchor) {
+ case EYES -> io.papermc.paper.entity.LookAnchor.EYES;
+ case FEET -> io.papermc.paper.entity.LookAnchor.FEET;
+ };
+ }
+
2024-10-31 17:25:52 +01:00
+ public static net.minecraft.world.entity.Relative deltaRelativeToNMS(io.papermc.paper.entity.TeleportFlag.Relative apiFlag) {
2022-07-22 21:36:43 +02:00
+ return switch (apiFlag) {
2024-10-31 17:25:52 +01:00
+ case VELOCITY_X -> net.minecraft.world.entity.Relative.DELTA_X;
+ case VELOCITY_Y -> net.minecraft.world.entity.Relative.DELTA_Y;
+ case VELOCITY_Z -> net.minecraft.world.entity.Relative.DELTA_Z;
+ case VELOCITY_ROTATION -> net.minecraft.world.entity.Relative.ROTATE_DELTA;
2022-07-22 21:36:43 +02:00
+ };
+ }
+
2024-10-31 17:25:52 +01:00
+ public static @org.jetbrains.annotations.Nullable io.papermc.paper.entity.TeleportFlag.Relative deltaRelativeToAPI(net.minecraft.world.entity.Relative nmsFlag) {
2022-07-22 21:36:43 +02:00
+ return switch (nmsFlag) {
2024-10-31 17:25:52 +01:00
+ case DELTA_X -> io.papermc.paper.entity.TeleportFlag.Relative.VELOCITY_X;
+ case DELTA_Y -> io.papermc.paper.entity.TeleportFlag.Relative.VELOCITY_Y;
+ case DELTA_Z -> io.papermc.paper.entity.TeleportFlag.Relative.VELOCITY_Z;
+ case ROTATE_DELTA -> io.papermc.paper.entity.TeleportFlag.Relative.VELOCITY_ROTATION;
+ default -> null;
2022-07-22 21:36:43 +02:00
+ };
+ }
+
+ @Override
2023-03-04 23:07:23 +01:00
+ public boolean teleport(Location location, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause, io.papermc.paper.entity.TeleportFlag... flags) {
2024-01-02 20:42:26 +01:00
+ Set<io.papermc.paper.entity.TeleportFlag.Relative> relativeArguments;
+ Set<io.papermc.paper.entity.TeleportFlag> allFlags;
2023-03-04 23:07:23 +01:00
+ if (flags.length == 0) {
+ relativeArguments = Set.of();
+ allFlags = Set.of();
+ } else {
2024-01-02 20:42:26 +01:00
+ relativeArguments = java.util.EnumSet.noneOf(io.papermc.paper.entity.TeleportFlag.Relative.class);
2023-03-04 23:07:23 +01:00
+ allFlags = new HashSet<>();
+ for (io.papermc.paper.entity.TeleportFlag flag : flags) {
2024-01-02 20:42:26 +01:00
+ if (flag instanceof final io.papermc.paper.entity.TeleportFlag.Relative relativeTeleportFlag) {
+ relativeArguments.add(relativeTeleportFlag);
2023-03-04 23:07:23 +01:00
+ }
+ allFlags.add(flag);
+ }
2022-07-22 21:36:43 +02:00
+ }
2023-03-04 23:07:23 +01:00
+ boolean dismount = !allFlags.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_VEHICLE);
+ boolean ignorePassengers = allFlags.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS);
2022-07-22 21:36:43 +02:00
+ // Paper end - Teleport API
Preconditions.checkArgument(location != null, "location");
Preconditions.checkArgument(location.getWorld() != null, "location.world");
+ // Paper start - Teleport passenger API
+ // Don't allow teleporting between worlds while keeping passengers
+ if (ignorePassengers && entity.isVehicle() && location.getWorld() != this.getWorld()) {
+ return false;
+ }
+
+ // Don't allow to teleport between worlds if remaining on vehicle
+ if (!dismount && entity.isPassenger() && location.getWorld() != this.getWorld()) {
+ return false;
+ }
+ // Paper end
location.checkFinite();
ServerPlayer entity = this.getHandle();
2024-10-31 17:25:52 +01:00
@@ -1322,7 +1403,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
Updated Upstream (Bukkit/CraftBukkit) (#10034)
Upstream has released updates that appear to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing
Bukkit Changes:
f29cb801 Separate checkstyle-suppressions file is not required
86f99bbe SPIGOT-7540, PR-946: Add ServerTickManager API
d4119585 SPIGOT-6903, PR-945: Add BlockData#getMapColor
b7a2ed41 SPIGOT-7530, PR-947: Add Player#removeResourcePack
9dd56255 SPIGOT-7527, PR-944: Add WindCharge#explode()
994a6163 Attempt upgrade of resolver libraries
CraftBukkit Changes:
b3b43a6ad Add Checkstyle check for unused imports
13fb3358e SPIGOT-7544: Scoreboard#getEntries() doesn't get entries but class names
3dda99c06 SPIGOT-7540, PR-1312: Add ServerTickManager API
2ab4508c0 SPIGOT-6903, PR-1311: Add BlockData#getMapColor
1dbdbbed4 PR-1238: Remove unnecessary sign ticking
659728d2a MC-264285, SPIGOT-7439, PR-1237: Fix unbreakable flint and steel is completely consumed while igniting creeper
e37e29ce0 Increase outdated build delay
c00438b39 SPIGOT-7530, PR-1313: Add Player#removeResourcePack
492dd80ce SPIGOT-7527, PR-1310: Add WindCharge#explode()
e11fbb9d7 Upgrade MySQL driver
9f3a0bd2a Attempt upgrade of resolver libraries
60d16d7ca PR-1306: Centralize Bukkit and Minecraft entity conversion
Spigot Changes:
06d602e7 Rebuild patches
2023-12-17 03:09:28 +01:00
return false;
2022-07-22 21:36:43 +02:00
}
- if (entity.isVehicle()) {
+ if (entity.isVehicle() && !ignorePassengers) { // Paper - Teleport API
return false;
}
2024-10-31 17:25:52 +01:00
@@ -1331,7 +1412,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
2024-01-02 20:42:26 +01:00
// To = Players new Location if Teleport is Successful
Location to = location;
// Create & Call the Teleport Event.
- PlayerTeleportEvent event = new PlayerTeleportEvent(this, from, to, cause);
+ PlayerTeleportEvent event = new PlayerTeleportEvent(this, from, to, cause, Set.copyOf(relativeArguments)); // Paper - Teleport API
this.server.getPluginManager().callEvent(event);
// Return False to inform the Plugin that the Teleport was unsuccessful/cancelled.
2024-10-31 17:25:52 +01:00
@@ -1340,7 +1421,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
2022-07-22 21:36:43 +02:00
}
// If this player is riding another entity, we must dismount before teleporting.
- entity.stopRiding();
+ if (dismount) entity.stopRiding(); // Paper - Teleport API
// SPIGOT-5509: Wakeup, similar to riding
if (this.isSleeping()) {
2024-10-31 17:25:52 +01:00
@@ -1356,13 +1437,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
2023-03-04 23:07:23 +01:00
ServerLevel toWorld = ((CraftWorld) to.getWorld()).getHandle();
// Close any foreign inventory
- if (this.getHandle().containerMenu != this.getHandle().inventoryMenu) {
+ if (this.getHandle().containerMenu != this.getHandle().inventoryMenu && !allFlags.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_OPEN_INVENTORY)) { // Paper
2024-01-21 19:37:09 +01:00
this.getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); // Paper - Inventory close reason
2023-03-04 23:07:23 +01:00
}
2022-07-22 21:36:43 +02:00
// Check if the fromWorld and toWorld are the same.
if (fromWorld == toWorld) {
- entity.connection.teleport(to);
2024-01-02 20:42:26 +01:00
+ // Paper start - Teleport API
2024-10-25 12:30:19 +02:00
+ final Set<net.minecraft.world.entity.Relative> nms = java.util.EnumSet.noneOf(net.minecraft.world.entity.Relative.class);
2024-01-02 20:42:26 +01:00
+ for (final io.papermc.paper.entity.TeleportFlag.Relative bukkit : relativeArguments) {
2024-10-31 17:25:52 +01:00
+ nms.add(deltaRelativeToNMS(bukkit));
2024-01-02 20:42:26 +01:00
+ }
2024-10-25 18:08:28 +02:00
+ entity.connection.internalTeleport(new net.minecraft.world.entity.PositionMoveRotation(
+ io.papermc.paper.util.MCUtil.toVec3(to), net.minecraft.world.phys.Vec3.ZERO, to.getYaw(), to.getPitch()
+ ), nms);
2024-01-02 20:42:26 +01:00
+ // Paper end - Teleport API
2022-07-22 21:36:43 +02:00
} else {
2024-07-06 21:19:14 +02:00
entity.portalProcess = null; // SPIGOT-7785: there is no need to carry this over as it contains the old world/location and we might run into trouble if there is a portal in the same spot in both worlds
2023-04-10 10:03:36 +02:00
// The respawn reason should never be used if the passed location is non null.