13
0
geforkt von Mirrors/Paper

feat: Entity#teleportAsync method with TeleportFlags (#10371)

* feat: Entity#teleportAsync method with TeleportFlags

* use method-local class

---------

Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
Dieser Commit ist enthalten in:
Bridge 2024-04-06 22:38:37 +02:00
Ursprung 68e86d7297
Commit 7de6922d21
13 geänderte Dateien mit 100 neuen und 84 gelöschten Zeilen

Datei anzeigen

@ -498,25 +498,31 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param loc Location to teleport to + * @param loc Location to teleport to
+ * @return A future that will be completed with the result of the teleport + * @return A future that will be completed with the result of the teleport
+ */ + */
+ @NotNull + default java.util.concurrent.@NotNull CompletableFuture<Boolean> teleportAsync(final @NotNull Location loc) {
+ public default java.util.concurrent.CompletableFuture<Boolean> teleportAsync(@NotNull Location loc) { + return this.teleportAsync(loc, TeleportCause.PLUGIN);
+ return teleportAsync(loc, TeleportCause.PLUGIN);
+ } + }
+
+ /** + /**
+ * Loads/Generates(in 1.13+) the Chunk asynchronously, and then teleports the entity when the chunk is ready. + * Loads/Generates(in 1.13+) the Chunk asynchronously, and then teleports the entity when the chunk is ready.
+ * @param loc Location to teleport to + * @param loc Location to teleport to
+ * @param cause Reason for teleport + * @param cause Reason for teleport
+ * @return A future that will be completed with the result of the teleport + * @return A future that will be completed with the result of the teleport
+ */ + */
+ @NotNull + default java.util.concurrent.@NotNull CompletableFuture<Boolean> teleportAsync(final @NotNull Location loc, final @NotNull TeleportCause cause) {
+ public default java.util.concurrent.CompletableFuture<Boolean> teleportAsync(@NotNull Location loc, @NotNull TeleportCause cause) { + final class Holder {
+ java.util.concurrent.CompletableFuture<Boolean> future = new java.util.concurrent.CompletableFuture<>(); + static final io.papermc.paper.entity.TeleportFlag[] EMPTY_FLAGS = new io.papermc.paper.entity.TeleportFlag[0];
+ loc.getWorld().getChunkAtAsyncUrgently(loc).thenAccept((chunk) -> future.complete(teleport(loc, cause))).exceptionally(ex -> { + }
+ future.completeExceptionally(ex); + return this.teleportAsync(loc, cause, Holder.EMPTY_FLAGS);
+ return null;
+ });
+ return future;
+ } + }
+
+ /**
+ * Loads/Generates(in 1.13+) the Chunk asynchronously, and then teleports the entity when the chunk is ready.
+ * @param loc Location to teleport to
+ * @param cause Reason for teleport
+ * @param teleportFlags Flags to be used in this teleportation
+ * @return A future that will be completed with the result of the teleport
+ */
+ java.util.concurrent.@NotNull CompletableFuture<Boolean> teleportAsync(@NotNull Location loc, @NotNull TeleportCause cause, @NotNull io.papermc.paper.entity.TeleportFlag @NotNull... teleportFlags);
+ // Paper end + // Paper end
+ +
/** /**

Datei anzeigen

@ -9,10 +9,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
public boolean isInPowderedSnow() {
return getHandle().isInPowderSnow || getHandle().wasInPowderSnow; // depending on the location in the entity "tick" either could be needed.
} }
+ // Paper end - entity powdered snow API
+ // Paper start - entity body yaw API
+ @Override + @Override
+ public double getX() { + public double getX() {
+ return this.entity.getX(); + return this.entity.getX();
@ -37,9 +37,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public float getYaw() { + public float getYaw() {
+ return this.entity.getBukkitYaw(); + return this.entity.getBukkitYaw();
+ } + }
// Paper end + // Paper end - entity body yaw API
+
// Paper start - missing entity api // Paper start - missing entity api
@Override
public boolean isInvisible() { // Paper - moved up from LivingEntity
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java

Datei anzeigen

@ -31,10 +31,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
}
return set;
} }
+ // Paper end - tracked players API
+ // Paper start - raw entity serialization API
+ @Override + @Override
+ public boolean spawnAt(Location location, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { + public boolean spawnAt(Location location, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
+ Preconditions.checkNotNull(location, "location cannot be null"); + Preconditions.checkNotNull(location, "location cannot be null");
@ -44,9 +44,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.entity.setRot(location.getYaw(), location.getPitch()); + this.entity.setRot(location.getYaw(), location.getPitch());
+ return !this.entity.valid && this.entity.level().addFreshEntity(this.entity, reason); + return !this.entity.valid && this.entity.level().addFreshEntity(this.entity, reason);
+ } + }
// Paper end + // Paper end - raw entity serialization API
+
// Paper start - missing entity api // Paper start - missing entity api
@Override
public boolean isInvisible() { // Paper - moved up from LivingEntity
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java

Datei anzeigen

@ -12,10 +12,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() {
return getHandle().spawnReason; return getHandle().spawnReason;
} }
// Paper end - entity spawn reason API
+ +
+ // Paper start - entity liquid API
+ @Override + @Override
+ public boolean isUnderWater() { + public boolean isUnderWater() {
+ return getHandle().isUnderWater(); + return getHandle().isUnderWater();
@ -50,5 +51,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public boolean isInLava() { + public boolean isInLava() {
+ return getHandle().isInLava(); + return getHandle().isInLava();
+ } + }
// Paper end + // Paper end - entity liquid API
} }

Datei anzeigen

@ -98,10 +98,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return this.spigot;
return ret;
} }
// Spigot end
+ +
+ // Paper start - entity origin API
+ @Override + @Override
+ public Location getOrigin() { + public Location getOrigin() {
+ Vector originVector = this.getHandle().getOriginVector(); + Vector originVector = this.getHandle().getOriginVector();
@ -116,5 +117,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ //noinspection ConstantConditions + //noinspection ConstantConditions
+ return originVector.toLocation(world); + return originVector.toLocation(world);
+ } + }
// Paper end + // Paper end - entity origin API
} }

Datei anzeigen

@ -53,13 +53,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
//noinspection ConstantConditions
return originVector.toLocation(world); return originVector.toLocation(world);
} }
// Paper end - entity origin API
+ +
+ // Paper start - Entity#fromMobSpawner
+ @Override + @Override
+ public boolean fromMobSpawner() { + public boolean fromMobSpawner() {
+ return getHandle().spawnedViaMobSpawner; + return this.getHandle().spawnedViaMobSpawner;
+ } + }
// Paper end + // Paper end - Entity#fromMobSpawner
} }

Datei anzeigen

@ -137,13 +137,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
public boolean fromMobSpawner() { return this.getHandle().spawnedViaMobSpawner;
return getHandle().spawnedViaMobSpawner;
} }
// Paper end - Entity#fromMobSpawner
+ +
+ // Paper start - entity spawn reason API
+ @Override + @Override
+ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { + public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() {
+ return getHandle().spawnReason; + return getHandle().spawnReason;
+ } + }
// Paper end + // Paper end - entity spawn reason API
} }

Datei anzeigen

@ -23,13 +23,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
public boolean isInLava() {
return getHandle().isInLava(); return getHandle().isInLava();
} }
// Paper end - entity liquid API
+ +
+ // Paper start - isTicking API
+ @Override + @Override
+ public boolean isTicking() { + public boolean isTicking() {
+ return getHandle().isTicking(); + return getHandle().isTicking();
+ } + }
// Paper end + // Paper end - isTicking API
} }

Datei anzeigen

@ -11,17 +11,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
this.entity.setRot(location.getYaw(), location.getPitch());
return !this.entity.valid && this.entity.level().addFreshEntity(this.entity, reason);
} }
+ // Paper end - raw entity serialization API
+ // Paper start - entity powdered snow API
+ @Override + @Override
+ public boolean isInPowderedSnow() { + public boolean isInPowderedSnow() {
+ return getHandle().isInPowderSnow || getHandle().wasInPowderSnow; // depending on the location in the entity "tick" either could be needed. + return getHandle().isInPowderSnow || getHandle().wasInPowderSnow; // depending on the location in the entity "tick" either could be needed.
+ } + }
// Paper end + // Paper end - entity powdered snow API
+
// Paper start - missing entity api // Paper start - missing entity api
@Override
public boolean isInvisible() { // Paper - moved up from LivingEntity
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java

Datei anzeigen

@ -9,10 +9,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
public boolean isTicking() {
return getHandle().isTicking(); return getHandle().isTicking();
} }
// Paper end - isTicking API
+ +
+ // Paper start - tracked players API
+ @Override + @Override
+ public Set<org.bukkit.entity.Player> getTrackedPlayers() { + public Set<org.bukkit.entity.Player> getTrackedPlayers() {
+ if (this.entity.tracker == null) { + if (this.entity.tracker == null) {
@ -25,5 +26,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ return set; + return set;
+ } + }
// Paper end + // Paper end - tracked players API
} }

Datei anzeigen

@ -7850,48 +7850,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public void setSendViewDistance(final int viewDistance) { + public void setSendViewDistance(final int viewDistance) {
+ throw new UnsupportedOperationException("Not implemented yet"); + throw new UnsupportedOperationException("Not implemented yet");
+ } + }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return this.spigot;
}
// Spigot end
+
+ // Paper start
+ @Override
+ public java.util.concurrent.CompletableFuture<Boolean> teleportAsync(Location location, TeleportCause cause) {
+ 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) ? 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 + // Paper end
} }
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java

Datei anzeigen

@ -677,7 +677,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return set; return set;
} }
// Paper end // Paper end - tracked players API
+ +
+ // Paper start - missing entity api + // Paper start - missing entity api
+ @Override + @Override

Datei anzeigen

@ -71,6 +71,46 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// Let the server handle cross world teleports // Let the server handle cross world teleports
if (location.getWorld() != null && !location.getWorld().equals(this.getWorld())) { if (location.getWorld() != null && !location.getWorld().equals(this.getWorld())) {
@@ -0,0 +0,0 @@ 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 diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java