From 7a22ffb998275dc151716225bf600ad773080da9 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Fri, 3 Oct 2025 22:52:33 -0500 Subject: [PATCH] feat(net): handle SMSG_CHAR_ENUM --- src/client/ClientRealmResponseAdapter.cpp | 4 ++ src/client/ClientRealmResponseAdapter.hpp | 1 + src/net/Types.hpp | 32 +++++++++ src/net/connection/RealmConnection.cpp | 87 ++++++++++++++++++++++- src/net/connection/RealmConnection.hpp | 3 + src/net/connection/RealmResponse.hpp | 1 + 6 files changed, 127 insertions(+), 1 deletion(-) diff --git a/src/client/ClientRealmResponseAdapter.cpp b/src/client/ClientRealmResponseAdapter.cpp index 7a835b7..ec5e6a4 100644 --- a/src/client/ClientRealmResponseAdapter.cpp +++ b/src/client/ClientRealmResponseAdapter.cpp @@ -4,6 +4,10 @@ void AccountDataInitialize(bool a1) { // TODO } +void ClientRealmResponseAdapter::CharacterListReceived(RealmConnection* realmConnection, const TSFixedArray& characterList, int32_t listSuccess) { + // TODO +} + void ClientRealmResponseAdapter::HandleAuthResponse(RealmConnection* realmConnection, uint8_t authResult) { auto clientConnection = static_cast(realmConnection); diff --git a/src/client/ClientRealmResponseAdapter.hpp b/src/client/ClientRealmResponseAdapter.hpp index 1c0c2ae..e56922e 100644 --- a/src/client/ClientRealmResponseAdapter.hpp +++ b/src/client/ClientRealmResponseAdapter.hpp @@ -7,6 +7,7 @@ class ClientRealmResponseAdapter : public RealmResponse { public: // Virtual member functions virtual void HandleAuthResponse(RealmConnection* realmConnection, uint8_t authResult); + virtual void CharacterListReceived(RealmConnection* realmConnection, const TSFixedArray& characterList, int32_t listSuccess); virtual void GameServerResult(RealmConnection* realmConnection, const char* a2, const char* a3, const char* a4) {}; }; diff --git a/src/net/Types.hpp b/src/net/Types.hpp index a5957b3..c7c408b 100644 --- a/src/net/Types.hpp +++ b/src/net/Types.hpp @@ -1,6 +1,7 @@ #ifndef NET_TYPES_HPP #define NET_TYPES_HPP +#include #include enum NETMESSAGE { @@ -1185,4 +1186,35 @@ struct REALM_INFO { uint16_t revision; }; +struct INVENTORY_ITEM { + uint8_t type; + uint32_t displayID; + uint32_t auraID; +}; + +struct CHARACTER_INFO { + uint64_t guid; + char name[48]; + uint32_t mapID; + uint32_t zoneID; + uint32_t guildID; + C3Vector position; + INVENTORY_ITEM items[23]; + uint32_t petDisplayInfoID; + uint32_t petExperienceLevel; + uint32_t petCreatureFamilyID; + uint32_t flags; + uint32_t customizeFlags; + uint8_t raceID; + uint8_t classID; + uint8_t sexID; + uint8_t skinID; + uint8_t faceID; + uint8_t hairStyleID; + uint8_t hairColorID; + uint8_t facialHairStyleID; + uint8_t experienceLevel; + uint8_t firstLogin; +}; + #endif diff --git a/src/net/connection/RealmConnection.cpp b/src/net/connection/RealmConnection.cpp index a099b55..500985e 100644 --- a/src/net/connection/RealmConnection.cpp +++ b/src/net/connection/RealmConnection.cpp @@ -24,7 +24,7 @@ int32_t RealmConnection::MessageHandler(void* param, NETMESSAGE msgId, uint32_t } case SMSG_ENUM_CHARACTERS_RESULT: { - // TODO + result = connection->HandleCharEnum(msgId, time, msg); break; } @@ -193,6 +193,91 @@ int32_t RealmConnection::HandleAuthResponse(uint32_t msgId, uint32_t time, CData return 1; } +int32_t RealmConnection::HandleCharEnum(uint32_t msgId, uint32_t time, CDataStore* msg) { + if (this->m_realmResponse) { + this->m_realmResponse->GameServerResult(this, "SMSG_CHAR_ENUM", nullptr, nullptr); + } + + int32_t characterLimitExceeded = 0; + + uint8_t count; + msg->Get(count); + + if (count > 10) { + count = 0; + characterLimitExceeded = 1; + } + + this->m_characterList.Clear(); + this->m_characterList.SetCount(count); + + for (uint32_t i = 0; i < count; i++) { + auto& character = this->m_characterList[i]; + + msg->Get(character.guid); + + msg->GetString(character.name, 48); + + msg->Get(character.raceID); + msg->Get(character.classID); + msg->Get(character.sexID); + + msg->Get(character.skinID); + msg->Get(character.faceID); + msg->Get(character.hairStyleID); + msg->Get(character.hairColorID); + msg->Get(character.facialHairStyleID); + + msg->Get(character.experienceLevel); + + msg->Get(character.zoneID); + msg->Get(character.mapID); + msg->Get(character.position.x); + msg->Get(character.position.y); + msg->Get(character.position.z); + + msg->Get(character.guildID); + + msg->Get(character.flags); + msg->Get(character.customizeFlags); + msg->Get(character.firstLogin); + + msg->Get(character.petDisplayInfoID); + msg->Get(character.petExperienceLevel); + msg->Get(character.petCreatureFamilyID); + + for (auto& item : character.items) { + msg->Get(item.displayID); + msg->Get(item.type); + msg->Get(item.auraID); + } + } + + int32_t listSuccess = 0; + + if (!characterLimitExceeded) { + if (!msg->IsRead()) { + // TODO what are these fields? + uint32_t unknown; + for (uint32_t i = 0; i < 10; i++) { + msg->Get(unknown); + } + } + + if (msg->IsRead()) { + listSuccess = 1; + } + } + + if (!listSuccess) { + this->m_characterList.Clear(); + } + + this->m_realmResponse->CharacterListReceived(this, this->m_characterList, listSuccess); + + return 1; +} + void RealmConnection::SetSelectedRealm(uint32_t a2, uint32_t a3, uint32_t a4) { // TODO } diff --git a/src/net/connection/RealmConnection.hpp b/src/net/connection/RealmConnection.hpp index 5414dc2..6159098 100644 --- a/src/net/connection/RealmConnection.hpp +++ b/src/net/connection/RealmConnection.hpp @@ -2,6 +2,7 @@ #define NET_CONNECTION_REALM_CONNECTION_HPP #include "net/connection/NetClient.hpp" +#include #include class CDataStore; @@ -24,6 +25,7 @@ class RealmConnection : public NetClient { // Member variables RealmResponse* m_realmResponse; + TSFixedArray m_characterList; uint8_t m_authenticated = 0; uint32_t m_queuePosition = 0; uint32_t m_freeCharacterMigration = 0; @@ -38,6 +40,7 @@ class RealmConnection : public NetClient { // Member functions RealmConnection(RealmResponse* realmResponse); int32_t HandleAuthResponse(uint32_t msgId, uint32_t time, CDataStore* msg); + int32_t HandleCharEnum(uint32_t msgId, uint32_t time, CDataStore* msg); void SetSelectedRealm(uint32_t a2, uint32_t a3, uint32_t a4); }; diff --git a/src/net/connection/RealmResponse.hpp b/src/net/connection/RealmResponse.hpp index 6600312..ae4fecd 100644 --- a/src/net/connection/RealmResponse.hpp +++ b/src/net/connection/RealmResponse.hpp @@ -5,6 +5,7 @@ class RealmResponse { public: // Virtual member functions virtual void HandleAuthResponse(RealmConnection* connection, uint8_t authResult) = 0; + virtual void CharacterListReceived(RealmConnection* realmConnection, const TSFixedArray& characterList, int32_t listResult) = 0; virtual void GameServerResult(RealmConnection* connection, const char* a3, const char* a4, const char* a5) = 0; };