feat(net): add RealmConnection::HandleCharEnum implementation

This commit is contained in:
VDm 2025-03-29 23:37:24 +04:00
parent ba21fb2994
commit 1e8dc7aef9
10 changed files with 171 additions and 10 deletions

View File

@ -71,7 +71,7 @@ void ClientServices::GetRealmList() {
}
void ClientServices::GetCharacterList() {
// TODO
ClientServices::s_currentConnection->GetCharacterList();
}
REALM_INFO* ClientServices::GetRealmInfoByIndex(int32_t index) {

View File

@ -4,6 +4,7 @@
TSGrowableArray<CharacterSelectionDisplay> CCharacterSelection::s_characterList;
CSimpleModelFFX* CCharacterSelection::s_modelFrame;
float CCharacterSelection::s_charFacing = 0.0f;
void CCharacterSelection::RenderPrep() {
// TODO
@ -33,3 +34,7 @@ void CCharacterSelection::SetBackgroundModel(const char* modelPath) {
model->IsDrawable(1, 1);
}
}
void CCharacterSelection::SetCharFacing(float facing) {
// TODO:
}

View File

@ -14,10 +14,12 @@ class CCharacterSelection {
// Static variables
static TSGrowableArray<CharacterSelectionDisplay> s_characterList;
static CSimpleModelFFX* s_modelFrame;
static float s_charFacing;
// Static functions
static void RenderPrep();
static void SetBackgroundModel(const char* modelPath);
static void SetCharFacing(float facing);
};
#endif

View File

@ -1,6 +1,8 @@
#ifndef NET_TYPES_HPP
#define NET_TYPES_HPP
#include <tempest/vector/C3Vector.hpp>
#include <cstdint>
enum LOGIN_RESULT {
@ -1252,4 +1254,36 @@ 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

View File

@ -132,6 +132,15 @@ void ClientConnection::AccountLogin_Queued() {
// TODO CGlueMgr::UpdateWaitQueue(this->m_queuePosition);
}
void ClientConnection::GetCharacterList() {
this->Initiate(COP_GET_CHARACTERS, 43, nullptr);
if (this->m_connected) {
this->RequestCharacterEnum();
} else {
this->Cancel(4);
}
}
void ClientConnection::Cancel(int32_t errorCode) {
this->Complete(0, errorCode);
}

View File

@ -18,6 +18,7 @@ class ClientConnection : public RealmConnection {
// Virtual member functions
virtual int32_t HandleConnect();
virtual void Complete(int32_t result, int32_t errorCode);
// Member functions
ClientConnection(RealmResponse* realmResponse)
@ -26,9 +27,9 @@ class ClientConnection : public RealmConnection {
void AccountLogin(const char* name, const char* password, int32_t region, int32_t locale);
void AccountLogin_Finish(int32_t authResult);
void AccountLogin_Queued();
void GetCharacterList();
void Cancel(int32_t errorCode);
void Cleanup();
void Complete(int32_t result, int32_t errorCode);
void Connect();
int32_t Disconnect();
void Initiate(WOWCS_OPS op, int32_t errorCode, void (*cleanup)());

View File

@ -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;
}
@ -192,6 +192,98 @@ 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);
}
uint8_t count;
msg->Get(count);
bool overflow = false;
if (count > 10) {
count = 0;
overflow = true;
}
m_characterList.SetCount(count);
for (uint32_t i = 0; i < count; ++i) {
auto& character = 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 (uint32_t j = 0; j < 23; ++j) {
msg->Get(character.items[j].displayID);
msg->Get(character.items[j].type);
msg->Get(character.items[j].auraID);
}
}
bool success = false;
if (msg->IsRead()) {
if (!overflow) {
success = true;
}
} else if (!overflow) {
// TODO: Proper implementation
uint32_t value;
msg->Get(value);
msg->Get(value);
msg->Get(value);
msg->Get(value);
msg->Get(value);
msg->Get(value);
msg->Get(value);
msg->Get(value);
msg->Get(value);
msg->Get(value);
if (msg->IsRead()) {
success = true;
}
}
if (!success) {
m_characterList.Clear();
}
// TODO: Should be implemented as call of sub_6B2000
if (success) {
this->Complete(1, 44);
} else {
this->Complete(1, 45);
}
return 1;
}
void RealmConnection::SetSelectedRealm(uint32_t a2, uint32_t a3, uint32_t a4) {
// TODO
}
void RealmConnection::RequestCharacterEnum() {
CDataStore msg;
msg.Put(static_cast<uint32_t>(CMSG_ENUM_CHARACTERS));
msg.Finalize();
this->Send(&msg);
}

