aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0904-Properly-resend-entities.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/server/0904-Properly-resend-entities.patch')
-rw-r--r--patches/server/0904-Properly-resend-entities.patch107
1 files changed, 107 insertions, 0 deletions
diff --git a/patches/server/0904-Properly-resend-entities.patch b/patches/server/0904-Properly-resend-entities.patch
new file mode 100644
index 0000000000..a394b38e9d
--- /dev/null
+++ b/patches/server/0904-Properly-resend-entities.patch
@@ -0,0 +1,107 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Owen1212055 <[email protected]>
+Date: Wed, 7 Dec 2022 17:25:19 -0500
+Subject: [PATCH] Properly resend entities
+
+This resolves some issues which caused entities to not be resent correctly.
+Entities that are interacted with need to be resent to the client, so we resend all the entity
+data to the player whilst making sure not to clear dirty entries from the tracker. This makes
+sure that values will be correctly updated to other players.
+
+See: https://github.com/PaperMC/Paper/pull/1896
+
+== AT ==
+public net.minecraft.server.level.ChunkMap$TrackedEntity serverEntity
+
+diff --git a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
+index d088479d160dbd2fc90b48a30553be141db8eef2..9e7a9e2fc19a0ac7a80a07efacf9cd2366826fa3 100644
+--- a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
++++ b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
+@@ -253,14 +253,46 @@ public class SynchedEntityData {
+ // CraftBukkit start
+ public void refresh(ServerPlayer to) {
+ if (!this.isEmpty()) {
+- List<SynchedEntityData.DataValue<?>> list = this.getNonDefaultValues();
++ List<SynchedEntityData.DataValue<?>> list = this.packAll(); // Paper - Update EVERYTHING not just not default
+
+ if (list != null) {
++ if (to.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { // Paper
+ to.connection.send(new ClientboundSetEntityDataPacket(this.entity.getId(), list));
++ } // Paper
+ }
+ }
+ }
+ // CraftBukkit end
++ // Paper start
++ // We need to pack all as we cannot rely on "non default values" or "dirty" ones.
++ // Because these values can possibly be desynced on the client.
++ @Nullable
++ private List<SynchedEntityData.DataValue<?>> packAll() {
++ if (this.isEmpty()) {
++ return null;
++ }
++
++ List<SynchedEntityData.DataValue<?>> list = new ArrayList<>();
++ for (DataItem<?> dataItem : this.itemsById.values()) {
++ list.add(dataItem.value());
++ }
++
++ return list;
++ }
++
++ // This method should only be used if the data of an entity could have became desynced
++ // due to interactions on the client.
++ public void resendPossiblyDesyncedEntity(ServerPlayer player) {
++ if (this.entity.tracker == null) {
++ return;
++ }
++
++ net.minecraft.server.level.ServerEntity serverEntity = this.entity.tracker.serverEntity;
++ if (player.getBukkitEntity().canSee(entity.getBukkitEntity())) {
++ serverEntity.sendPairingData(player.connection::send, player);
++ }
++ }
++ // Paper end
+
+ public static class DataItem<T> {
+
+diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+index f52b01bca1b4221b389b2e980f2f75b0f1eca077..9b00b18e5c80c69b0c44299b48cef1937168f38a 100644
+--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+@@ -2795,7 +2795,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
+
+ // Entity in bucket - SPIGOT-4048 and SPIGOT-6859a
+ if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem)) {
+- ServerGamePacketListenerImpl.this.send(new ClientboundAddEntityPacket(entity));
++ entity.getEntityData().resendPossiblyDesyncedEntity(player); // Paper - The entire mob gets deleted, so resend it.
+ player.containerMenu.sendAllDataToRemote();
+ }
+
+diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
+index f937dbd6a19b595e3660e598e52bf37f8cc72d13..d3e259eb22202133d54c4be58c5121735fe412ed 100644
+--- a/src/main/java/net/minecraft/server/players/PlayerList.java
++++ b/src/main/java/net/minecraft/server/players/PlayerList.java
+@@ -371,7 +371,7 @@ public abstract class PlayerList {
+ ((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - track entity now
+ // CraftBukkit end
+
+- player.getEntityData().refresh(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn
++ //player.getEntityData().refresh(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn Paper - THIS IS NOT NEEDED ANYMORE
+
+ this.sendLevelInfo(player, worldserver1);
+
+diff --git a/src/main/java/net/minecraft/world/entity/animal/Bucketable.java b/src/main/java/net/minecraft/world/entity/animal/Bucketable.java
+index 37596c7b65f280be00e8e59ae18bd1aceae21080..eca18540aeb0b0d4098477d73b14c78a7bf9f455 100644
+--- a/src/main/java/net/minecraft/world/entity/animal/Bucketable.java
++++ b/src/main/java/net/minecraft/world/entity/animal/Bucketable.java
+@@ -109,8 +109,7 @@ public interface Bucketable {
+ itemstack1 = CraftItemStack.asNMSCopy(playerBucketFishEvent.getEntityBucket());
+ if (playerBucketFishEvent.isCancelled()) {
+ ((ServerPlayer) player).containerMenu.sendAllDataToRemote(); // We need to update inventory to resync client's bucket
+- ((ServerPlayer) player).connection.send(new ClientboundAddEntityPacket(entity)); // We need to play out these packets as the client assumes the fish is gone
+- entity.getEntityData().refresh((ServerPlayer) player); // Need to send data such as the display name to client
++ entity.getEntityData().resendPossiblyDesyncedEntity((ServerPlayer) player); // Paper
+ return Optional.of(InteractionResult.FAIL);
+ }
+ entity.playSound(((Bucketable) entity).getPickupSound(), 1.0F, 1.0F);