core: add clientless player session bootstrap
clang PCH / build (push) Canceled after 0s
GCC PCH / build (push) Canceled after 0s

This commit is contained in:
Nico committed 2026-10-12 10:17:43 +00:00
1 parent df55203a96
commit fe96d310d6
5 files changed
+144

No files matched your search

@@ -754,6 +754,29 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPackets::Character::PlayerLogin&
SendConnectToInstance(WorldPackets::Auth::ConnectToSerial::WorldAttempt1);
}
bool WorldSession::InitializeClientlessPlayer(ObjectGuid playerGuid)
{
if (!IsClientless())
{
TC_LOG_ERROR("server.worldserver",
"WorldSession::InitializeClientlessPlayer rejected a non-clientless session for account %u.",
GetAccountId());
return false;
}
if (!playerGuid || !_clientlessPendingPlayerGuid.IsEmpty() || PlayerLoading() || GetPlayer())
{
TC_LOG_ERROR("server.worldserver",
"WorldSession::InitializeClientlessPlayer rejected invalid initialization state for account %u, character GUID %u.",
GetAccountId(), uint32(playerGuid.GetCounter()));
return false;
}
_clientlessPendingPlayerGuid = playerGuid;
InitializeSession();
return true;
}
bool WorldSession::BeginClientlessPlayerLogin(ObjectGuid playerGuid)
{
if (!IsClientless())
+12
View File
@@ -115,6 +115,7 @@ WorldSession::WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldS
m_GUIDLow(0),
_player(nullptr),
_sessionMode(sessionMode),
_clientlessPendingPlayerGuid(),
_security(sec),
_accountId(id),
_accountName(std::move(name)),
@@ -1280,6 +1281,17 @@ void WorldSession::InitializeSessionCallback(CharacterDatabaseQueryHolder const&
}
SetInQueue(false);
if (IsClientless() && !_clientlessPendingPlayerGuid.IsEmpty())
{
ObjectGuid playerGuid = _clientlessPendingPlayerGuid;
_clientlessPendingPlayerGuid.Clear();
if (!BeginClientlessPlayerLogin(playerGuid))
TC_LOG_ERROR("server.worldserver",
"WorldSession::InitializeSessionCallback failed to continue clientless login for account %u, character GUID %u.",
GetAccountId(), uint32(playerGuid.GetCounter()));
}
}
rbac::RBACData* WorldSession::GetRBACData()
+5
View File
@@ -687,6 +687,10 @@ class TC_GAME_API WorldSession
void HandleCharCreateOpcode(WorldPacket& recvPacket);
void HandlePlayerLoginOpcode(WorldPackets::Character::PlayerLogin& packet);
// Initializes shared account/session state and then starts the normal
// Player DB-load/login pipeline for a registered Clientless session.
bool InitializeClientlessPlayer(ObjectGuid playerGuid);
// Starts the normal Player DB-load/login pipeline without relying on
// client character-enumeration state or a network login opcode.
// The WorldSession must already be a registered Clientless session
@@ -1371,6 +1375,7 @@ class TC_GAME_API WorldSession
ObjectGuid::LowType m_GUIDLow; // set logined or recently logout player (while m_playerRecentlyLogout set)
Player* _player;
WorldSessionMode _sessionMode;
ObjectGuid _clientlessPendingPlayerGuid;
std::shared_ptr<WorldSocket> m_Socket[2];
std::string m_Address; // Current Remote Address
// std::string m_LAddress; // Last Attempted Remote Adress - we can not set attempted ip for a non-existing session!
+103
View File
@@ -379,6 +379,109 @@ bool World::RemoveClientlessSession(uint32 characterGuid)
return true;
}
bool World::CreateClientlessPlayerSession(uint32 accountId, uint32 characterGuid)
{
if (!accountId || !characterGuid)
{
TC_LOG_ERROR("server.worldserver",
"World::CreateClientlessPlayerSession rejected account %u, character GUID %u.",
accountId, characterGuid);
return false;
}
if (FindClientlessSession(characterGuid))
{
TC_LOG_ERROR("server.worldserver",
"World::CreateClientlessPlayerSession rejected duplicate character GUID %u.",
characterGuid);
return false;
}
if (FindSession(accountId))
{
TC_LOG_ERROR("server.worldserver",
"World::CreateClientlessPlayerSession rejected account %u because a network session is active.",
accountId);
return false;
}
QueryResult characterResult = CharacterDatabase.PQuery(
"SELECT account FROM characters WHERE guid = %u", characterGuid);
if (!characterResult)
{
TC_LOG_ERROR("server.worldserver",
"World::CreateClientlessPlayerSession could not find character GUID %u.",
characterGuid);
return false;
}
uint32 characterAccountId = characterResult->Fetch()[0].GetUInt32();
if (characterAccountId != accountId)
{
TC_LOG_ERROR("server.worldserver",
"World::CreateClientlessPlayerSession rejected character GUID %u: character account %u does not match requested account %u.",
characterGuid, characterAccountId, accountId);
return false;
}
QueryResult accountResult = LoginDatabase.PQuery(
"SELECT username, expansion, mutetime, locale, recruiter FROM account WHERE id = %u",
accountId);
if (!accountResult)
{
TC_LOG_ERROR("server.worldserver",
"World::CreateClientlessPlayerSession could not find account %u.",
accountId);
return false;
}
Field* accountFields = accountResult->Fetch();
std::string accountName = accountFields[0].GetString();
uint8 expansion = accountFields[1].GetUInt8();
time_t muteTime = time_t(accountFields[2].GetUInt64());
LocaleConstant locale = LocaleConstant(accountFields[3].GetUInt8());
uint32 recruiter = accountFields[4].GetUInt32();
if (locale >= TOTAL_LOCALES)
locale = LOCALE_enUS;
QueryResult recruiterResult = LoginDatabase.PQuery(
"SELECT 1 FROM account WHERE recruiter = %u LIMIT 1", accountId);
bool isRecruiter = bool(recruiterResult);
AccountTypes security = AccountTypes(AccountMgr::GetSecurity(accountId, realm.Id.Realm));
WorldSession* session = new WorldSession(
accountId,
std::move(accountName),
nullptr,
security,
expansion,
muteTime,
locale,
recruiter,
isRecruiter,
WorldSession::WorldSessionMode::Clientless);
if (!AddClientlessSession(characterGuid, session))
{
delete session;
return false;
}
ObjectGuid playerGuid = ObjectGuid::Create<HighGuid::Player>(characterGuid);
if (!session->InitializeClientlessPlayer(playerGuid))
{
RemoveClientlessSession(characterGuid);
return false;
}
TC_LOG_INFO("server.worldserver",
"Created clientless player session for character GUID %u (account %u).",
characterGuid, accountId);
return true;
}
bool World::RemoveSession(uint32 id)
{
///- Find the session, kick the user, but we can't delete session at this moment to prevent iterator invalidation
+1
View File
@@ -612,6 +612,7 @@ class TC_GAME_API World
WorldSession* FindClientlessSession(uint32 characterGuid) const;
bool AddClientlessSession(uint32 characterGuid, WorldSession* session);
bool RemoveClientlessSession(uint32 characterGuid);
bool CreateClientlessPlayerSession(uint32 accountId, uint32 characterGuid);
SessionMap const& GetAllClientlessSessions() const { return m_clientlessSessions; }
uint32 GetClientlessSessionCount() const { return uint32(m_clientlessSessions.size()); }
void AddInstanceSocket(std::weak_ptr<WorldSocket> sock, uint64 connectToKey);