View File

@ -24,6 +24,7 @@ class RealmConnection : public NetClient {
// Member variables
RealmResponse* m_realmResponse;
TSFixedArray<CHARACTER_INFO> m_characterList;
uint8_t m_authenticated = 0;
uint32_t m_queuePosition = 0;
uint32_t m_freeCharacterMigration = 0;
@ -34,11 +35,14 @@ class RealmConnection : public NetClient {
// Virtual member functions
virtual int32_t HandleAuthChallenge(AuthenticationChallenge* challenge);
virtual void Complete(int32_t result, int32_t errorCode) = 0;
// 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);
void RequestCharacterEnum();
};
#endif

View File

@ -74,11 +74,19 @@ int32_t Script_UpdateSelectionCustomizationScene(lua_State* L) {
}
int32_t Script_GetCharacterSelectFacing(lua_State* L) {
WHOA_UNIMPLEMENTED(0);
// Radian to Degree
lua_pushnumber(L, CCharacterSelection::s_charFacing * 57.29578f);
return 1;
}
int32_t Script_SetCharacterSelectFacing(lua_State* L) {
WHOA_UNIMPLEMENTED(0);
if (!lua_isnumber(L, 1)) {
luaL_error(L, "Usage: SetCharacterSelectFacing(degrees)");
}
// Degree to Radian
float facing = lua_tonumber(L, 1) * 0.017453292;
CCharacterSelection::SetCharFacing(facing);
return 1;
}
int32_t Script_GetSelectBackgroundModel(lua_State* L) {

View File

@ -5,6 +5,7 @@
#include "glue/CGlueMgr.hpp"
#include "gx/Coordinate.hpp"
#include "net/connection/ClientConnection.hpp"
#include "net/Login.hpp"
#include "ui/CSimpleTop.hpp"
#include "ui/Types.hpp"
#include "console/CVar.hpp"
@ -19,11 +20,11 @@ int32_t Script_IsShiftKeyDown(lua_State* L) {
}
int32_t Script_GetBuildInfo(lua_State* L) {
auto version = FrameScript_GetText("VERSION", -1, GENDER_NOT_APPLICABLE);
lua_pushstring(L, version);
auto szVersion = FrameScript_GetText("VERSION", -1, GENDER_NOT_APPLICABLE);
auto szVersionType = FrameScript_GetText("RELEASE_BUILD", -1, GENDER_NOT_APPLICABLE);
auto releaseBuild = FrameScript_GetText("RELEASE_BUILD", -1, GENDER_NOT_APPLICABLE);
lua_pushstring(L, releaseBuild);
lua_pushstring(L, szVersion);
lua_pushstring(L, szVersionType);
lua_pushstring(L, "3.3.5");
lua_pushstring(L, "12340");
lua_pushstring(L, "Jun 24 2010");
@ -274,7 +275,12 @@ int32_t Script_GetServerName(lua_State* L) {
}
int32_t Script_DisconnectFromServer(lua_State* L) {
WHOA_UNIMPLEMENTED(0);
if (ClientServices::Connection()->IsConnected()) {
CGlueMgr::m_disconnectPending = 1;
ClientServices::Connection()->Disconnect();
}
ClientServices::LoginConnection()->Logoff();
return 0;
}
int32_t Script_IsConnectedToServer(lua_State* L) {