mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-28 15:30:19 +01:00
0e7361704a
Updated Upstream (Bukkit/CraftBukkit/Spigot) 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: 4068c6aa PR-1053: Change docs for max power in FireworkMeta 6b3c241b SPIGOT-7783, SPIGOT-7784, PR-1051: Add Trial Vault & Spawner event API 5fe300ec PR-1052: Fix broken links and minor improvement for checkstyle.xml CraftBukkit Changes: 7548afcf2 SPIGOT-7872: Fix crash with event-modified teleports 93480d5d6 SPIGOT-7868, PR-1463: Fix default and max power in FireworkMeta 5060d1a84 SPIGOT-7783, SPIGOT-7784, PR-1460: Add Trial Vault & Spawner event API 11dfcae71 PR-1462: Fix broken links and minor improvement for checkstyle.xml Spigot Changes: ca581228 Rebuild patches
269 lines
15 KiB
Diff
269 lines
15 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
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
index 1d91e106b5cef0ab735e916ae32970fd793c8915..48470ab53797a14955ecc1c8368de4ca53dc560b 100644
|
|
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
@@ -1561,11 +1561,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
|
return true; // 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 - Teleport API
|
|
this.cserver.getPluginManager().callEvent(event);
|
|
|
|
if (event.isCancelled() || !to.equals(event.getTo())) {
|
|
- set = Collections.emptySet(); // Can't relative teleport
|
|
+ // set = Collections.emptySet(); // 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 4c09f2529dd8eb7ac7d260d177f5292ff2339442..94051ae8ea93ab144f3767345b1cda0438d2afc6 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
|
@@ -221,15 +221,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())) {
|
|
@@ -975,6 +996,39 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
|
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()),
|
|
+ this instanceof CraftPlayer ? ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER : ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, (list) -> {
|
|
+ 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()
|
|
{
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
index 252309281f440e9b7a6be3118363c4d97e5dd767..78c11d99b6dfdf742dbe24f7b3c2ddbcfd433fd6 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
@@ -1286,13 +1286,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 net.minecraft.world.phys.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) {
|
|
+ Set<io.papermc.paper.entity.TeleportFlag.Relative> relativeArguments;
|
|
+ Set<io.papermc.paper.entity.TeleportFlag> allFlags;
|
|
+ if (flags.length == 0) {
|
|
+ relativeArguments = Set.of();
|
|
+ allFlags = Set.of();
|
|
+ } else {
|
|
+ relativeArguments = java.util.EnumSet.noneOf(io.papermc.paper.entity.TeleportFlag.Relative.class);
|
|
+ allFlags = new HashSet<>();
|
|
+ for (io.papermc.paper.entity.TeleportFlag flag : flags) {
|
|
+ if (flag instanceof final io.papermc.paper.entity.TeleportFlag.Relative relativeTeleportFlag) {
|
|
+ relativeArguments.add(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();
|
|
@@ -1305,7 +1393,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
return false;
|
|
}
|
|
|
|
- if (entity.isVehicle()) {
|
|
+ if (entity.isVehicle() && !ignorePassengers) { // Paper - Teleport API
|
|
return false;
|
|
}
|
|
|
|
@@ -1314,7 +1402,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
// 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.
|
|
@@ -1323,7 +1411,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()) {
|
|
@@ -1339,13 +1427,19 @@ 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 - Inventory close reason
|
|
}
|
|
|
|
// Check if the fromWorld and toWorld are the same.
|
|
if (fromWorld == toWorld) {
|
|
- entity.connection.teleport(to);
|
|
+ // Paper start - Teleport API
|
|
+ final Set<net.minecraft.world.entity.RelativeMovement> nms = java.util.EnumSet.noneOf(net.minecraft.world.entity.RelativeMovement.class);
|
|
+ for (final io.papermc.paper.entity.TeleportFlag.Relative bukkit : relativeArguments) {
|
|
+ nms.add(toNmsRelativeFlag(bukkit));
|
|
+ }
|
|
+ entity.connection.internalTeleport(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch(), nms);
|
|
+ // Paper end - Teleport API
|
|
} else {
|
|
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
|
|
// The respawn reason should never be used if the passed location is non null.
|