diff options
author | Nassim Jahnke <[email protected]> | 2024-06-16 12:47:57 +0200 |
---|---|---|
committer | Nassim Jahnke <[email protected]> | 2024-06-16 12:47:57 +0200 |
commit | 752f957e12e4ceb8b7d2043a4a7dbce786b7b98f (patch) | |
tree | 006ea0327b7f1ad952cdde2fb077b9e6f63e525c /patches/server | |
parent | 60f3bd8d0c01e17f1947e706b5c3ab5fda4b694a (diff) | |
download | Paper-752f957e12e4ceb8b7d2043a4a7dbce786b7b98f.tar.gz Paper-752f957e12e4ceb8b7d2043a4a7dbce786b7b98f.zip |
Add back more patches
Diffstat (limited to 'patches/server')
-rw-r--r-- | patches/server/0991-Chunk-System-Starlight-from-Moonrise.patch | 9 | ||||
-rw-r--r-- | patches/server/1009-Entity-load-save-limit-per-chunk.patch | 81 | ||||
-rw-r--r-- | patches/server/1010-Optimize-Voxel-Shape-Merging.patch (renamed from patches/server/1009-Optimize-Voxel-Shape-Merging.patch) | 0 | ||||
-rw-r--r-- | patches/server/1011-Optimize-Bit-Operations-by-inlining.patch (renamed from patches/server/1010-Optimize-Bit-Operations-by-inlining.patch) | 0 | ||||
-rw-r--r-- | patches/server/1012-Remove-streams-from-hot-code.patch (renamed from patches/server/1011-Remove-streams-from-hot-code.patch) | 0 | ||||
-rw-r--r-- | patches/server/1013-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch (renamed from patches/server/1012-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch) | 0 | ||||
-rw-r--r-- | patches/server/1014-Custom-table-implementation-for-blockstate-state-loo.patch (renamed from patches/server/1013-Custom-table-implementation-for-blockstate-state-loo.patch) | 0 | ||||
-rw-r--r-- | patches/server/1015-Fix-entity-type-tags-suggestions-in-selectors.patch (renamed from patches/server/1014-Fix-entity-type-tags-suggestions-in-selectors.patch) | 0 | ||||
-rw-r--r-- | patches/server/1016-Handle-Oversized-block-entities-in-chunks.patch (renamed from patches/server/1015-Handle-Oversized-block-entities-in-chunks.patch) | 0 | ||||
-rw-r--r-- | patches/server/1017-API-for-checking-sent-chunks.patch (renamed from patches/server/1016-API-for-checking-sent-chunks.patch) | 0 | ||||
-rw-r--r-- | patches/server/1018-Configurable-Sand-Duping.patch (renamed from patches/server/1017-Configurable-Sand-Duping.patch) | 0 | ||||
-rw-r--r-- | patches/server/1019-Properly-resend-entities.patch | 232 |
12 files changed, 318 insertions, 4 deletions
diff --git a/patches/server/0991-Chunk-System-Starlight-from-Moonrise.patch b/patches/server/0991-Chunk-System-Starlight-from-Moonrise.patch index 6b8f2f460b..3e7b994bed 100644 --- a/patches/server/0991-Chunk-System-Starlight-from-Moonrise.patch +++ b/patches/server/0991-Chunk-System-Starlight-from-Moonrise.patch @@ -5024,10 +5024,10 @@ index 0000000000000000000000000000000000000000..755b08dd32e568d341ceef8a8aef8418 +} diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java new file mode 100644 -index 0000000000000000000000000000000000000000..f85820b959213c9bb566897c173f644fd430d01a +index 0000000000000000000000000000000000000000..19672631d7c69ade16a6f966c72a4a9d57b77c55 --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java -@@ -0,0 +1,810 @@ +@@ -0,0 +1,811 @@ +package ca.spottedleaf.moonrise.patches.chunk_system.level.entity; + +import ca.spottedleaf.moonrise.common.list.EntityList; @@ -5056,6 +5056,7 @@ index 0000000000000000000000000000000000000000..f85820b959213c9bb566897c173f644f +import java.util.Iterator; +import java.util.List; +import java.util.function.Predicate; ++import org.bukkit.event.entity.EntityRemoveEvent; + +public final class ChunkEntitySlices { + @@ -5176,12 +5177,12 @@ index 0000000000000000000000000000000000000000..f85820b959213c9bb566897c173f644f + continue; + } + if (entity.shouldBeSaved()) { -+ entity.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK); ++ entity.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK, EntityRemoveEvent.Cause.UNLOAD); + if (entity.isVehicle()) { + // we cannot assume that these entities are contained within this chunk, because entities can + // desync - so we need to remove them all + for (final Entity passenger : entity.getIndirectPassengers()) { -+ passenger.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK); ++ passenger.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK, EntityRemoveEvent.Cause.UNLOAD); + } + } + } diff --git a/patches/server/1009-Entity-load-save-limit-per-chunk.patch b/patches/server/1009-Entity-load-save-limit-per-chunk.patch new file mode 100644 index 0000000000..cf71d8747d --- /dev/null +++ b/patches/server/1009-Entity-load-save-limit-per-chunk.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jason Penilla <[email protected]> +Date: Wed, 18 Nov 2020 20:52:25 -0800 +Subject: [PATCH] Entity load/save limit per chunk + +Adds a config option to limit the number of entities saved and loaded +to a chunk. The default values of -1 disable the limit. Although +defaults are only included for certain entites, this allows setting +limits for any entity type. + +diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java +index 19672631d7c69ade16a6f966c72a4a9d57b77c55..df4aadd40c0033c852af575fd11dce8eb3f2959e 100644 +--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java ++++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java +@@ -100,7 +100,18 @@ public final class ChunkEntitySlices { + } + + final ListTag entitiesTag = new ListTag(); ++ final java.util.Map<net.minecraft.world.entity.EntityType<?>, Integer> savedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk + for (final Entity entity : entities) { ++ // Paper start - Entity load/save limit per chunk ++ final EntityType<?> entityType = entity.getType(); ++ final int saveLimit = world.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ break; ++ } ++ savedEntityCounts.merge(entityType, 1, Integer::sum); ++ } ++ // Paper end - Entity load/save limit per chunk + CompoundTag compoundTag = new CompoundTag(); + if (entity.save(compoundTag)) { + entitiesTag.add(compoundTag); +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index 842b0cec0397d7ae5166617627340ffac0e35db1..cb61462d4691a055a4b25f7b953609d8a154fdfe 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -649,9 +649,20 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT + final Spliterator<? extends Tag> spliterator = entityNbtList.spliterator(); + + return StreamSupport.stream(new Spliterator<Entity>() { ++ final java.util.Map<EntityType<?>, Integer> loadedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk + public boolean tryAdvance(Consumer<? super Entity> consumer) { + return spliterator.tryAdvance((nbtbase) -> { + EntityType.loadEntityRecursive((CompoundTag) nbtbase, world, (entity) -> { ++ // Paper start - Entity load/save limit per chunk ++ final EntityType<?> entityType = entity.getType(); ++ final int saveLimit = world.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (this.loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ return null; ++ } ++ this.loadedEntityCounts.merge(entityType, 1, Integer::sum); ++ } ++ // Paper end - Entity load/save limit per chunk + consumer.accept(entity); + return entity; + }); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java +index 503ac0374e0c9f9993ad37bb8bd8cf1570d3615a..d4a505ef4af9ded02aeb1a817bcbe5b1a912a5b3 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java +@@ -92,7 +92,18 @@ public class EntityStorage implements EntityPersistentStorage<Entity> { + } + } else { + ListTag listTag = new ListTag(); ++ final java.util.Map<net.minecraft.world.entity.EntityType<?>, Integer> savedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk + dataList.getEntities().forEach(entity -> { ++ // Paper start - Entity load/save limit per chunk ++ final EntityType<?> entityType = entity.getType(); ++ final int saveLimit = this.level.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ return; ++ } ++ savedEntityCounts.merge(entityType, 1, Integer::sum); ++ } ++ // Paper end - Entity load/save limit per chunk + CompoundTag compoundTagx = new CompoundTag(); + if (entity.save(compoundTagx)) { + listTag.add(compoundTagx); diff --git a/patches/server/1009-Optimize-Voxel-Shape-Merging.patch b/patches/server/1010-Optimize-Voxel-Shape-Merging.patch index 4ec779560c..4ec779560c 100644 --- a/patches/server/1009-Optimize-Voxel-Shape-Merging.patch +++ b/patches/server/1010-Optimize-Voxel-Shape-Merging.patch diff --git a/patches/server/1010-Optimize-Bit-Operations-by-inlining.patch b/patches/server/1011-Optimize-Bit-Operations-by-inlining.patch index b7d93a56b9..b7d93a56b9 100644 --- a/patches/server/1010-Optimize-Bit-Operations-by-inlining.patch +++ b/patches/server/1011-Optimize-Bit-Operations-by-inlining.patch diff --git a/patches/server/1011-Remove-streams-from-hot-code.patch b/patches/server/1012-Remove-streams-from-hot-code.patch index 4c6d94f7bf..4c6d94f7bf 100644 --- a/patches/server/1011-Remove-streams-from-hot-code.patch +++ b/patches/server/1012-Remove-streams-from-hot-code.patch diff --git a/patches/server/1012-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/patches/server/1013-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch index 6fc4445bbf..6fc4445bbf 100644 --- a/patches/server/1012-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch +++ b/patches/server/1013-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch diff --git a/patches/server/1013-Custom-table-implementation-for-blockstate-state-loo.patch b/patches/server/1014-Custom-table-implementation-for-blockstate-state-loo.patch index 96d90abea3..96d90abea3 100644 --- a/patches/server/1013-Custom-table-implementation-for-blockstate-state-loo.patch +++ b/patches/server/1014-Custom-table-implementation-for-blockstate-state-loo.patch diff --git a/patches/server/1014-Fix-entity-type-tags-suggestions-in-selectors.patch b/patches/server/1015-Fix-entity-type-tags-suggestions-in-selectors.patch index 47e6c56f5b..47e6c56f5b 100644 --- a/patches/server/1014-Fix-entity-type-tags-suggestions-in-selectors.patch +++ b/patches/server/1015-Fix-entity-type-tags-suggestions-in-selectors.patch diff --git a/patches/server/1015-Handle-Oversized-block-entities-in-chunks.patch b/patches/server/1016-Handle-Oversized-block-entities-in-chunks.patch index d3283fd63f..d3283fd63f 100644 --- a/patches/server/1015-Handle-Oversized-block-entities-in-chunks.patch +++ b/patches/server/1016-Handle-Oversized-block-entities-in-chunks.patch diff --git a/patches/server/1016-API-for-checking-sent-chunks.patch b/patches/server/1017-API-for-checking-sent-chunks.patch index a0c0a6363e..a0c0a6363e 100644 --- a/patches/server/1016-API-for-checking-sent-chunks.patch +++ b/patches/server/1017-API-for-checking-sent-chunks.patch diff --git a/patches/server/1017-Configurable-Sand-Duping.patch b/patches/server/1018-Configurable-Sand-Duping.patch index cbc52697db..cbc52697db 100644 --- a/patches/server/1017-Configurable-Sand-Duping.patch +++ b/patches/server/1018-Configurable-Sand-Duping.patch diff --git a/patches/server/1019-Properly-resend-entities.patch b/patches/server/1019-Properly-resend-entities.patch new file mode 100644 index 0000000000..104ad37efe --- /dev/null +++ b/patches/server/1019-Properly-resend-entities.patch @@ -0,0 +1,232 @@ +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. + +This also adds utilities to aid in further preventing entity desyncs. + +This also also fixes the bug causing cancelling PlayerInteractEvent to cause items to continue +to be used despite being cancelled on the server. + +For example, items being consumed but never finishing, shields being put up, etc. +The underlying issue of this is that the client modifies their synced data values, +and so we have to (forcibly) resend them in order for the client to reset their using item state. + +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 02bf2705ca1c99023a83a22d92e1962181102297..0f99733660f91280e4c6262cf75b3c9cae86f65a 100644 +--- a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java ++++ b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java +@@ -50,7 +50,7 @@ public class SynchedEntityData { + } + } + +- private <T> SynchedEntityData.DataItem<T> getItem(EntityDataAccessor<T> key) { ++ public <T> SynchedEntityData.DataItem<T> getItem(EntityDataAccessor<T> key) { // Paper - public + return (SynchedEntityData.DataItem<T>) this.itemsById[key.id()]; // CraftBukkit - decompile error + } + +@@ -151,6 +151,20 @@ public class SynchedEntityData { + } + } + ++ // 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 ++ public List<SynchedEntityData.DataValue<?>> packAll() { ++ final List<SynchedEntityData.DataValue<?>> list = new ArrayList<>(); ++ for (final DataItem<?> dataItem : this.itemsById) { ++ list.add(dataItem.value()); ++ } ++ ++ return list; ++ } ++ // Paper end ++ + public static class DataItem<T> { + + final EntityDataAccessor<T> accessor; +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index e9dcdb1e09e84a9b451034ff4bdfa6eae2dd1c04..24b1715397ba8e6f5e9841a030d0e3d964356f89 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -561,6 +561,7 @@ public class ServerPlayerGameMode { + } + // Paper end - extend Player Interact cancellation + player.getBukkitEntity().updateInventory(); // SPIGOT-2867 ++ this.player.resyncUsingItem(this.player); // Paper - Properly cancel usable items + return (event.useItemInHand() != Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS; + } else if (this.gameModeForPlayer == GameType.SPECTATOR) { + MenuProvider itileinventory = iblockdata.getMenuProvider(world, blockposition); +@@ -612,6 +613,11 @@ public class ServerPlayerGameMode { + + return enuminteractionresult; + } else { ++ // Paper start - Properly cancel usable items; Cancel only if cancelled + if the interact result is different from default response ++ if (this.interactResult && this.interactResult != cancelledItem) { ++ this.player.resyncUsingItem(this.player); ++ } ++ // Paper end - Properly cancel usable items + return InteractionResult.PASS; + } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index be2e97e4de911ad9570a9b4e9f3c5fafa93f6203..199e2f447ddb319387a15c934da71c27aab6da1e 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -1949,6 +1949,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + } + + if (cancelled) { ++ this.player.resyncUsingItem(this.player); // Paper - Properly cancel usable items + this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 + return; + } +@@ -2718,7 +2719,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + + // 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)) { +- entity.getBukkitEntity().update(ServerGamePacketListenerImpl.this.player); ++ entity.resendPossiblyDesyncedEntityData(ServerGamePacketListenerImpl.this.player); // Paper - The entire mob gets deleted, so resend it + ServerGamePacketListenerImpl.this.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 0d0b07c9199be9ca0d5ac3feb1d44f149ba69283..3d30427e75bdfb9cf453fb5cd2a344227da1641a 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -393,7 +393,7 @@ public abstract class PlayerList { + ((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - Fire PlayerJoinEvent when Player is actually ready; track entity now + // CraftBukkit end + +- player.refreshEntityData(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn ++ //player.refreshEntityData(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/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 14db8510af7465eb663501008ca35f8ec63bfe30..898651b7cfff15fe1afb690c247cdc3936d12fa6 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -664,13 +664,44 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + + // CraftBukkit start + public void refreshEntityData(ServerPlayer to) { +- List<SynchedEntityData.DataValue<?>> list = this.getEntityData().getNonDefaultValues(); ++ List<SynchedEntityData.DataValue<?>> list = this.entityData.packAll(); // Paper - Update EVERYTHING not just not default + +- if (list != null) { ++ if (list != null && to.getBukkitEntity().canSee(this.getBukkitEntity())) { // Paper + to.connection.send(new ClientboundSetEntityDataPacket(this.getId(), list)); + } + } + // CraftBukkit end ++ // Paper start ++ // This method should only be used if the data of an entity could have become desynced ++ // due to interactions on the client. ++ public void resendPossiblyDesyncedEntityData(net.minecraft.server.level.ServerPlayer player) { ++ if (this.tracker == null) { ++ return; ++ } ++ ++ if (player.getBukkitEntity().canSee(this.getBukkitEntity())) { ++ final net.minecraft.server.level.ServerEntity serverEntity = this.tracker.serverEntity; ++ final List<net.minecraft.network.protocol.Packet<? super net.minecraft.network.protocol.game.ClientGamePacketListener>> list = new java.util.ArrayList<>(); ++ serverEntity.sendPairingData(player, list::add); ++ player.connection.send(new net.minecraft.network.protocol.game.ClientboundBundlePacket(list)); ++ } ++ } ++ ++ // This method allows you to specifically resend certain data accessor keys to the client ++ public void resendPossiblyDesyncedDataValues(List<EntityDataAccessor<?>> keys, ServerPlayer to) { ++ if (!to.getBukkitEntity().canSee(this.getBukkitEntity())) { ++ return; ++ } ++ ++ final List<SynchedEntityData.DataValue<?>> values = new java.util.ArrayList<>(keys.size()); ++ for (final EntityDataAccessor<?> key : keys) { ++ final SynchedEntityData.DataItem<?> synchedValue = this.entityData.getItem(key); ++ values.add(synchedValue.value()); ++ } ++ ++ to.connection.send(new ClientboundSetEntityDataPacket(this.id, values)); ++ } ++ // Paper end + + public boolean equals(Object object) { + return object instanceof Entity ? ((Entity) object).id == this.id : false; +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 25a7dfddb44a11f6e20c459141a61270c0c12d4c..e980c8c356b30d25e2fc5a73b91ad2c6edd4fe05 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3840,6 +3840,11 @@ public abstract class LivingEntity extends Entity implements Attackable { + return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; + } + ++ // Paper start - Properly cancel usable items ++ public void resyncUsingItem(ServerPlayer serverPlayer) { ++ this.resendPossiblyDesyncedDataValues(java.util.List.of(DATA_LIVING_ENTITY_FLAGS), serverPlayer); ++ } ++ // Paper end - Properly cancel usable items + private void updatingUsingItem() { + if (this.isUsingItem()) { + if (ItemStack.isSameItem(this.getItemInHand(this.getUsedItemHand()), this.useItem)) { +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 b586116d8cca1585f9c9e618ed4d0cb2ef2747be..acf38ef6d8de8b15cf2b09eb7bda390c4e446e9a 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Bucketable.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Bucketable.java +@@ -108,8 +108,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 +- entity.getBukkitEntity().update((ServerPlayer) player); // We need to play out these packets as the client assumes the fish is gone +- entity.refreshEntityData((ServerPlayer) player); // Need to send data such as the display name to client ++ entity.resendPossiblyDesyncedEntityData((ServerPlayer) player); // Paper + return Optional.of(InteractionResult.FAIL); + } + entity.playSound(((Bucketable) entity).getPickupSound(), 1.0F, 1.0F); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index b8eb9166e44da8745a056bf68f2f9316ce25d7a7..2cde808bfa797256409879505ba205a71f381981 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -1012,7 +1012,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + return; + } + +- entityTracker.broadcast(this.getHandle().getAddEntityPacket(entityTracker.serverEntity)); ++ // Paper start - resend possibly desynced entity instead of add entity packet ++ for (final ServerPlayerConnection connection : entityTracker.seenBy) { ++ this.getHandle().resendPossiblyDesyncedEntityData(connection.getPlayer()); ++ } ++ // Paper end - resend possibly desynced entity instead of add entity packet + } + + public void update(ServerPlayer player) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java +index f3a9b3380246fb2dd4b60a8d1a94c5dfed98d316..350ad61ab3fe66abd528e353b431a4a6dac17506 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java +@@ -39,9 +39,11 @@ public class CraftItemFrame extends CraftHanging implements ItemFrame { + protected void update() { + super.update(); + ++ // Paper start, don't mark as dirty as this is handled in super.update() + // mark dirty, so that the client gets updated with item and rotation +- this.getHandle().getEntityData().markDirty(net.minecraft.world.entity.decoration.ItemFrame.DATA_ITEM); +- this.getHandle().getEntityData().markDirty(net.minecraft.world.entity.decoration.ItemFrame.DATA_ROTATION); ++ //this.getHandle().getEntityData().markDirty(net.minecraft.world.entity.decoration.ItemFrame.DATA_ITEM); ++ //this.getHandle().getEntityData().markDirty(net.minecraft.world.entity.decoration.ItemFrame.DATA_ROTATION); ++ // Paper end + + // update redstone + if (!this.getHandle().generation) { |