feat(glue): add realm and character handling (#7)

* fix(build): make project compilable

* feat(glue): update Character Selection screen to support switching

* fix(ui): fix CSimpleFontString::GetHeight() to use proper method

* feat(db): add static database classes from whoa-autocode

* feat(ui): use class and area IDs for Character Selection

* chore(db): update ItemRandomPropertiesRec

* feat(glue): update CCharacterSelection methods

* chore(db): uncomment DB records

* feat(glue): implement character deletion

* feat(gx): update supported text tags in GxuDetermineQuotedCode

* fix(ui): fix CSimpleFontString to use the FixedColor flag only if the string does not contain color tags

* feat(net): implement GrunLogin::LogOff

* feat(net): implement NetClient::Disconnect

* feat(login): implement trimming of realm name in LoginResponse::HandleRealmData

* feat(net): implement proper disconnection from login and realm servers

* feat(net): implement PING/PONG messages

* feat(net): add NetClient::Destroy method

* feat(net): implement ClientServices::GetRealmList (second request of Realm List)

* feat(glue): implement CGlueMgr::PollRealmList

* feat(glue): implement CGlueMgr::PollCreateCharacter

* chore(glue): add skeleton of CCharacterComponent class

* fix(build): fix build using latest features

* fix(glue): kill gotos in CGlueMgr::NetDisconnectHandler

* fix(build): include SDL3

---------

Co-authored-by: superp00t <superp00t@tutanota.com>
This commit is contained in:
VDm 2025-04-17 01:32:37 +04:00 committed by GitHub
parent 50e37d16bc
commit 957a4c7e2f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
633 changed files with 1729 additions and 227 deletions

View file

@ -39,6 +39,7 @@ CVar* Client::g_accountUsesTokenVar;
CVar* Client::g_movieVar;
CVar* Client::g_expansionMovieVar;
CVar* Client::g_movieSubtitleVar;
CVar* Client::g_lastCharacterIndex;
HEVENTCONTEXT Client::g_clientEventContext;
@ -168,6 +169,16 @@ void ClientRegisterConsoleCommands() {
false
);
Client::g_lastCharacterIndex = CVar::Register(
"lastCharacterIndex",
"Last character selected",
0,
"0",
nullptr,
GAME,
false,
nullptr,
false);
// TODO
}

View file

@ -14,6 +14,7 @@ namespace Client {
extern CVar* g_movieVar;
extern CVar* g_expansionMovieVar;
extern CVar* g_movieSubtitleVar;
extern CVar* g_lastCharacterIndex;
extern HEVENTCONTEXT g_clientEventContext;
extern char g_currentLocaleName[5];
}

View file

