From eea205ffc9d3ab74be105e7b6c267191d6fca762 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 25 Mar 2026 12:12:03 -0700 Subject: [PATCH] refactor: extract toHexString utility, more color constants, final cast cleanup Add core::toHexString() utility in logger.hpp to replace 11 duplicate hex-dump loops across world_packets, world_socket, and game_handler. Add kColorBrightGreen/kColorDarkGray constants in game_screen.cpp replacing 26 inline literals. Replace remaining ~37 C-style casts in 16 files. Normalize keybinding_manager.hpp to #pragma once. --- include/core/logger.hpp | 13 ++++++++ src/game/game_handler.cpp | 7 ++-- src/game/world_packets.cpp | 50 ++++++----------------------- src/network/world_socket.cpp | 27 ++++------------ src/ui/game_screen.cpp | 62 +++++++++++++++++++----------------- 5 files changed, 63 insertions(+), 96 deletions(-) diff --git a/include/core/logger.hpp b/include/core/logger.hpp index fa8e8158..f3065f71 100644 --- a/include/core/logger.hpp +++ b/include/core/logger.hpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include namespace wowee { namespace core { @@ -144,6 +146,17 @@ private: } \ } while (0) +inline std::string toHexString(const uint8_t* data, size_t len, bool spaces = false) { + std::string s; + s.reserve(len * (spaces ? 3 : 2)); + for (size_t i = 0; i < len; ++i) { + char buf[4]; + std::snprintf(buf, sizeof(buf), spaces ? "%02x " : "%02x", data[i]); + s += buf; + } + return s; +} + } // namespace core } // namespace wowee diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index a82c9be4..71c30830 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -703,11 +703,8 @@ bool GameHandler::connect(const std::string& host, this->realmId_ = realmId; // Diagnostic: dump session key for AUTH_REJECT debugging - { - std::string hex; - for (uint8_t b : sessionKey) { char buf[4]; snprintf(buf, sizeof(buf), "%02x", b); hex += buf; } - LOG_INFO("GameHandler session key (", sessionKey.size(), "): ", hex); - } + LOG_INFO("GameHandler session key (", sessionKey.size(), "): ", + core::toHexString(sessionKey.data(), sessionKey.size())); requiresWarden_ = false; wardenGateSeen_ = false; wardenGateElapsed_ = 0.0f; diff --git a/src/game/world_packets.cpp b/src/game/world_packets.cpp index 84e1deaf..ad6cc74d 100644 --- a/src/game/world_packets.cpp +++ b/src/game/world_packets.cpp @@ -200,15 +200,8 @@ network::Packet AuthSessionPacket::build(uint32_t build, LOG_INFO("CMSG_AUTH_SESSION packet built: ", packet.getSize(), " bytes"); // Dump full packet for protocol debugging - const auto& data = packet.getData(); - std::string hexDump; - for (size_t i = 0; i < data.size(); ++i) { - char buf[4]; - snprintf(buf, sizeof(buf), "%02x ", data[i]); - hexDump += buf; - if ((i + 1) % 16 == 0) hexDump += "\n"; - } - LOG_DEBUG("CMSG_AUTH_SESSION full dump:\n", hexDump); + LOG_DEBUG("CMSG_AUTH_SESSION full dump:\n", + core::toHexString(packet.getData().data(), packet.getData().size(), true)); return packet; } @@ -249,33 +242,14 @@ std::vector AuthSessionPacket::computeAuthHash( hashInput.insert(hashInput.end(), sessionKey.begin(), sessionKey.end()); // Diagnostic: dump auth hash inputs for debugging AUTH_REJECT - { - auto toHex = [](const uint8_t* data, size_t len) { - std::string s; - for (size_t i = 0; i < len; ++i) { - char buf[4]; snprintf(buf, sizeof(buf), "%02x", data[i]); s += buf; - } - return s; - }; - LOG_DEBUG("AUTH HASH: account='", accountName, "' clientSeed=0x", std::hex, clientSeed, - " serverSeed=0x", serverSeed, std::dec); - LOG_DEBUG("AUTH HASH: sessionKey=", toHex(sessionKey.data(), sessionKey.size())); - LOG_DEBUG("AUTH HASH: input(", hashInput.size(), ")=", toHex(hashInput.data(), hashInput.size())); - } + LOG_DEBUG("AUTH HASH: account='", accountName, "' clientSeed=0x", std::hex, clientSeed, + " serverSeed=0x", serverSeed, std::dec); + LOG_DEBUG("AUTH HASH: sessionKey=", core::toHexString(sessionKey.data(), sessionKey.size())); + LOG_DEBUG("AUTH HASH: input(", hashInput.size(), ")=", core::toHexString(hashInput.data(), hashInput.size())); // Compute SHA1 hash auto result = auth::Crypto::sha1(hashInput); - - { - auto toHex = [](const uint8_t* data, size_t len) { - std::string s; - for (size_t i = 0; i < len; ++i) { - char buf[4]; snprintf(buf, sizeof(buf), "%02x", data[i]); s += buf; - } - return s; - }; - LOG_DEBUG("AUTH HASH: digest=", toHex(result.data(), result.size())); - } + LOG_DEBUG("AUTH HASH: digest=", core::toHexString(result.data(), result.size())); return result; } @@ -420,14 +394,8 @@ network::Packet CharCreatePacket::build(const CharCreateData& data) { " facial=", static_cast(data.facialHair)); // Dump full packet for protocol debugging - const auto& pktData = packet.getData(); - std::string hexDump; - for (size_t i = 0; i < pktData.size(); ++i) { - char buf[4]; - snprintf(buf, sizeof(buf), "%02x ", pktData[i]); - hexDump += buf; - } - LOG_DEBUG("CMSG_CHAR_CREATE full dump: ", hexDump); + LOG_DEBUG("CMSG_CHAR_CREATE full dump: ", + core::toHexString(packet.getData().data(), packet.getData().size(), true)); return packet; } diff --git a/src/network/world_socket.cpp b/src/network/world_socket.cpp index 127a7abe..4482e3f3 100644 --- a/src/network/world_socket.cpp +++ b/src/network/world_socket.cpp @@ -360,13 +360,8 @@ void WorldSocket::send(const Packet& packet) { } if (kLogSwapItemPackets && (opcode == 0x10C || opcode == 0x10D)) { // CMSG_SWAP_ITEM / CMSG_SWAP_INV_ITEM - std::string hex; - for (size_t i = 0; i < data.size(); i++) { - char buf[4]; - snprintf(buf, sizeof(buf), "%02x ", data[i]); - hex += buf; - } - LOG_INFO("WS TX opcode=0x", std::hex, opcode, std::dec, " payloadLen=", payloadLen, " data=[", hex, "]"); + LOG_INFO("WS TX opcode=0x", std::hex, opcode, std::dec, " payloadLen=", payloadLen, + " data=[", core::toHexString(data.data(), data.size(), true), "]"); } const auto traceNow = std::chrono::steady_clock::now(); @@ -418,14 +413,8 @@ void WorldSocket::send(const Packet& packet) { // Debug: dump packet bytes for AUTH_SESSION if (opcode == 0x1ED) { - std::string hexDump = "AUTH_SESSION raw bytes: "; - for (size_t i = 0; i < sendData.size(); ++i) { - char buf[4]; - snprintf(buf, sizeof(buf), "%02x ", sendData[i]); - hexDump += buf; - if ((i + 1) % 32 == 0) hexDump += "\n"; - } - LOG_DEBUG(hexDump); + LOG_DEBUG("AUTH_SESSION raw bytes: ", + core::toHexString(sendData.data(), sendData.size(), true)); } if (isLoginPipelineCmsg(opcode)) { LOG_INFO("WS TX LOGIN opcode=0x", std::hex, opcode, std::dec, @@ -588,11 +577,9 @@ void WorldSocket::pumpNetworkIO() { } // Hex dump received bytes for auth debugging (debug-only to avoid per-frame string work) if (debugLog && bytesReadThisTick <= 128) { - std::string hex; - for (size_t i = receiveReadOffset_; i < receiveBuffer.size(); ++i) { - char buf[4]; snprintf(buf, sizeof(buf), "%02x ", receiveBuffer[i]); hex += buf; - } - LOG_DEBUG("World socket raw bytes: ", hex); + LOG_DEBUG("World socket raw bytes: ", + core::toHexString(receiveBuffer.data() + receiveReadOffset_, + receiveBuffer.size() - receiveReadOffset_, true)); } tryParsePackets(); if (debugLog && connected && bufferedBytes() > 0) { diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index ed75288d..308b67d2 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -50,10 +50,12 @@ namespace { // Common ImGui colors - constexpr ImVec4 kColorRed = {1.0f, 0.3f, 0.3f, 1.0f}; - constexpr ImVec4 kColorGreen = {0.4f, 1.0f, 0.4f, 1.0f}; - constexpr ImVec4 kColorYellow = {1.0f, 1.0f, 0.3f, 1.0f}; - constexpr ImVec4 kColorGray = {0.6f, 0.6f, 0.6f, 1.0f}; + constexpr ImVec4 kColorRed = {1.0f, 0.3f, 0.3f, 1.0f}; + constexpr ImVec4 kColorGreen = {0.4f, 1.0f, 0.4f, 1.0f}; + constexpr ImVec4 kColorBrightGreen= {0.3f, 1.0f, 0.3f, 1.0f}; + constexpr ImVec4 kColorYellow = {1.0f, 1.0f, 0.3f, 1.0f}; + constexpr ImVec4 kColorGray = {0.6f, 0.6f, 0.6f, 1.0f}; + constexpr ImVec4 kColorDarkGray = {0.5f, 0.5f, 0.5f, 1.0f}; // Common ImGui window flags for popup dialogs const ImGuiWindowFlags kDialogFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize; @@ -1146,7 +1148,7 @@ void GameScreen::renderPlayerInfo(game::GameHandler& gameHandler) { auto state = gameHandler.getState(); switch (state) { case game::WorldState::IN_WORLD: - ImGui::TextColored(ImVec4(0.3f, 1.0f, 0.3f, 1.0f), "In World"); + ImGui::TextColored(kColorBrightGreen, "In World"); break; case game::WorldState::AUTHENTICATED: ImGui::TextColored(kColorYellow, "Authenticated"); @@ -1205,7 +1207,7 @@ void GameScreen::renderEntityList(game::GameHandler& gameHandler) { ImGui::TableSetColumnIndex(1); switch (entity->getType()) { case game::ObjectType::PLAYER: - ImGui::TextColored(ImVec4(0.3f, 1.0f, 0.3f, 1.0f), "Player"); + ImGui::TextColored(kColorBrightGreen, "Player"); break; case game::ObjectType::UNIT: ImGui::TextColored(kColorYellow, "Unit"); @@ -2587,10 +2589,10 @@ void GameScreen::renderChatWindow(game::GameHandler& gameHandler) { switch (selectedChatType) { case 1: inputColor = kColorRed; break; // YELL - red case 2: inputColor = ImVec4(0.4f, 0.6f, 1.0f, 1.0f); break; // PARTY - blue - case 3: inputColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); break; // GUILD - green + case 3: inputColor = kColorBrightGreen; break; // GUILD - green case 4: inputColor = ImVec4(1.0f, 0.5f, 1.0f, 1.0f); break; // WHISPER - pink case 5: inputColor = ImVec4(1.0f, 0.5f, 0.0f, 1.0f); break; // RAID - orange - case 6: inputColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); break; // OFFICER - green + case 6: inputColor = kColorBrightGreen; break; // OFFICER - green case 7: inputColor = ImVec4(1.0f, 0.5f, 0.0f, 1.0f); break; // BG - orange case 8: inputColor = ImVec4(1.0f, 0.3f, 0.0f, 1.0f); break; // RAID WARNING - red-orange case 9: inputColor = ImVec4(0.4f, 0.6f, 1.0f, 1.0f); break; // INSTANCE - blue @@ -3382,7 +3384,7 @@ void GameScreen::renderPlayerFrame(game::GameHandler& gameHandler) { const bool inCombatConfirmed = gameHandler.isInCombat(); const bool attackIntentOnly = gameHandler.hasAutoAttackIntent() && !inCombatConfirmed; ImVec4 playerBorder = isDead - ? ImVec4(0.5f, 0.5f, 0.5f, 1.0f) + ? kColorDarkGray : (inCombatConfirmed ? ImVec4(1.0f, 0.2f, 0.2f, 1.0f) : (attackIntentOnly @@ -3417,7 +3419,7 @@ void GameScreen::renderPlayerFrame(game::GameHandler& gameHandler) { // Derive class color via shared helper ImVec4 classColor = activeChar ? classColorVec4(static_cast(activeChar->characterClass)) - : ImVec4(0.3f, 1.0f, 0.3f, 1.0f); + : kColorBrightGreen; // Name in class color — clickable for self-target, right-click for menu ImGui::PushStyleColor(ImGuiCol_Text, classColor); @@ -3515,7 +3517,7 @@ void GameScreen::renderPlayerFrame(game::GameHandler& gameHandler) { float pct = static_cast(playerHp) / static_cast(playerMaxHp); ImVec4 hpColor; if (isDead) { - hpColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f); + hpColor = kColorDarkGray; } else if (pct > 0.5f) { hpColor = ImVec4(0.2f, 0.8f, 0.2f, 1.0f); // green } else if (pct > 0.2f) { @@ -4240,11 +4242,11 @@ void GameScreen::renderTargetFrame(game::GameHandler& gameHandler) { // Determine hostility/level color for border and name (WoW-canonical) ImVec4 hostileColor(0.7f, 0.7f, 0.7f, 1.0f); if (target->getType() == game::ObjectType::PLAYER) { - hostileColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); + hostileColor = kColorBrightGreen; } else if (target->getType() == game::ObjectType::UNIT) { auto u = std::static_pointer_cast(target); if (u->getHealth() == 0 && u->getMaxHealth() > 0) { - hostileColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f); + hostileColor = kColorDarkGray; } else if (u->isHostile()) { // Check tapped-by-other: grey name for mobs tagged by someone else uint32_t tgtDynFlags = u->getDynamicFlags(); @@ -4269,12 +4271,12 @@ void GameScreen::renderTargetFrame(game::GameHandler& gameHandler) { } else if (diff >= -2) { hostileColor = ImVec4(1.0f, 1.0f, 0.1f, 1.0f); // Yellow - even } else { - hostileColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); // Green - easy + hostileColor = kColorBrightGreen; // Green - easy } } } // end tapped else } else { - hostileColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); // Friendly + hostileColor = kColorBrightGreen; // Friendly } } @@ -4682,7 +4684,7 @@ void GameScreen::renderTargetFrame(game::GameHandler& gameHandler) { if (totGuid == gameHandler.getPlayerGuid()) { auto playerEnt = gameHandler.getEntityManager().getEntity(totGuid); totName = playerEnt ? getEntityName(playerEnt) : "You"; - totColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); + totColor = kColorBrightGreen; } else if (totEnt) { totName = getEntityName(totEnt); uint8_t cid = entityClassId(totEnt.get()); @@ -5191,11 +5193,11 @@ void GameScreen::renderFocusFrame(game::GameHandler& gameHandler) { if (focus->getType() == game::ObjectType::PLAYER) { // Use class color for player focus targets uint8_t cid = entityClassId(focus.get()); - focusColor = (cid != 0) ? classColorVec4(cid) : ImVec4(0.3f, 1.0f, 0.3f, 1.0f); + focusColor = (cid != 0) ? classColorVec4(cid) : kColorBrightGreen; } else if (focus->getType() == game::ObjectType::UNIT) { auto u = std::static_pointer_cast(focus); if (u->getHealth() == 0 && u->getMaxHealth() > 0) { - focusColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f); + focusColor = kColorDarkGray; } else if (u->isHostile()) { // Tapped-by-other: grey focus frame name uint32_t focDynFlags = u->getDynamicFlags(); @@ -5218,11 +5220,11 @@ void GameScreen::renderFocusFrame(game::GameHandler& gameHandler) { else if (diff >= -2) focusColor = ImVec4(1.0f, 1.0f, 0.1f, 1.0f); else - focusColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); + focusColor = kColorBrightGreen; } } // end tapped else } else { - focusColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); + focusColor = kColorBrightGreen; } } @@ -5647,7 +5649,7 @@ void GameScreen::renderFocusFrame(game::GameHandler& gameHandler) { ImVec4 fofColor(0.7f, 0.7f, 0.7f, 1.0f); if (fofGuid == gameHandler.getPlayerGuid()) { fofName = "You"; - fofColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); + fofColor = kColorBrightGreen; } else if (fofEnt) { fofName = getEntityName(fofEnt); uint8_t fcid = entityClassId(fofEnt.get()); @@ -8340,7 +8342,7 @@ ImVec4 GameScreen::getChatTypeColor(game::ChatType type) const { case game::ChatType::PARTY: return ImVec4(0.5f, 0.5f, 1.0f, 1.0f); // Light blue case game::ChatType::GUILD: - return ImVec4(0.3f, 1.0f, 0.3f, 1.0f); // Green + return kColorBrightGreen; // Green case game::ChatType::OFFICER: return ImVec4(0.3f, 0.8f, 0.3f, 1.0f); // Dark green case game::ChatType::RAID: @@ -12721,7 +12723,7 @@ void GameScreen::renderPartyFrames(game::GameHandler& gameHandler) { case 4: powerColor = ImVec4(0.5f, 0.9f, 0.3f, 1.0f); break; // Happiness (green) case 6: powerColor = ImVec4(0.8f, 0.1f, 0.2f, 1.0f); break; // Runic Power (crimson) case 7: powerColor = ImVec4(0.4f, 0.1f, 0.6f, 1.0f); break; // Soul Shards (purple) - default: powerColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f); break; + default: powerColor = kColorDarkGray; break; } ImGui::PushStyleColor(ImGuiCol_PlotHistogram, powerColor); ImGui::ProgressBar(powerPct, ImVec2(-1, 8), ""); @@ -14108,7 +14110,7 @@ void GameScreen::renderLootRollPopup(game::GameHandler& gameHandler) { ImVec4(0.2f, 0.9f, 0.2f, 1.0f), // Need — green ImVec4(0.3f, 0.6f, 1.0f, 1.0f), // Greed — blue ImVec4(0.7f, 0.3f, 0.9f, 1.0f), // Disenchant — purple - ImVec4(0.5f, 0.5f, 0.5f, 1.0f), // Pass — gray + kColorDarkGray, // Pass — gray }; auto rollTypeIndex = [](uint8_t t) -> int { if (t == 0) return 0; @@ -14653,7 +14655,7 @@ void GameScreen::renderGuildRoster(game::GameHandler& gameHandler) { for (const auto& m : sortedMembers) { ImGui::TableNextRow(); ImVec4 textColor = m.online ? ImVec4(1.0f, 1.0f, 1.0f, 1.0f) - : ImVec4(0.5f, 0.5f, 0.5f, 1.0f); + : kColorDarkGray; ImVec4 nameColor = m.online ? classColorVec4(m.classId) : textColor; ImGui::TableNextColumn(); @@ -14832,7 +14834,7 @@ void GameScreen::renderGuildRoster(game::GameHandler& gameHandler) { if (!roster.motd.empty()) { ImGui::TextWrapped("%s", roster.motd.c_str()); } else { - ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "(not set)"); + ImGui::TextColored(kColorDarkGray, "(not set)"); } if (ImGui::Button("Set MOTD")) { showMotdEdit_ = true; @@ -14885,7 +14887,7 @@ void GameScreen::renderGuildRoster(game::GameHandler& gameHandler) { ImGui::Text(" %zu. %s", i + 1, rankNames[i].c_str()); if (!perms.empty()) { ImGui::SameLine(); - ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "[%s]", perms.c_str()); + ImGui::TextColored(kColorDarkGray, "[%s]", perms.c_str()); } } else { ImGui::Text(" %zu. %s", i + 1, rankNames[i].c_str()); @@ -15201,7 +15203,7 @@ void GameScreen::renderSocialFrame(game::GameHandler& gameHandler) { const char* displayName = c.name.empty() ? "(unknown)" : c.name.c_str(); ImVec4 nameCol = c.isOnline() ? classColorVec4(static_cast(c.classId)) - : ImVec4(0.5f, 0.5f, 0.5f, 1.0f); + : kColorDarkGray; ImGui::TextColored(nameCol, "%s", displayName); if (c.isOnline() && c.level > 0) { @@ -24072,7 +24074,7 @@ void GameScreen::renderInstanceLockouts(game::GameHandler& gameHandler) { static_cast(mins)); } } else { - ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Expired"); + ImGui::TextColored(kColorDarkGray, "Expired"); } // Locked / Extended status @@ -24446,7 +24448,7 @@ void GameScreen::renderCombatLog(game::GameHandler& gameHandler) { snprintf(desc, sizeof(desc), "%s critically heals %s for %d! (%s)", src, tgt, e.amount, spell); else snprintf(desc, sizeof(desc), "%s critically heals %s for %d!", src, tgt, e.amount); - color = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); + color = kColorBrightGreen; break; case T::PERIODIC_HEAL: if (spell)