202 lines
9.8 KiB
Diff
202 lines
9.8 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
Date: Sun, 10 Apr 2016 22:50:33 -0400
|
|
Subject: [PATCH] Allow Vehicle/Passenger Teleporting for Bukkit API
|
|
|
|
If Bukkit teleport is called, teleport the whole set of entities together and maintain the chain.
|
|
Patch from EMC: https://github.com/starlis/empirecraft/blob/f73510d91048d8b01bf8c50b0a2b0d054cb7c0b5/patches/server/0056-Allow-Vehicle-Passenger-Teleporting-for-Bukkit-API.patch
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
index 4032f499fd533e8d35d050758ea2358ad6878b94..c35331ea354b7c464677acc3c724d2e22bb375c1 100644
|
|
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
@@ -819,7 +819,7 @@ public abstract class PlayerList {
|
|
|
|
public ServerPlayer moveToWorld(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag...respawnFlags) {
|
|
// Paper end
|
|
- entityplayer.stopRiding(); // CraftBukkit
|
|
+ //entityplayer.stopRiding(); // CraftBukkit // Parchment - remove stop riding
|
|
this.players.remove(entityplayer);
|
|
this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
|
|
entityplayer.getLevel().removePlayerImmediately(entityplayer, Entity.RemovalReason.DISCARDED);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
index 94857a736d2a16e8ade286c6f2ddf8bd798008eb..8a5f4d0f01ce1d22790ccf6b11547b5e7cdd99bb 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
@@ -217,7 +217,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
|
|
public ImmutableList<Entity> passengers;
|
|
protected int boardingCooldown;
|
|
@Nullable
|
|
- private Entity vehicle;
|
|
+ public Entity vehicle; // Parchment - make public
|
|
public Level level;
|
|
public double xo;
|
|
public double yo;
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
|
index 2712aa554383a3b2b742c945e2f0be7ee96eea69..b3e21bc2347854fb39ba7c25c6de586f084119d4 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
|
@@ -3,6 +3,7 @@ package org.bukkit.craftbukkit.entity;
|
|
import com.google.common.base.Function;
|
|
import com.google.common.base.Preconditions;
|
|
import com.google.common.base.Predicates;
|
|
+import com.google.common.collect.ImmutableList;
|
|
import com.google.common.collect.Lists;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
@@ -556,23 +557,103 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
|
return this.teleport(location, TeleportCause.PLUGIN);
|
|
}
|
|
|
|
+ // Parchment start - vehicle passenger teleporting
|
|
+ private static CraftEntity teleportingEntity;
|
|
+ private CraftEntity storedRoot;
|
|
+ private ImmutableList<CraftEntity> storedPassengers;
|
|
+ void detachEntities() {
|
|
+ if (teleportingEntity == null) {
|
|
+ teleportingEntity = this;
|
|
+ this.storedRoot = entity.getRootVehicle().getBukkitEntity();
|
|
+ this.storedRoot.detachEntities();
|
|
+ teleportingEntity = null;
|
|
+ return;
|
|
+ }
|
|
+ this.storedPassengers = this.entity.passengers.stream().map(Entity::getBukkitEntity).collect(ImmutableList.toImmutableList());
|
|
+ this.forceEjectPassengers();
|
|
+ for (CraftEntity ent : this.storedPassengers) {
|
|
+ ent.detachEntities();
|
|
+ }
|
|
+ }
|
|
+ void forceEjectPassengers() {
|
|
+ for (int i = this.entity.passengers.size() - 1; i >= 0; --i) {
|
|
+ Entity passenger = (this.entity.passengers.get(i));
|
|
+ passenger.vehicle = null;
|
|
+ }
|
|
+ this.entity.passengers = ImmutableList.of();
|
|
+ }
|
|
+ void teleportAndReattachEntities(Location location) {
|
|
+ if (teleportingEntity == null) {
|
|
+ if (this.storedRoot != null) {
|
|
+ teleportingEntity = this;
|
|
+ this.storedRoot.teleportAndReattachEntities(location);
|
|
+ CraftEntity root = this.storedRoot;
|
|
+ this.storedRoot = null;
|
|
+ root.reattachPassengers();
|
|
+ teleportingEntity = null;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ if (!teleportingEntity.equals(this)) {
|
|
+ this.teleportEntity(location);
|
|
+ }
|
|
+ for (CraftEntity ent : this.storedPassengers) {
|
|
+ ent.teleportAndReattachEntities(location);
|
|
+ }
|
|
+ }
|
|
+ void teleportEntity(Location location) {
|
|
+ if (getWorld().equals(location.getWorld())) {
|
|
+ if (this.storedPassengers == null || this.storedPassengers.isEmpty()) {
|
|
+ this.entity.moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
|
+ this.entity.setYHeadRot(location.getYaw());
|
|
+ } else {
|
|
+ ServerLevel world = (ServerLevel) this.entity.level;
|
|
+ Entity target = this.entity.getType().create(world);
|
|
+ if (target == null) {
|
|
+ return;
|
|
+ }
|
|
+ target.restoreFrom(this.entity);
|
|
+ target.moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
|
+ target.setYHeadRot(location.getYaw());
|
|
+ this.entity.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION);
|
|
+ this.setHandle(target);
|
|
+ world.addDuringTeleport(target);
|
|
+ }
|
|
+ } else {
|
|
+ this.entity.teleportTo(((CraftWorld) location.getWorld()).getHandle(), new BlockPos(location.getX(), location.getY(), location.getZ()));
|
|
+ }
|
|
+ }
|
|
+ private void reattachPassengers() {
|
|
+ if (this.storedPassengers == null) {
|
|
+ return;
|
|
+ }
|
|
+ this.entity.passengers = this.storedPassengers.stream().map(CraftEntity::getHandle).collect(ImmutableList.toImmutableList());
|
|
+ for (CraftEntity passenger : this.storedPassengers) {
|
|
+ passenger.getHandle().vehicle = this.getHandle();
|
|
+ passenger.reattachPassengers();
|
|
+ }
|
|
+ this.storedPassengers = null;
|
|
+ }
|
|
+ // Parchment end - vehicle passenger teleporting
|
|
@Override
|
|
public boolean teleport(Location location, TeleportCause cause) {
|
|
Preconditions.checkArgument(location != null, "location");
|
|
location.checkFinite();
|
|
|
|
- if (this.entity.isVehicle() || this.entity.isRemoved()) {
|
|
+ if (this.entity.isRemoved()) { // Parchment
|
|
return false;
|
|
}
|
|
|
|
// If this entity is riding another entity, we must dismount before teleporting.
|
|
- this.entity.stopRiding();
|
|
+ //this.entity.stopRiding(); // Parchment
|
|
+ this.detachEntities(); // Parchment
|
|
|
|
// Let the server handle cross world teleports
|
|
if (!location.getWorld().equals(this.getWorld())) {
|
|
// Prevent teleportation to an other world during world generation
|
|
Preconditions.checkState(!entity.generation, "Cannot teleport entity to an other world during world generation");
|
|
this.entity.teleportTo(((CraftWorld) location.getWorld()).getHandle(), new BlockPos(location.getX(), location.getY(), location.getZ()));
|
|
+ this.teleportAndReattachEntities(location); // Parchment
|
|
return true;
|
|
}
|
|
|
|
@@ -581,6 +662,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
|
// SPIGOT-619: Force sync head rotation also
|
|
this.entity.setYHeadRot(location.getYaw());
|
|
|
|
+ this.teleportAndReattachEntities(location); // Parchment
|
|
return true;
|
|
}
|
|
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
index 2b8e31ae00e786dfbfbf5bb5228b846752cd2543..1a09026ccbe785a37e935e77e35f629068df4d83 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
@@ -1021,7 +1021,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
}
|
|
|
|
// If this player is riding another entity, we must dismount before teleporting.
|
|
- entity.stopRiding();
|
|
+ //entity.stopRiding(); // Parchment
|
|
|
|
// SPIGOT-5509: Wakeup, similar to riding
|
|
if (this.isSleeping()) {
|
|
@@ -1043,12 +1043,27 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
|
|
// Check if the fromWorld and toWorld are the same.
|
|
if (fromWorld == toWorld) {
|
|
+ this.detachEntities(); // Parchment
|
|
entity.connection.teleport(to);
|
|
} else {
|
|
+ this.detachEntities(); // Parchment
|
|
server.getHandle().moveToWorld(entity, toWorld, true, to, !toWorld.paperConfig.disableTeleportationSuffocationCheck); // Paper
|
|
}
|
|
+ this.teleportAndReattachEntities(location); // Parchment
|
|
return true;
|
|
}
|
|
+ // Parchment start
|
|
+ @Override
|
|
+ void teleportEntity(Location location) {
|
|
+ ServerPlayer entity = this.getHandle();
|
|
+ if (getWorld().equals(location.getWorld())) {
|
|
+ entity.connection.teleport(location);
|
|
+ } else {
|
|
+ ServerLevel toWorld = ((CraftWorld) location.getWorld()).getHandle();
|
|
+ server.getHandle().moveToWorld(entity, toWorld, true, location, !toWorld.paperConfig.disableTeleportationSuffocationCheck);
|
|
+ }
|
|
+ }
|
|
+ // Parchment end
|
|
|
|
// Paper start - Ugly workaround for SPIGOT-1915 & GH-114
|
|
@Override
|