Fix zone batch update sync causing floor item ghosting - #1135
Conversation
- Send active zone before individual updates so they can't apply to the wrong zone - Clear encoded batches each tick to stop last tick's updates being resent on zone change - Skip zones outside the loaded map instead of clamping offsets - Defer zone content resend until the client confirms the map has loaded - Version dynamic zone changes to prevent duplicate region updates in one tick Closes GregHib#1000
Client reads packet 41 as y (inverse), level (add), x (add); the unused encoder wrote x first, offsetting private updates by a zone whenever the player wasn't diagonal-symmetric to the map centre.
|
Found and fixed in a99c656. the Verified against the deob: opcode 33 and 48 read orders match the existing |
GregHib
left a comment
There was a problem hiding this comment.
Tested the original scenario along with common situations with multiple players and instances. LGTM!
Golden bytes were recorded from the unverified encoder; y-first order now matches the client and the clear zone packet convention.
Closes #1000, #1087
Root cause is a set of sync gaps in the zone batch update pipeline rather than floor items specifically, items were just the visible symptom since spawns constantly re-queue additions.
Screencast_20260805_143328.webm
Problems
privateand sent as bare single packets, which the client applies relative to its active zone, set by whateverclearZone/batch header happened to come last. When that pointer pointed at a neighbouring zone, the item rendered one zone (8 tiles) off in the direction of travel.getZoneOffsetusedsafeMinus, so zones south/west of the loaded map base clamped to offset 0 and rendered 8 tiles north/east of their true tile (reproducible with the logs at 3155 in zone389,394after logging in at3114,3209).encodedmap was never cleared, so mid-tick sends (region change/batch zone change) replayed the previous tick's batch, re-applying object add/removes (door flicker on the Wizards' Tower bridge) and duplicating item additions. This affects objects just the same as items, as you noted — items only made it visible.updateRegionsent zone contents immediately after the map region packet, but the client loads maps asynchronously and drops zone updates in the window beforeFinishRegionLoad,viewport.loadedwas tracked but never gated anything, so items vanished after every region reload.checkReloadandDynamicZones.reloadCallbackcould both callupdateRegionin the same tick with no in-progress check, and two send paths with different anchors (lastBatchZonevssteps.previous.zone) cleared and resent the same entered zones twice per tick.Changes
UPDATE_ZONE) before individual private updates so they always apply to the correct zone (matches partial-follows behaviour before each bare update)encodedalongsidebatcheseach tick and skip encoding empty batches (also fixes unbounded growth)lastBatchZone; removed thesteps.previous-anchored duplicateFinishRegionLoadhandler, with sends gated onviewport.loadedso nothing is fired into the load windowDynamicZones.versionstamped on the viewport per region update socrossedDynamicBoarderno longer force-reloads players already updated for the current dynamic state