mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-14 00:23:50 +00:00
refactor(core): decompose Application::setupUICallbacks() into 7 domain handlers
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
This commit is contained in:
parent
a23c2172a8
commit
6dcc06697b
18 changed files with 2293 additions and 1765 deletions
182
src/core/ui_screen_callback_handler.cpp
Normal file
182
src/core/ui_screen_callback_handler.cpp
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
#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
|
||||
Loading…
Add table
Add a link
Reference in a new issue