mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-12 23:53:52 +00:00
Extract ~1,700 lines / 60+ inline [this]-capturing lambdas from the monolithic
Application::setupUICallbacks() into 7 focused callback handler classes following
the ToastManager/ChatPanel::setupCallbacks() pattern already in the codebase.
New handlers (include/core/ + src/core/):
- NPCInteractionCallbackHandler NPC greeting/farewell/vendor/aggro voice
- AudioCallbackHandler Music, positional sound, level-up, achievement, LFG
- EntitySpawnCallbackHandler Creature/player/GO spawn, despawn, move, state
- AnimationCallbackHandler Death, respawn, combat, emotes, charge, sprint, vehicle
- TransportCallbackHandler Mount, taxi, transport spawn/move
- WorldEntryCallbackHandler World entry, unstuck, hearthstone, bind point
- UIScreenCallbackHandler Auth, realm selection, char selection/creation/deletion
application.cpp: 4,462 → 2,791 lines (−1,671)
setupUICallbacks: ~1,700 → ~50 lines (thin orchestrator)
Deduplication:
resolveSoundEntryPath() — was 3× copy-paste of SoundEntries.dbc lookup
resolveNpcVoiceType() — was 4× copy-paste of display-ID→voice detection
precacheNearbyTiles() — was 3× copy-paste of 17×17 tile loop
4 helper lambdas — promoted to private methods on WorldEntryCallbackHandler
State migration out of Application:
charge* (6 vars) → AnimationCallbackHandler
hearth*/worldEntry*/taxi* → WorldEntryCallbackHandler
pendingCreatedCharacterName_ → UIScreenCallbackHandler
Bug fixes:
- Duplicate `namespace core {` in application.hpp caused wowee::std pollution
- AppState forward decl in ui_screen_callback_handler.hpp was at wrong scope
- world_loader.cpp accessed moved member vars directly via friend; now uses handler API
182 lines
7.3 KiB
C++
182 lines
7.3 KiB
C++
#include "core/ui_screen_callback_handler.hpp"
|
|
#include "core/application.hpp" // AppState
|
|
#include "core/logger.hpp"
|
|
#include "ui/ui_manager.hpp"
|
|
#include "auth/auth_handler.hpp"
|
|
#include "game/game_handler.hpp"
|
|
#include "game/expansion_profile.hpp"
|
|
#include "game/world_packets.hpp"
|
|
#include "pipeline/asset_manager.hpp"
|
|
|
|
namespace wowee { namespace core {
|
|
|
|
UIScreenCallbackHandler::UIScreenCallbackHandler(
|
|
ui::UIManager& uiManager,
|
|
game::GameHandler& gameHandler,
|
|
auth::AuthHandler& authHandler,
|
|
game::ExpansionRegistry* expansionRegistry,
|
|
pipeline::AssetManager* assetManager,
|
|
SetStateFn setState)
|
|
: uiManager_(uiManager)
|
|
, gameHandler_(gameHandler)
|
|
, authHandler_(authHandler)
|
|
, expansionRegistry_(expansionRegistry)
|
|
, assetManager_(assetManager)
|
|
, setState_(std::move(setState))
|
|
{
|
|
}
|
|
|
|
void UIScreenCallbackHandler::setupCallbacks() {
|
|
// Authentication screen callback
|
|
uiManager_.getAuthScreen().setOnSuccess([this]() {
|
|
LOG_INFO("Authentication successful, transitioning to realm selection");
|
|
setState_(AppState::REALM_SELECTION);
|
|
});
|
|
|
|
// Realm selection callback
|
|
uiManager_.getRealmScreen().setOnRealmSelected([this](const std::string& realmName, const std::string& realmAddress) {
|
|
LOG_INFO("Realm selected: ", realmName, " (", realmAddress, ")");
|
|
|
|
// Parse realm address (format: "hostname:port")
|
|
std::string host = realmAddress;
|
|
uint16_t port = 8085; // Default world server port
|
|
|
|
size_t colonPos = realmAddress.find(':');
|
|
if (colonPos != std::string::npos) {
|
|
host = realmAddress.substr(0, colonPos);
|
|
try { port = static_cast<uint16_t>(std::stoi(realmAddress.substr(colonPos + 1))); }
|
|
catch (...) { LOG_WARNING("Invalid port in realm address: ", realmAddress); }
|
|
}
|
|
|
|
// Connect to world server
|
|
const auto& sessionKey = authHandler_.getSessionKey();
|
|
std::string accountName = authHandler_.getUsername();
|
|
if (accountName.empty()) {
|
|
LOG_WARNING("Auth username missing; falling back to TESTACCOUNT");
|
|
accountName = "TESTACCOUNT";
|
|
}
|
|
|
|
uint32_t realmId = 0;
|
|
uint16_t realmBuild = 0;
|
|
{
|
|
// WotLK AUTH_SESSION includes a RealmID field; some servers reject if it's wrong/zero.
|
|
const auto& realms = authHandler_.getRealms();
|
|
for (const auto& r : realms) {
|
|
if (r.name == realmName && r.address == realmAddress) {
|
|
realmId = r.id;
|
|
realmBuild = r.build;
|
|
break;
|
|
}
|
|
}
|
|
LOG_INFO("Selected realmId=", realmId, " realmBuild=", realmBuild);
|
|
}
|
|
|
|
uint32_t clientBuild = 12340; // default WotLK
|
|
if (expansionRegistry_) {
|
|
auto* profile = expansionRegistry_->getActive();
|
|
if (profile) clientBuild = profile->worldBuild;
|
|
}
|
|
// Prefer realm-reported build when available (e.g. vanilla servers
|
|
// that report build 5875 in the realm list)
|
|
if (realmBuild != 0) {
|
|
clientBuild = realmBuild;
|
|
LOG_INFO("Using realm-reported build: ", clientBuild);
|
|
}
|
|
if (gameHandler_.connect(host, port, sessionKey, accountName, clientBuild, realmId)) {
|
|
LOG_INFO("Connected to world server, transitioning to character selection");
|
|
setState_(AppState::CHARACTER_SELECTION);
|
|
} else {
|
|
LOG_ERROR("Failed to connect to world server");
|
|
}
|
|
});
|
|
|
|
// Realm screen back button - return to login
|
|
uiManager_.getRealmScreen().setOnBack([this]() {
|
|
authHandler_.disconnect();
|
|
uiManager_.getRealmScreen().reset();
|
|
setState_(AppState::AUTHENTICATION);
|
|
});
|
|
|
|
// Character selection callback
|
|
uiManager_.getCharacterScreen().setOnCharacterSelected([this](uint64_t characterGuid) {
|
|
LOG_INFO("Character selected: GUID=0x", std::hex, characterGuid, std::dec);
|
|
// Always set the active character GUID
|
|
gameHandler_.setActiveCharacterGuid(characterGuid);
|
|
// Keep CHARACTER_SELECTION active until world entry is fully loaded.
|
|
// This avoids exposing pre-load hitching before the loading screen/intro.
|
|
});
|
|
|
|
// Character create screen callbacks
|
|
uiManager_.getCharacterCreateScreen().setOnCreate([this](const game::CharCreateData& data) {
|
|
pendingCreatedCharacterName_ = data.name; // Store name for auto-selection
|
|
gameHandler_.createCharacter(data);
|
|
});
|
|
|
|
uiManager_.getCharacterCreateScreen().setOnCancel([this]() {
|
|
setState_(AppState::CHARACTER_SELECTION);
|
|
});
|
|
|
|
// Character create result callback
|
|
gameHandler_.setCharCreateCallback([this](bool success, const std::string& msg) {
|
|
if (success) {
|
|
// Auto-select the newly created character
|
|
if (!pendingCreatedCharacterName_.empty()) {
|
|
uiManager_.getCharacterScreen().selectCharacterByName(pendingCreatedCharacterName_);
|
|
pendingCreatedCharacterName_.clear();
|
|
}
|
|
setState_(AppState::CHARACTER_SELECTION);
|
|
} else {
|
|
uiManager_.getCharacterCreateScreen().setStatus(msg, true);
|
|
pendingCreatedCharacterName_.clear();
|
|
}
|
|
});
|
|
|
|
// Character login failure callback
|
|
gameHandler_.setCharLoginFailCallback([this](const std::string& reason) {
|
|
LOG_WARNING("Character login failed: ", reason);
|
|
setState_(AppState::CHARACTER_SELECTION);
|
|
uiManager_.getCharacterScreen().setStatus("Login failed: " + reason, true);
|
|
});
|
|
|
|
// "Create Character" button on character screen
|
|
uiManager_.getCharacterScreen().setOnCreateCharacter([this]() {
|
|
uiManager_.getCharacterCreateScreen().reset();
|
|
// Apply expansion race/class constraints before showing the screen
|
|
if (expansionRegistry_ && expansionRegistry_->getActive()) {
|
|
auto* profile = expansionRegistry_->getActive();
|
|
uiManager_.getCharacterCreateScreen().setExpansionConstraints(
|
|
profile->races, profile->classes);
|
|
}
|
|
uiManager_.getCharacterCreateScreen().initializePreview(assetManager_);
|
|
setState_(AppState::CHARACTER_CREATION);
|
|
});
|
|
|
|
// "Back" button on character screen
|
|
uiManager_.getCharacterScreen().setOnBack([this]() {
|
|
// Disconnect from world server and reset UI state for fresh realm selection
|
|
gameHandler_.disconnect();
|
|
uiManager_.getRealmScreen().reset();
|
|
uiManager_.getCharacterScreen().reset();
|
|
setState_(AppState::REALM_SELECTION);
|
|
});
|
|
|
|
// "Delete Character" button on character screen
|
|
uiManager_.getCharacterScreen().setOnDeleteCharacter([this](uint64_t guid) {
|
|
gameHandler_.deleteCharacter(guid);
|
|
});
|
|
|
|
// Character delete result callback
|
|
gameHandler_.setCharDeleteCallback([this](bool success) {
|
|
if (success) {
|
|
uiManager_.getCharacterScreen().setStatus("Character deleted.");
|
|
// Refresh character list
|
|
gameHandler_.requestCharacterList();
|
|
} else {
|
|
uint8_t code = gameHandler_.getLastCharDeleteResult();
|
|
uiManager_.getCharacterScreen().setStatus(
|
|
"Delete failed (code " + std::to_string(static_cast<int>(code)) + ").", true);
|
|
}
|
|
});
|
|
}
|
|
|
|
}} // namespace wowee::core
|