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.
This commit is contained in:
Kelsi 2026-03-25 12:12:03 -07:00
parent ba99d505dd
commit eea205ffc9
5 changed files with 63 additions and 96 deletions

View file

@ -7,6 +7,8 @@
#include <fstream>
#include <chrono>
#include <atomic>
#include <cstdio>
#include <cstdint>
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

View file

@ -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;

View file

@ -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<uint8_t> 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<int>(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;
}

View file

@ -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) {

View file

@ -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<uint8_t>(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<float>(playerHp) / static_cast<float>(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<game::Unit>(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<game::Unit>(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<uint8_t>(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<unsigned long long>(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)