PaperMC/patches/server/0832-More-Teleport-API.patch
Nassim Jahnke 9df2066642
Updated Upstream (Bukkit/CraftBukkit)
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:
dfe1fb48 PR-906: Add missing MinecraftExperimental annotation to Bundles
825ab30d PR-905: Add missing MapCursor.Type and update documentation
e03d10e6 PR-903: Make BARRIER Waterlogged
1961ead6 PR-898: Use Java Consumer instead of Bukkit Consumer

CraftBukkit Changes:
f71a799f0 Make BARRIER Waterlogged
172f76a45 Upgrade specialsource-maven-plugin
f0702775c SPIGOT-7486: Alternate approach to null profile names
069495671 SPIGOT-7485: Allow air entity items since required for Vanilla logic
5dfd33dc2 SPIGOT-7484: Cancelling PlayerEditBookEvent does not update client's book contents
02d490788 PR-1250: Standardize and centralize Bukkit / Minecraft registry conversion
9024a09b9 PR-1251: Use Java Consumer instead of Bukkit Consumer
6d4b25bf1 Increase diff stability
2023-09-23 12:21:59 +10:00

216 lines
12 KiB
Diff

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
== AT ==
public net.minecraft.server.network.ServerGamePacketListenerImpl internalTeleport(DDDFFLjava/util/Set;Z)V
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 85651f43ef7c979d3024f168cb9f42956e544a7d..8014c067396dc595ec456847e05615f8aa794f1e 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1605,11 +1605,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
return false; // CraftBukkit - Return event status
}
- PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), cause);
+ // Paper start - Teleport API
+ Set<io.papermc.paper.entity.TeleportFlag.Relative> relativeFlags = java.util.EnumSet.noneOf(io.papermc.paper.entity.TeleportFlag.Relative.class);
+ for (RelativeMovement relativeArgument : set) {
+ relativeFlags.add(org.bukkit.craftbukkit.entity.CraftPlayer.toApiRelativeFlag(relativeArgument));
+ }
+ PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), cause, java.util.Set.copyOf(relativeFlags));
+ // Paper end
this.cserver.getPluginManager().callEvent(event);
if (event.isCancelled() || !to.equals(event.getTo())) {
- set.clear(); // Can't relative teleport
+ //set.clear(); // Can't relative teleport // Paper - Teleport API: Now you can!
to = event.isCancelled() ? event.getFrom() : event.getTo();
d0 = to.getX();
d1 = to.getY();
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 03142d4eaa3ebdf590ec1131f28690da9c6fe748..863d5a2c6729f8675b03a0575a7eb69ccaf04f4b 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -566,15 +566,36 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
@Override
public boolean teleport(Location location, TeleportCause cause) {
+ // Paper start - Teleport passenger API
+ return teleport(location, cause, new io.papermc.paper.entity.TeleportFlag[0]);
+ }
+
+ @Override
+ public boolean teleport(Location location, TeleportCause cause, io.papermc.paper.entity.TeleportFlag... flags) {
+ // Paper end
Preconditions.checkArgument(location != null, "location cannot be null");
location.checkFinite();
+ // Paper start - Teleport passenger API
+ 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);
+ // Don't allow teleporting between worlds while keeping passengers
+ if (flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS) && this.entity.isVehicle() && location.getWorld() != this.getWorld()) {
+ return false;
+ }
+
+ // Don't allow to teleport between worlds if remaining on vehicle
+ if (!dismount && this.entity.isPassenger() && location.getWorld() != this.getWorld()) {
+ return false;
+ }
+ // Paper end
- if (this.entity.isVehicle() || this.entity.isRemoved()) {
+ 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())) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 16f3381e9cc42c7747199e7c178bd071b798f0e4..842471eb7dd0d68368e551220922b05b26e476e2 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1212,13 +1212,101 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void setRotation(float yaw, float pitch) {
- throw new UnsupportedOperationException("Cannot set rotation of players. Consider teleporting instead.");
+ // Paper start - Teleport API
+ Location targetLocation = this.getEyeLocation();
+ targetLocation.setYaw(yaw);
+ targetLocation.setPitch(pitch);
+
+ org.bukkit.util.Vector direction = targetLocation.getDirection();
+ direction.multiply(9999999); // We need to move the target block.. FAR out
+ targetLocation.add(direction);
+ this.lookAt(targetLocation, io.papermc.paper.entity.LookAnchor.EYES);
+ // Paper end
}
@Override
public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) {
+ // Paper start - Teleport API
+ return this.teleport(location, cause, new io.papermc.paper.entity.TeleportFlag[0]);
+ }
+
+ @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) {
+ this.getHandle().lookAt(toNmsAnchor(playerAnchor), new Vec3(x, y, z));
+ }
+
+ 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;
+ };
+ }
+
+ public static net.minecraft.world.entity.RelativeMovement toNmsRelativeFlag(io.papermc.paper.entity.TeleportFlag.Relative apiFlag) {
+ return switch (apiFlag) {
+ case X -> net.minecraft.world.entity.RelativeMovement.X;
+ case Y -> net.minecraft.world.entity.RelativeMovement.Y;
+ case Z -> net.minecraft.world.entity.RelativeMovement.Z;
+ case PITCH -> net.minecraft.world.entity.RelativeMovement.X_ROT;
+ case YAW -> net.minecraft.world.entity.RelativeMovement.Y_ROT;
+ };
+ }
+
+ public static io.papermc.paper.entity.TeleportFlag.Relative toApiRelativeFlag(net.minecraft.world.entity.RelativeMovement nmsFlag) {
+ return switch (nmsFlag) {
+ case X -> io.papermc.paper.entity.TeleportFlag.Relative.X;
+ case Y -> io.papermc.paper.entity.TeleportFlag.Relative.Y;
+ case Z -> io.papermc.paper.entity.TeleportFlag.Relative.Z;
+ case X_ROT -> io.papermc.paper.entity.TeleportFlag.Relative.PITCH;
+ case Y_ROT -> io.papermc.paper.entity.TeleportFlag.Relative.YAW;
+ };
+ }
+
+ @Override
+ public boolean teleport(Location location, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause, io.papermc.paper.entity.TeleportFlag... flags) {
+ java.util.Set<net.minecraft.world.entity.RelativeMovement> relativeArguments;
+ java.util.Set<io.papermc.paper.entity.TeleportFlag> allFlags;
+ if (flags.length == 0) {
+ relativeArguments = Set.of();
+ allFlags = Set.of();
+ } else {
+ relativeArguments = java.util.EnumSet.noneOf(net.minecraft.world.entity.RelativeMovement.class);
+ allFlags = new HashSet<>();
+ for (io.papermc.paper.entity.TeleportFlag flag : flags) {
+ if (flag instanceof io.papermc.paper.entity.TeleportFlag.Relative relativeTeleportFlag) {
+ relativeArguments.add(toNmsRelativeFlag(relativeTeleportFlag));
+ }
+ allFlags.add(flag);
+ }
+ }
+ boolean dismount = !allFlags.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_VEHICLE);
+ boolean ignorePassengers = allFlags.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS);
+ // 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();
@@ -1231,7 +1319,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return false;
}
- if (entity.isVehicle()) {
+ if (entity.isVehicle() && !ignorePassengers) { // Paper - Teleport API
return false;
}
@@ -1249,7 +1337,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
// 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()) {
@@ -1265,13 +1353,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
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
this.getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); // Paper
}
// Check if the fromWorld and toWorld are the same.
if (fromWorld == toWorld) {
- entity.connection.teleport(to);
+ entity.connection.internalTeleport(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch(), relativeArguments); // Paper - Teleport API
} else {
// The respawn reason should never be used if the passed location is non null.
server.getHandle().respawn(entity, toWorld, true, to, !toWorld.paperConfig().environment.disableTeleportationSuffocationCheck, null); // Paper