From f577411a15b99d8cc41a23c553665e15c23b97dc Mon Sep 17 00:00:00 2001 From: Kelsi Davis Date: Sat, 4 Apr 2026 01:16:28 -0700 Subject: [PATCH] fix(chat): resolve /r reply target when name arrives after whisper Whisper sender name may not be in the player name cache when the packet arrives. Store the sender GUID and lazily resolve the name from the cache in getLastWhisperSender(). Also backfill lastWhisperSender_ when the SMSG_NAME_QUERY_RESPONSE arrives. --- assets/shaders/character.frag.spv | Bin 17632 -> 17488 bytes include/game/game_handler.hpp | 12 +++++++++++- src/game/chat_handler.cpp | 23 +++++++++++++++-------- src/game/entity_controller.cpp | 5 +++++ 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/assets/shaders/character.frag.spv b/assets/shaders/character.frag.spv index f970ac7cfaa372c9f83b94572e6aea8b0bcdf821..43789272f26cf2430fef49603a82af4bbb54dbe4 100644 GIT binary patch literal 17488 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 + } + return ""; + } void setLastWhisperSender(const std::string& name) { lastWhisperSender_ = name; } // Party/Raid management @@ -2436,6 +2445,7 @@ private: std::string afkMessage_; std::string dndMessage_; std::string lastWhisperSender_; + uint64_t lastWhisperSenderGuid_ = 0; // ---- Online item tracking ---- struct OnlineItemInfo { diff --git a/src/game/chat_handler.cpp b/src/game/chat_handler.cpp index ec9d6e46..0c3dcd83 100644 --- a/src/game/chat_handler.cpp +++ b/src/game/chat_handler.cpp @@ -255,15 +255,22 @@ void ChatHandler::handleMessageChat(network::Packet& packet) { } // Track whisper sender for /r command - if (data.type == ChatType::WHISPER && !data.senderName.empty()) { - owner_.lastWhisperSender_ = data.senderName; + if (data.type == ChatType::WHISPER) { + // Always store GUID so getLastWhisperSender() can resolve the name + // from the player name cache even if name wasn't available yet + if (data.senderGuid != 0) + owner_.lastWhisperSenderGuid_ = data.senderGuid; + if (!data.senderName.empty()) + owner_.lastWhisperSender_ = data.senderName; - if (owner_.afkStatus_ && !data.senderName.empty()) { - std::string reply = owner_.afkMessage_.empty() ? "Away from Keyboard" : owner_.afkMessage_; - sendChatMessage(ChatType::WHISPER, " " + reply, data.senderName); - } else if (owner_.dndStatus_ && !data.senderName.empty()) { - std::string reply = owner_.dndMessage_.empty() ? "Do Not Disturb" : owner_.dndMessage_; - sendChatMessage(ChatType::WHISPER, " " + reply, data.senderName); + if (!data.senderName.empty()) { + if (owner_.afkStatus_) { + std::string reply = owner_.afkMessage_.empty() ? "Away from Keyboard" : owner_.afkMessage_; + sendChatMessage(ChatType::WHISPER, " " + reply, data.senderName); + } else if (owner_.dndStatus_) { + std::string reply = owner_.dndMessage_.empty() ? "Do Not Disturb" : owner_.dndMessage_; + sendChatMessage(ChatType::WHISPER, " " + reply, data.senderName); + } } } diff --git a/src/game/entity_controller.cpp b/src/game/entity_controller.cpp index 6a9cc826..f788fca3 100644 --- a/src/game/entity_controller.cpp +++ b/src/game/entity_controller.cpp @@ -1988,6 +1988,11 @@ void EntityController::handleNameQueryResponse(network::Packet& packet) { } } + // Backfill whisper reply target if the name arrived after the whisper. + if (owner_.lastWhisperSenderGuid_ == data.guid && owner_.lastWhisperSender_.empty()) { + owner_.lastWhisperSender_ = data.name; + } + // Backfill mail inbox sender names for (auto& mail : owner_.mailInbox_) { if (mail.messageType == 0 && mail.senderGuid == data.guid) {