From d22f4b30ac05f7c64d22dfca373b0d113f3399e3 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Tue, 10 Mar 2026 08:38:39 -0700 Subject: [PATCH] game: process partial UPDATE_OBJECT packets when a block parse fails Previously, if any single block in an SMSG_UPDATE_OBJECT packet failed to parse (e.g. unusual spline flags), the entire packet was dropped and all entities in it were lost. On busy zones with many CREATE_OBJECTs in one packet, one bad NPC movement block would silently suppress all NPCs that followed it in the same packet. - parseUpdateObject: break instead of return false on block failure, so already-parsed blocks are returned to the caller - handleUpdateObject: fall through to process partial data when parsing returns false but some blocks were successfully parsed --- src/game/game_handler.cpp | 3 ++- src/game/world_packets.cpp | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index e0838a3c..76b4eb04 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -7327,7 +7327,8 @@ void GameHandler::handleUpdateObject(network::Packet& packet) { static int updateObjErrors = 0; if (++updateObjErrors <= 5) LOG_WARNING("Failed to parse SMSG_UPDATE_OBJECT"); - return; + if (data.blocks.empty()) return; + // Fall through: process any blocks that were successfully parsed before the failure. } auto extractPlayerAppearance = [&](const std::map& fields, diff --git a/src/game/world_packets.cpp b/src/game/world_packets.cpp index 69427728..7587cd65 100644 --- a/src/game/world_packets.cpp +++ b/src/game/world_packets.cpp @@ -1252,11 +1252,14 @@ bool UpdateObjectParser::parse(network::Packet& packet, UpdateObjectData& data) if (!parseUpdateBlock(packet, block)) { static int parseBlockErrors = 0; if (++parseBlockErrors <= 5) { - LOG_ERROR("Failed to parse update block ", i + 1); + LOG_ERROR("Failed to parse update block ", i + 1, " of ", data.blockCount, + " (", i, " blocks parsed successfully before failure)"); if (parseBlockErrors == 5) LOG_ERROR("(suppressing further update block parse errors)"); } - return false; + // Cannot reliably re-sync to the next block after a parse failure, + // but still return true so the blocks already parsed are processed. + break; } data.blocks.emplace_back(std::move(block));