2021-06-11 12:02:28 +00:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Caleb Bassham <caleb.bassham@gmail.com>
|
|
|
|
Date: Fri, 28 Sep 2018 02:32:19 -0500
|
|
|
|
Subject: [PATCH] Call player spectator target events and improve
|
|
|
|
implementation
|
|
|
|
|
|
|
|
Use a proper teleport for teleporting to entities in different
|
|
|
|
worlds.
|
|
|
|
|
|
|
|
Implementation improvements authored by Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
|
|
Validate that the target entity is valid and deny spectate
|
|
|
|
requests from frozen players.
|
|
|
|
|
|
|
|
Also, make sure the entity is spawned to the client before
|
|
|
|
sending the camera packet. If the entity isn't spawned clientside
|
|
|
|
when it receives the camera packet, then the client will not
|
|
|
|
spectate the target entity.
|
|
|
|
|
|
|
|
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
2022-09-26 08:02:51 +00:00
|
|
|
index 645012ea3590a46773e2bb14e9cafd9e3c695fd4..cb55e38b22330dbc542003841e8140eb6bee01bf 100644
|
2021-06-11 12:02:28 +00:00
|
|
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
2022-09-26 08:02:51 +00:00
|
|
|
@@ -1876,14 +1876,58 @@ public class ServerPlayer extends Player {
|
2021-06-11 12:02:28 +00:00
|
|
|
}
|
|
|
|
|
2021-11-23 23:06:05 +00:00
|
|
|
public void setCamera(@Nullable Entity entity) {
|
2021-06-11 12:02:28 +00:00
|
|
|
+ // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity Event and improve implementation
|
|
|
|
Entity entity1 = this.getCamera();
|
|
|
|
|
|
|
|
- this.camera = (Entity) (entity == null ? this : entity);
|
|
|
|
- if (entity1 != this.camera) {
|
|
|
|
- this.connection.send(new ClientboundSetCameraPacket(this.camera));
|
2021-11-23 23:06:05 +00:00
|
|
|
- this.connection.teleport(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.getYRot(), this.getXRot(), TeleportCause.SPECTATE); // CraftBukkit
|
2021-06-11 12:02:28 +00:00
|
|
|
+ if (entity == null) {
|
|
|
|
+ entity = this;
|
2021-11-23 23:06:05 +00:00
|
|
|
+ }
|
|
|
|
+
|
2021-06-11 12:02:28 +00:00
|
|
|
+ if (entity1 == entity) return; // new spec target is the current spec target
|
|
|
|
+
|
|
|
|
+ if (entity == this) {
|
|
|
|
+ com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent playerStopSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity());
|
|
|
|
+
|
|
|
|
+ if (!playerStopSpectatingEntityEvent.callEvent()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent playerStartSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity(), entity.getBukkitEntity());
|
|
|
|
+
|
|
|
|
+ if (!playerStartSpectatingEntityEvent.callEvent()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // Validate
|
|
|
|
+ if (entity != this) {
|
2021-06-13 06:48:25 +00:00
|
|
|
+ if (entity.isRemoved() || !entity.valid || entity.level == null) {
|
2021-06-17 17:11:00 +00:00
|
|
|
+ MinecraftServer.LOGGER.info("Blocking player " + this + " from spectating invalid entity " + entity);
|
2021-06-11 12:02:28 +00:00
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (this.isImmobile()) {
|
|
|
|
+ // use debug: clients might maliciously spam this
|
2021-06-17 17:11:00 +00:00
|
|
|
+ MinecraftServer.LOGGER.debug("Blocking frozen player " + this + " from spectating entity " + entity);
|
2021-06-11 12:02:28 +00:00
|
|
|
+ return;
|
|
|
|
+ }
|
2021-11-23 23:06:05 +00:00
|
|
|
}
|
|
|
|
|
2021-06-11 12:02:28 +00:00
|
|
|
+ this.camera = entity; // only set after validating state
|
|
|
|
+
|
|
|
|
+ if (entity != this) {
|
|
|
|
+ // Make sure we're in the right place
|
|
|
|
+ this.ejectPassengers(); // teleport can fail if we have passengers...
|
2021-06-13 06:48:25 +00:00
|
|
|
+ this.getBukkitEntity().teleport(new Location(entity.getCommandSenderWorld().getWorld(), entity.getX(), entity.getY(), entity.getZ(), this.getYRot(), this.getXRot()), TeleportCause.SPECTATE); // Correctly handle cross-world entities from api calls by using CB teleport
|
2021-06-11 12:02:28 +00:00
|
|
|
+
|
|
|
|
+ // Make sure we're tracking the entity before sending
|
|
|
|
+ ChunkMap.TrackedEntity tracker = ((ServerLevel)entity.level).getChunkSource().chunkMap.entityMap.get(entity.getId());
|
|
|
|
+ if (tracker != null) { // dumb plugins...
|
|
|
|
+ tracker.updatePlayer(this);
|
|
|
|
+ }
|
|
|
|
+ } else {
|
2021-06-13 06:48:25 +00:00
|
|
|
+ this.connection.teleport(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.getYRot(), this.getXRot(), TeleportCause.SPECTATE); // CraftBukkit
|
2021-06-11 12:02:28 +00:00
|
|
|
+ }
|
|
|
|
+ this.connection.send(new ClientboundSetCameraPacket(entity));
|
|
|
|
+ // Paper end
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|