@ -9,6 +9,113 @@
#include <bc/Memory.hpp>
#include <storm/String.hpp>
static const char* s_errorCodeTokens[] = {
"RESPONSE_SUCCESS",
"RESPONSE_FAILURE",
"RESPONSE_CANCELLED",
"RESPONSE_DISCONNECTED",
"RESPONSE_FAILED_TO_CONNECT",
"RESPONSE_CONNECTED",
"RESPONSE_VERSION_MISMATCH",
"CSTATUS_CONNECTING",
"CSTATUS_NEGOTIATING_SECURITY",
"CSTATUS_NEGOTIATION_COMPLETE",
"CSTATUS_NEGOTIATION_FAILED",
"CSTATUS_AUTHENTICATING",
"AUTH_OK",
"AUTH_FAILED",
"AUTH_REJECT",
"AUTH_BAD_SERVER_PROOF",
"AUTH_UNAVAILABLE",
"AUTH_SYSTEM_ERROR",
"AUTH_BILLING_ERROR",
"AUTH_BILLING_EXPIRED",
"AUTH_VERSION_MISMATCH",
"AUTH_UNKNOWN_ACCOUNT",
"AUTH_INCORRECT_PASSWORD",
"AUTH_SESSION_EXPIRED",
"AUTH_SERVER_SHUTTING_DOWN",
"AUTH_ALREADY_LOGGING_IN",
"AUTH_LOGIN_SERVER_NOT_FOUND",
"AUTH_WAIT_QUEUE",
"AUTH_BANNED",
"AUTH_ALREADY_ONLINE",
"AUTH_NO_TIME",
"AUTH_DB_BUSY",
"AUTH_SUSPENDED",
"AUTH_PARENTAL_CONTROL",
"AUTH_LOCKED_ENFORCED",
"REALM_LIST_IN_PROGRESS",
"REALM_LIST_SUCCESS",
"REALM_LIST_FAILED",
"REALM_LIST_INVALID",
"REALM_LIST_REALM_NOT_FOUND",
"ACCOUNT_CREATE_IN_PROGRESS",
"ACCOUNT_CREATE_SUCCESS",
"ACCOUNT_CREATE_FAILED",
"CHAR_LIST_RETRIEVING",
"CHAR_LIST_RETRIEVED",
"CHAR_LIST_FAILED",
"CHAR_CREATE_IN_PROGRESS",
"CHAR_CREATE_SUCCESS",
"CHAR_CREATE_ERROR",
"CHAR_CREATE_FAILED",
"CHAR_CREATE_NAME_IN_USE",
"CHAR_CREATE_DISABLED",
"CHAR_CREATE_PVP_TEAMS_VIOLATION",
"CHAR_CREATE_SERVER_LIMIT",
"CHAR_CREATE_ACCOUNT_LIMIT",
"CHAR_CREATE_SERVER_QUEUE",
"CHAR_CREATE_ONLY_EXISTING",
"CHAR_CREATE_EXPANSION",
"CHAR_CREATE_EXPANSION_CLASS",
"CHAR_CREATE_LEVEL_REQUIREMENT",
"CHAR_CREATE_UNIQUE_CLASS_LIMIT",
"CHAR_CREATE_CHARACTER_IN_GUILD",
"CHAR_CREATE_RESTRICTED_RACECLASS",
"CHAR_CREATE_CHARACTER_CHOOSE_RACE",
"CHAR_CREATE_CHARACTER_ARENA_LEADER",
"CHAR_CREATE_CHARACTER_DELETE_MAIL",
"CHAR_CREATE_CHARACTER_SWAP_FACTION",
"CHAR_CREATE_CHARACTER_RACE_ONLY",
"CHAR_CREATE_CHARACTER_GOLD_LIMIT",
"CHAR_CREATE_FORCE_LOGIN",
"CHAR_DELETE_IN_PROGRESS",
"CHAR_DELETE_SUCCESS",
"CHAR_DELETE_FAILED",
"CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER",
"CHAR_DELETE_FAILED_GUILD_LEADER",
"CHAR_DELETE_FAILED_ARENA_CAPTAIN",
"CHAR_LOGIN_IN_PROGRESS",
"CHAR_LOGIN_SUCCESS",
"CHAR_LOGIN_NO_WORLD",
"CHAR_LOGIN_DUPLICATE_CHARACTER",
"CHAR_LOGIN_NO_INSTANCES",
"CHAR_LOGIN_FAILED",
"CHAR_LOGIN_DISABLED",
"CHAR_LOGIN_NO_CHARACTER",
"CHAR_LOGIN_LOCKED_FOR_TRANSFER",
"CHAR_LOGIN_LOCKED_BY_BILLING",
"CHAR_LOGIN_LOCKED_BY_MOBILE_AH",
"CHAR_NAME_SUCCESS",
"CHAR_NAME_FAILURE",
"CHAR_NAME_NO_NAME",
"CHAR_NAME_TOO_SHORT",
"CHAR_NAME_TOO_LONG",
"CHAR_NAME_INVALID_CHARACTER",
"CHAR_NAME_MIXED_LANGUAGES",
"CHAR_NAME_PROFANE",
"CHAR_NAME_RESERVED",
"CHAR_NAME_INVALID_APOSTROPHE",
"CHAR_NAME_MULTIPLE_APOSTROPHES",
"CHAR_NAME_THREE_CONSECUTIVE",
"CHAR_NAME_INVALID_SPACE",
"CHAR_NAME_CONSECUTIVE_SPACES",
"CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS",
"CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END",
"CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME",
};
ClientConnection* g_clientConnection;
char ClientServices::s_accountName[1280];
@ -27,6 +134,20 @@ CVar* ClientServices::s_darkPortalVar = nullptr;
CVar* ClientServices::s_ServerAlertVar = nullptr;
CVar* ClientServices::s_realmListVar = nullptr;
const char* ClientServices::GetErrorToken(uint32_t token) {
if (token < sizeof(s_errorCodeTokens) / sizeof(s_errorCodeTokens[0])) {
return s_errorCodeTokens[token];
} else {
return "";
}
}
bool ClientServices::ValidDisconnect(const void* client) {
STORM_ASSERT(client);
STORM_ASSERT(ClientServices::s_currentConnection);
return client == ClientServices::s_currentConnection;
}
void ClientServices::ConnectToSelectedServer() {
if (!ClientServices::s_selectRealmInfoValid && !ClientServices::SetSelectedRealmInfo(0)) {
ClientServices::Connection()->Complete(0, 39);
@ -69,13 +190,25 @@ void ClientServices::SetMessageHandler(NETMESSAGE msgId, MESSAGE_HANDLER handler
}
void ClientServices::GetRealmList() {
// TODO
STORM_ASSERT(ClientServices::s_currentConnection);
ClientServices::s_currentConnection->Initiate(COP_GET_REALMS, 35, nullptr);
if (ClientServices::s_loginObj->IsLoggedOn()) {
ClientServices::s_loginObj->GetRealmList();
} else {
ClientServices::s_loginObj->Reconnect();
}
}
void ClientServices::GetCharacterList() {
STORM_ASSERT(ClientServices::s_currentConnection);
ClientServices::s_currentConnection->GetCharacterList();
}
void ClientServices::EnumerateCharacters(ENUMERATE_CHARACTERS_CALLBACK fcn, void* param) {
STORM_ASSERT(ClientServices::s_currentConnection);
ClientServices::s_currentConnection->EnumerateCharacters(fcn, param);
}
void ClientServices::CharacterLogin(uint64_t id, const C3Vector& position) {
ClientServices::s_currentConnection->CharacterLogin(id);
}
@ -110,6 +243,11 @@ const REALM_INFO* ClientServices::GetSelectedRealm() {
return &ClientServices::s_selectRealmInfo;
}
void ClientServices::CharacterDelete(uint64_t guid) {
STORM_ASSERT(ClientServices::s_currentConnection);
ClientServices::s_currentConnection->DeleteCharacter(guid);
}
void ClientServices::Initialize() {
if (!g_clientConnection) {
ClientServices::s_clientRealmResponse = NEW(ClientRealmResponseAdapter);
@ -235,6 +373,7 @@ void ClientServices::LoginServerStatus(LOGIN_STATE state, LOGIN_RESULT result, c
void ClientServices::RealmEnumCallback(uint32_t a2) {
auto connection = ClientServices::Connection();
STORM_ASSERT(connection);
if (a2 == 1) {
connection->Complete(0, 23);
@ -246,7 +385,13 @@ void ClientServices::RealmEnumCallback(uint32_t a2) {
return;
}
// TODO statusCop checks
// TODO: Proper implementation
if (connection->m_statusCop != COP_CONNECT) {
if (connection->m_statusCop == COP_GET_REALMS) {
connection->Complete(1, 36);
}
return;
}
if (ClientServices::LoginConnection()->GetLoginServerType() == 1) {
// TODO Battlenet logic

View file

@ -32,16 +32,20 @@ class ClientServices : public LoginResponse {
static CVar* s_patchListVar;
// Static functions
static const char* GetErrorToken(uint32_t token);
static bool ValidDisconnect(const void* client);
static void ConnectToSelectedServer();
static ClientConnection* Connection();
static ClientServices* GetInstance();
static void SetMessageHandler(NETMESSAGE msgId, MESSAGE_HANDLER handler, void* param);
static void GetRealmList();
static void GetCharacterList();
static void EnumerateCharacters(ENUMERATE_CHARACTERS_CALLBACK fcn, void* param);
static void CharacterLogin(uint64_t id, const C3Vector& position);
static REALM_INFO* GetRealmInfoByIndex(int32_t index);
static const char* GetSelectedRealmName();
static const REALM_INFO* GetSelectedRealm();
static void CharacterDelete(uint64_t guid);
static void Initialize();
static Login* LoginConnection();
static void Logon(const char* accountName, const char* password);