From febd7d08ee86d9f78906bcd1614ec5026aa78b78 Mon Sep 17 00:00:00 2001 From: neonjava Date: Sun, 4 Oct 2026 19:56:57 +0530 Subject: [PATCH 1/2] Fix trader leash desync after tracking resumes --- .../server/level/ChunkMap.java.patch | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch index 7a827cb0798c..41c6c1c71871 100644 --- a/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch @@ -1,5 +1,25 @@ --- a/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java +@@ -58,6 +_,7 @@ + import net.minecraft.network.protocol.game.ClientGamePacketListener; + import net.minecraft.network.protocol.game.ClientboundChunksBiomesPacket; + import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket; ++import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; + import net.minecraft.resources.Identifier; + import net.minecraft.resources.ResourceKey; + import net.minecraft.server.network.ServerPlayerConnection; +@@ -73,9 +_,11 @@ + import net.minecraft.util.thread.ConsecutiveExecutor; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.Leashable; + import net.minecraft.world.entity.UpdateInterval; + import net.minecraft.world.entity.ai.village.poi.PoiManager; + import net.minecraft.world.entity.boss.enderdragon.EnderDragonPart; ++import net.minecraft.world.entity.npc.wanderingtrader.WanderingTrader; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.TicketStorage; @@ -151,6 +_,33 @@ public int serverViewDistance; private final WorldGenContext worldGenContext; @@ -311,7 +331,7 @@ if (this.seenBy.remove(player.connection)) { this.serverEntity.removePairing(player); if (this.seenBy.isEmpty()) { -@@ -1382,23 +_,47 @@ +@@ -1382,23 +_,58 @@ } public void updatePlayer(final ServerPlayer player) { @@ -352,6 +372,17 @@ + // Paper start - entity tracking events + if (io.papermc.paper.event.player.PlayerTrackEntityEvent.getHandlerList().getRegisteredListeners().length == 0 || new io.papermc.paper.event.player.PlayerTrackEntityEvent(player.getBukkitEntity(), this.entity.getBukkitEntity()).callEvent()) { this.serverEntity.addPairing(player); ++ // Paper start - Resend trader leashes when the holder returns to tracking range ++ if (this.entity instanceof WanderingTrader) { ++ for (Leashable leashed : Leashable.leashableLeashedTo(this.entity)) { ++ Entity leashedEntity = (Entity) leashed; ++ TrackedEntity leashedTracker = ChunkMap.this.entityMap.get(leashedEntity.getId()); ++ if (leashedTracker != null && leashedTracker.seenBy.contains(player.connection)) { ++ player.connection.send(new ClientboundSetEntityLinkPacket(leashedEntity, this.entity)); ++ } ++ } ++ } ++ // Paper end - Resend trader leashes when the holder returns to tracking range if (this.seenBy.size() == 1) { ChunkMap.this.level.debugSynchronizers().registerEntity(this.entity); } From 8ed86856fd5d182f6c90be6e8067510bd8f03741 Mon Sep 17 00:00:00 2001 From: neonjava Date: Thu, 22 Oct 2026 20:21:41 +0530 Subject: [PATCH 2/2] Resend leashes when their holder starts tracking --- .../0003-Moonrise-optimisation-patches.patch | 60 +++++++++---------- .../0029-Optional-per-player-mob-spawns.patch | 6 +- ...ng-PreCreatureSpawnEvent-with-per-pl.patch | 6 +- ...er-desync-when-new-players-are-added.patch | 4 +- .../server/level/ChunkMap.java.patch | 22 ++----- 5 files changed, 44 insertions(+), 54 deletions(-) diff --git a/paper-server/patches/features/0003-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0003-Moonrise-optimisation-patches.patch index 0a83e293640c..47eb7cddd92d 100644 --- a/paper-server/patches/features/0003-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0003-Moonrise-optimisation-patches.patch @@ -297,7 +297,7 @@ index 0000000000000000000000000000000000000000..fff7a796a61542213bdaa417d44e25cd + } +} diff --git a/ca/spottedleaf/moonrise/paper/PaperHooks.java b/ca/spottedleaf/moonrise/paper/PaperHooks.java -index 4a62c50d0b4fe82c3aacaa56b303b9699120c778..92238518c25dd765b356ff628fd373997464ea82 100644 +index aa14dd369d5d2c5c843839f289afdc39c200f0c3..76f990f150f040b1ad6d7d5b91cfb34ebd6f436a 100644 --- a/ca/spottedleaf/moonrise/paper/PaperHooks.java +++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java @@ -13,6 +13,7 @@ import net.minecraft.server.level.ChunkHolder; @@ -25232,10 +25232,10 @@ index e3df851be4b31950018406dfa74f06635d636f51..cd5a325d37f617431ceb568a65570160 @FunctionalInterface diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java -index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f4771d6b142 100644 +index a8e52743529e26949dcb855a7c639c7c7185f8a1..4b9f128c3a3938ae3b0468b67367d2cacf5ce648 100644 --- a/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java -@@ -124,10 +124,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -126,10 +126,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP public static final int MIN_VIEW_DISTANCE = 2; public static final int MAX_VIEW_DISTANCE = 32; public static final int FORCED_TICKET_LEVEL = ChunkLevel.byStatus(FullChunkStatus.ENTITY_TICKING); @@ -25247,7 +25247,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 public final ServerLevel level; private final ThreadedLevelLightEngine lightEngine; private final BlockableEventLoop mainThreadExecutor; -@@ -137,19 +134,15 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -139,19 +136,15 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP private final PoiManager poiManager; public final LongSet toDrop = new LongOpenHashSet(); private boolean modified; @@ -25270,7 +25270,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() public final CallbackExecutor callbackExecutor = new CallbackExecutor(); -@@ -174,7 +167,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -176,7 +169,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP // Paper start public final ChunkHolder getUnloadingChunkHolder(int chunkX, int chunkZ) { @@ -25279,7 +25279,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 } // Paper end -@@ -222,9 +215,9 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -224,9 +217,9 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP ConsecutiveExecutor worldgen = new ConsecutiveExecutor(executor, "worldgen"); this.chunkStatusListener = chunkStatusListener; ConsecutiveExecutor light = new ConsecutiveExecutor(executor, "light"); @@ -25292,7 +25292,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 this.distanceManager = new ChunkMap.DistanceManager(ticketStorage, executor, mainThreadExecutor); this.ticketStorage = ticketStorage; this.poiManager = new PoiManager( -@@ -237,11 +230,11 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -239,11 +232,11 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP level ); this.setServerViewDistance(serverViewDistance); @@ -25306,7 +25306,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 } // Paper start -@@ -263,23 +256,11 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -265,23 +258,11 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP } public boolean isChunkTracked(final ServerPlayer player, final int chunkX, final int chunkZ) { @@ -25332,7 +25332,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 } protected ThreadedLevelLightEngine getLightEngine() { -@@ -287,11 +268,17 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -289,11 +270,17 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP } public @Nullable ChunkHolder getUpdatingChunkIfPresent(final long key) { @@ -25352,7 +25352,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 } public @Nullable ChunkStatus getLatestStatus(final long key) { -@@ -300,12 +287,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -302,12 +289,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP } protected IntSupplier getChunkQueueLevel(final long pos) { @@ -25366,7 +25366,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 } public String getChunkDebugData(final ChunkPos pos) { -@@ -333,47 +315,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -335,47 +317,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP CompletableFuture>> getChunkRangeFuture( final ChunkHolder centerChunk, final int range, final IntFunction distanceToStatus ) { @@ -25415,7 +25415,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 } public ReportedException debugFuturesAndCreateReportedException(final IllegalStateException exception, final String details) { -@@ -397,92 +339,28 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -399,92 +341,28 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP } public CompletableFuture> prepareEntityTickingChunk(final ChunkHolder chunk) { @@ -25517,7 +25517,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 } protected void tick(final BooleanSupplier haveTime) { -@@ -498,129 +376,28 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -500,129 +378,28 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP } public boolean hasWork() { @@ -25654,7 +25654,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 } private ChunkAccess handleChunkLoadFailure(final Throwable throwable, final ChunkPos pos) { -@@ -658,231 +435,139 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -660,231 +437,139 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP @Override public GenerationChunkHolder acquireGeneration(final long chunkNode) { @@ -25959,7 +25959,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 public @Nullable LevelChunk getChunkToSend(final long key) { ChunkHolder chunkHolder = this.getVisibleChunkIfPresent(key); return chunkHolder == null ? null : chunkHolder.getChunkToSend(); -@@ -964,7 +649,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -966,7 +651,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP return this.read(pos).thenApplyAsync(chunkTag -> chunkTag.map(this::upgradeChunkTag), Util.backgroundExecutor().forName("upgradeChunk")); } @@ -25968,7 +25968,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 return this.upgradeChunkTag( tag, -1, -@@ -981,23 +666,66 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -983,23 +668,66 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP return contextTag; } @@ -26044,7 +26044,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 if (holder != null) { LevelChunk chunk = holder.getTickingChunk(); if (chunk != null) { -@@ -1013,8 +741,8 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -1015,8 +743,8 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP } boolean anyPlayerCloseEnoughForSpawning(final ChunkPos pos, boolean reducedRange) { @@ -26055,7 +26055,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 // Spigot end } -@@ -1038,7 +766,20 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -1040,7 +768,20 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP private boolean anyPlayerCloseEnoughForSpawningInternal(final ChunkPos pos, final boolean reducedRange) { double blockRange; // Paper - use from event // Spigot end @@ -26077,7 +26077,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 // Paper start - PlayerNaturallySpawnCreaturesEvent com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; blockRange = 16384.0; -@@ -1054,26 +795,41 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -1056,26 +797,41 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP } return false; @@ -26128,7 +26128,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 if (player.isSpectator()) { return false; } -@@ -1111,18 +867,20 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -1113,18 +869,20 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP this.updatePlayerPos(player); if (!ignored) { this.distanceManager.addPlayer(SectionPos.of(player), player); @@ -26151,7 +26151,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 } } -@@ -1132,13 +890,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -1134,13 +892,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP } public void move(final ServerPlayer player) { @@ -26166,7 +26166,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 SectionPos oldSection = player.getLastSectionPos(); SectionPos newSection = SectionPos.of(player); -@@ -1147,6 +899,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -1149,6 +901,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP boolean positionChanged = oldSection.asLong() != newSection.asLong(); if (positionChanged || wasIgnored != ignored) { this.updatePlayerPos(player); @@ -26174,7 +26174,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 if (!wasIgnored) { this.distanceManager.removePlayer(oldSection, player); } -@@ -1163,47 +916,29 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -1165,47 +918,29 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP this.playerMap.unIgnorePlayer(player); } @@ -26233,7 +26233,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 } public boolean hasEntityWithId(final int id) { -@@ -1232,6 +967,14 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -1234,6 +969,14 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP UpdateInterval updateInterval = type.hasUpdateInterval() ? UpdateInterval.periodic(type.updateInterval()) : UpdateInterval.NEVER; ChunkMap.TrackedEntity trackedEntity = new ChunkMap.TrackedEntity(entity, range, updateInterval, type.trackDeltas()); this.entityMap.put(entity.getId(), trackedEntity); @@ -26248,7 +26248,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 trackedEntity.updatePlayers(this.level.players()); if (entity instanceof ServerPlayer player) { this.updatePlayerStatus(player, true); -@@ -1260,12 +1003,92 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -1262,12 +1005,92 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP if (trackedEntity != null) { trackedEntity.broadcastRemoved(); } @@ -26343,7 +26343,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 List movedPlayers = Lists.newArrayList(); List players = this.level.players(); -@@ -1360,17 +1183,11 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -1362,17 +1185,11 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP } public void waitForLightBeforeSending(final ChunkPos centerChunk, final int chunkRadius) { @@ -26363,7 +26363,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 LevelChunk chunk = chunkHolder.getChunkToSend(); if (chunk != null) { consumer.accept(chunk); -@@ -1378,14 +1195,21 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -1380,14 +1197,21 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP } } @@ -26387,7 +26387,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 } @Override -@@ -1399,13 +1223,96 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -1401,13 +1225,96 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP } } @@ -26485,7 +26485,7 @@ index a71bb2cb640b9e94386643a439e3d731417fc24c..0a60283625536515bfcf6c2a09ca0f47 public TrackedEntity(final Entity entity, final int range, final UpdateInterval updateInterval, final boolean trackDelta) { this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this, this.seenBy); // Paper this.entity = entity; -@@ -1517,17 +1424,24 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -1524,17 +1431,24 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP } private int getEffectiveRange() { @@ -28511,7 +28511,7 @@ index 47a0e17e4fed94828e02c7f4159d32195158f6cc..46e7478bd96e42487cf0fc467b6b9b83 "Server weather", () -> String.format( diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index bae5ed2cdd6627a0934f0a7bbf85621db5bed2d8..b3b00964d91804f108b7bc5b5ffc853a2ac62f16 100644 +index 3272f89607e6fd4f2fee223ecefde0774f0a0c1f..b3132c6dde9b371e9580458cd7602ceaeca29945 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -210,7 +210,7 @@ import net.minecraft.world.scores.criteria.ObjectiveCriteria; diff --git a/paper-server/patches/features/0029-Optional-per-player-mob-spawns.patch b/paper-server/patches/features/0029-Optional-per-player-mob-spawns.patch index 0438b8dbd6f4..a8a2cb6fd2cd 100644 --- a/paper-server/patches/features/0029-Optional-per-player-mob-spawns.patch +++ b/paper-server/patches/features/0029-Optional-per-player-mob-spawns.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Optional per player mob spawns diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java -index 0a60283625536515bfcf6c2a09ca0f4771d6b142..42500899812fe3ef18c09f68a85012b705c1010d 100644 +index 4b9f128c3a3938ae3b0468b67367d2cacf5ce648..ec44ea0fda689f8a721660503e45ee53da6ba5a5 100644 --- a/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java -@@ -237,11 +237,29 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -239,11 +239,29 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP // Paper - rewrite chunk system } @@ -75,7 +75,7 @@ index 2dc8b94c434e841b319ef5b77bd725fd66f3c10b..a5540612a4052d9e9d8b1b0ac3c15917 profiler.popPush("tickSpawningChunks"); diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 2cf8854636df72c1dccbb73dfe8f642dfdf1ea37..99403edc1eda1e238b66028b7d236e5fceb235a1 100644 +index 8fe1f113203b27cee20bd8fddd6492e087064c2a..26cea80a358e6de87fa23f62d29992a1dad8344e 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -422,6 +422,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc diff --git a/paper-server/patches/features/0030-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch b/paper-server/patches/features/0030-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch index c10e34855095..d3c740efae59 100644 --- a/paper-server/patches/features/0030-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch +++ b/paper-server/patches/features/0030-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Improve cancelling PreCreatureSpawnEvent with per player mob diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java -index 42500899812fe3ef18c09f68a85012b705c1010d..fdcbf132e2045bc6828028556ca4c3549d9abec7 100644 +index ec44ea0fda689f8a721660503e45ee53da6ba5a5..1aef03c22dd4e6a96aa1fe492728e37dd71c2763 100644 --- a/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java -@@ -256,8 +256,25 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -258,8 +258,25 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP } } @@ -60,7 +60,7 @@ index a5540612a4052d9e9d8b1b0ac3c1591777f26caa..c4cfb53e145d69666ffc27ef4ee0c50b spawnCookie = NaturalSpawner.createState(chunkCount, this.level, this::getFullChunk, null, true); } else { diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 99403edc1eda1e238b66028b7d236e5fceb235a1..23b3a82ab3e1c6abc85000d9285470cb12300a6b 100644 +index 26cea80a358e6de87fa23f62d29992a1dad8344e..119236a8b3ad2d6d81a816d6abdc2b809a753eff 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -426,6 +426,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc diff --git a/paper-server/patches/features/0033-Fix-entity-tracker-desync-when-new-players-are-added.patch b/paper-server/patches/features/0033-Fix-entity-tracker-desync-when-new-players-are-added.patch index c14a1475cbd2..a91cf77cb937 100644 --- a/paper-server/patches/features/0033-Fix-entity-tracker-desync-when-new-players-are-added.patch +++ b/paper-server/patches/features/0033-Fix-entity-tracker-desync-when-new-players-are-added.patch @@ -48,10 +48,10 @@ index cff05f64af7f425b77cbbd7680c5cc592faa798c..0ab4080c8e30d5ee14ce5fcbac64b031 serverEntity.getLastSentYRot(), entity.getType(), diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java -index fdcbf132e2045bc6828028556ca4c3549d9abec7..fd0b9f20fbdd523d51550fd6009b5011e6e7e6e6 100644 +index 1aef03c22dd4e6a96aa1fe492728e37dd71c2763..0ccf43ae9dbb97718339b4e9ac11ccbe4b37059f 100644 --- a/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java -@@ -1447,6 +1447,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP +@@ -1454,6 +1454,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP ChunkMap.this.level.debugSynchronizers().startTrackingEntity(player, this.entity); } // Paper end - entity tracking events diff --git a/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch index 41c6c1c71871..fee8262c8304 100644 --- a/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch @@ -8,7 +8,7 @@ import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; import net.minecraft.server.network.ServerPlayerConnection; -@@ -73,9 +_,11 @@ +@@ -73,6 +_,7 @@ import net.minecraft.util.thread.ConsecutiveExecutor; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; @@ -16,10 +16,6 @@ import net.minecraft.world.entity.UpdateInterval; import net.minecraft.world.entity.ai.village.poi.PoiManager; import net.minecraft.world.entity.boss.enderdragon.EnderDragonPart; -+import net.minecraft.world.entity.npc.wanderingtrader.WanderingTrader; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.Level; - import net.minecraft.world.level.TicketStorage; @@ -151,6 +_,33 @@ public int serverViewDistance; private final WorldGenContext worldGenContext; @@ -331,7 +327,7 @@ if (this.seenBy.remove(player.connection)) { this.serverEntity.removePairing(player); if (this.seenBy.isEmpty()) { -@@ -1382,23 +_,58 @@ +@@ -1382,23 +_,52 @@ } public void updatePlayer(final ServerPlayer player) { @@ -372,17 +368,11 @@ + // Paper start - entity tracking events + if (io.papermc.paper.event.player.PlayerTrackEntityEvent.getHandlerList().getRegisteredListeners().length == 0 || new io.papermc.paper.event.player.PlayerTrackEntityEvent(player.getBukkitEntity(), this.entity.getBukkitEntity()).callEvent()) { this.serverEntity.addPairing(player); -+ // Paper start - Resend trader leashes when the holder returns to tracking range -+ if (this.entity instanceof WanderingTrader) { -+ for (Leashable leashed : Leashable.leashableLeashedTo(this.entity)) { -+ Entity leashedEntity = (Entity) leashed; -+ TrackedEntity leashedTracker = ChunkMap.this.entityMap.get(leashedEntity.getId()); -+ if (leashedTracker != null && leashedTracker.seenBy.contains(player.connection)) { -+ player.connection.send(new ClientboundSetEntityLinkPacket(leashedEntity, this.entity)); -+ } -+ } ++ // Paper start - Resend leashes when the holder starts being tracked ++ for (Leashable leashed : Leashable.leashableLeashedTo(this.entity)) { ++ player.connection.send(new ClientboundSetEntityLinkPacket((Entity) leashed, this.entity)); + } -+ // Paper end - Resend trader leashes when the holder returns to tracking range ++ // Paper end - Resend leashes when the holder starts being tracked if (this.seenBy.size() == 1) { ChunkMap.this.level.debugSynchronizers().registerEntity(this.entity); }