eqemu-server/world/cliententry.cpp
Chris Miles eb6ac25540
[Code Cleanup] More login <-> world code cleanup (#4724)
* More cleanup

* More cleanup
2025-02-28 16:08:06 -06:00

375 lines
9.0 KiB
C++

#include "../common/global_define.h"
#include "cliententry.h"
#include "clientlist.h"
#include "login_server.h"
#include "login_server_list.h"
#include "shared_task_manager.h"
#include "worlddb.h"
#include "zoneserver.h"
#include "world_config.h"
extern uint32 numplayers;
extern LoginServerList loginserverlist;
extern ClientList client_list;
extern volatile bool RunLoops;
extern SharedTaskManager shared_task_manager;
ClientListEntry::ClientListEntry(
uint32 id,
uint32 login_server_id,
const char *login_server_name,
const char *account_name,
const char *login_key,
int16 is_world_admin,
uint32 ip_address,
uint8 local
)
: m_id(id)
{
ClearVars(true);
LogDebug(
"id [{}] loginserver_id [{}] loginserver_name [{}] login_name [{}] login_key [{}] is_world_admin [{}] ip [{}] local [{}]",
id,
login_server_id,
login_server_name,
account_name,
login_key,
is_world_admin,
ip_address,
local
);
m_ip_address = ip_address;
m_login_server_id = login_server_id;
if (login_server_id > 0) {
m_account_id = database.GetAccountIDFromLSID(
login_server_name,
login_server_id,
m_account_name,
&m_admin
);
}
strn0cpy(m_login_account_name, account_name, sizeof(m_login_account_name));
strn0cpy(m_key, login_key, sizeof(m_key));
strn0cpy(m_source_loginserver, login_server_name, sizeof(m_source_loginserver));
m_world_admin = is_world_admin;
m_is_local = (local == 1);
memset(m_lfg_comments, 0, 64);
}
ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer *z, ServerClientList_Struct *scl, CLE_Status online)
: m_id(in_id)
{
ClearVars(true);
m_ip_address = 0;
m_login_server_id = scl->LSAccountID;
strn0cpy(m_login_account_name, scl->name, sizeof(m_login_account_name));
strn0cpy(m_key, scl->lskey, sizeof(m_key));
m_world_admin = 0;
m_account_id = scl->AccountID;
strn0cpy(m_account_name, scl->AccountName, sizeof(m_account_name));
m_admin = scl->Admin;
m_instance = 0;
m_lfg_from_level = 0;
m_lfg_to_level = 0;
m_lfg_match_filter = false;
memset(m_lfg_comments, 0, 64);
if (online >= CLE_Status::Zoning) {
Update(z, scl, online);
}
else {
SetOnline(online);
}
}
ClientListEntry::~ClientListEntry()
{
if (RunLoops) {
Camp(); // updates zoneserver's numplayers
client_list.RemoveCLEReferances(this);
}
for (auto &elem: m_tell_queue) {
safe_delete_array(elem);
}
m_tell_queue.clear();
}
void ClientListEntry::SetChar(uint32 iCharID, const char *iCharName)
{
m_char_id = iCharID;
strn0cpy(m_char_name, iCharName, sizeof(m_char_name));
}
void ClientListEntry::SetOnline(CLE_Status iOnline)
{
LogClientLogin(
"Online status [{}] ({}) status [{}] ({})",
AccountName(),
AccountID(),
CLEStatusString[iOnline],
static_cast<int>(iOnline)
);
if (iOnline >= CLE_Status::Online && m_online < CLE_Status::Online) {
numplayers++;
}
else if (iOnline < CLE_Status::Online && m_online >= CLE_Status::Online) {
numplayers--;
}
if (iOnline != CLE_Status::Online || m_online < CLE_Status::Online) {
m_online = iOnline;
}
if (iOnline < CLE_Status::Zoning) {
Camp();
}
if (m_online >= CLE_Status::Online) {
m_stale = 0;
}
}
void ClientListEntry::LSUpdate(ZoneServer *iZS)
{
if (WorldConfig::get()->UpdateStats) {
auto pack = new ServerPacket;
pack->opcode = ServerOP_LSZoneInfo;
pack->size = sizeof(LoginserverZoneInfoUpdate);
pack->pBuffer = new uchar[pack->size];
auto *zone = (LoginserverZoneInfoUpdate *) pack->pBuffer;
zone->count = iZS->NumPlayers();
zone->zone = iZS->GetZoneID();
zone->zone_wid = iZS->GetID();
loginserverlist.SendPacket(pack);
safe_delete(pack);
}
}
void ClientListEntry::LSZoneChange(ZoneToZone_Struct *ztz)
{
if (WorldConfig::get()->UpdateStats) {
auto pack = new ServerPacket;
pack->opcode = ServerOP_LSPlayerZoneChange;
pack->size = sizeof(ServerLSPlayerZoneChange_Struct);
pack->pBuffer = new uchar[pack->size];
auto *zonechange = (ServerLSPlayerZoneChange_Struct *) pack->pBuffer;
zonechange->lsaccount_id = LSID();
zonechange->from = ztz->current_zone_id;
zonechange->to = ztz->requested_zone_id;
loginserverlist.SendPacket(pack);
safe_delete(pack);
}
}
void ClientListEntry::Update(ZoneServer *iZS, ServerClientList_Struct *scl, CLE_Status iOnline)
{
if (m_zone_server != iZS) {
if (m_zone_server) {
m_zone_server->RemovePlayer();
LSUpdate(m_zone_server);
}
if (iZS) {
iZS->AddPlayer();
LSUpdate(iZS);
}
}
m_zone_server = iZS;
m_zone = scl->zone;
m_instance = scl->instance_id;
m_char_id = scl->charid;
strcpy(m_char_name, scl->name);
if (m_account_id == 0) {
m_account_id = scl->AccountID;
strcpy(m_account_name, scl->AccountName);
strcpy(m_login_account_name, scl->AccountName);
m_ip_address = scl->IP;
m_login_server_id = scl->LSAccountID;
strn0cpy(m_key, scl->lskey, sizeof(m_key));
}
m_admin = scl->Admin;
m_level = scl->level;
m_class_ = scl->class_;
m_race = scl->race;
m_anon = scl->anon;
m_tells_off = scl->tellsoff;
m_guild_id = scl->guild_id;
m_guild_rank = scl->guild_rank;
m_guild_tribute_opt_in = scl->guild_tribute_opt_in;
m_lfg = scl->LFG;
m_gm = scl->gm;
m_client_version = scl->ClientVersion;
// Fields from the LFG Window
if ((scl->LFGFromLevel != 0) && (scl->LFGToLevel != 0)) {
m_lfg_from_level = scl->LFGFromLevel;
m_lfg_to_level = scl->LFGToLevel;
m_lfg_match_filter = scl->LFGMatchFilter;
memcpy(m_lfg_comments, scl->LFGComments, sizeof(m_lfg_comments));
}
SetOnline(iOnline);
}
void ClientListEntry::LeavingZone(ZoneServer *iZS, CLE_Status iOnline)
{
if (iZS != 0 && iZS != m_zone_server) {
return;
}
SetOnline(iOnline);
shared_task_manager.RemoveActiveInvitationByCharacterID(CharID());
if (m_zone_server) {
m_zone_server->RemovePlayer();
LSUpdate(m_zone_server);
}
m_zone_server = 0;
m_zone = 0;
}
void ClientListEntry::ClearVars(bool iAll)
{
if (iAll) {
m_online = CLE_Status::Never;
m_stale = 0;
m_login_server_id = 0;
memset(m_login_account_name, 0, sizeof(m_login_account_name));
memset(m_key, 0, sizeof(m_key));
m_world_admin = 0;
m_account_id = 0;
memset(m_account_name, 0, sizeof(m_account_name));
m_admin = AccountStatus::Player;
}
m_zone_server = 0;
m_zone = 0;
m_char_id = 0;
memset(m_char_name, 0, sizeof(m_char_name));
m_level = 0;
m_class_ = 0;
m_race = 0;
m_anon = 0;
m_tells_off = 0;
m_guild_id = GUILD_NONE;
m_guild_rank = 0;
m_lfg = 0;
m_gm = 0;
m_client_version = 0;
for (auto &elem: m_tell_queue) {
safe_delete_array(elem);
}
m_tell_queue.clear();
}
void ClientListEntry::Camp(ZoneServer *iZS)
{
if (iZS != 0 && iZS != m_zone_server) {
return;
}
if (m_zone_server) {
m_zone_server->RemovePlayer();
LSUpdate(m_zone_server);
}
ClearVars();
m_stale = 0;
}
bool ClientListEntry::CheckStale()
{
m_stale++;
if (m_stale > 20) {
if (m_online > CLE_Status::Offline) {
SetOnline(CLE_Status::Offline);
}
return true;
}
return false;
}
bool ClientListEntry::CheckAuth(uint32 loginserver_account_id, const char *key_password)
{
LogDebug(
"ls_account_id [{}] key_password [{}] key [{}]",
loginserver_account_id,
key_password,
m_key
);
if (m_login_server_id == loginserver_account_id && strncmp(m_key, key_password, 10) == 0) {
LogDebug(
"ls_account_id [{}] key_password [{}] m_key [{}] lsid [{}] m_account_id [{}]",
loginserver_account_id,
key_password,
m_key,
LSID(),
m_account_id
);
// create account if it doesn't exist
if (m_account_id == 0 && LSID() > 0) {
int16 default_account_status = WorldConfig::get()->DefaultStatus;
m_account_id = database.CreateAccount(
m_login_account_name,
std::string(),
default_account_status,
m_source_loginserver,
LSID()
);
if (!m_account_id) {
LogError(
"Error adding local account for LS login [{}] [{}], duplicate name",
m_source_loginserver,
m_login_account_name
);
return false;
}
strn0cpy(m_account_name, m_login_account_name, sizeof(m_account_name));
m_admin = default_account_status;
}
std::string lsworldadmin;
if (database.GetVariable("honorlsworldadmin", lsworldadmin)) {
if (Strings::ToInt(lsworldadmin) == 1 && m_world_admin != 0 &&
(m_admin < m_world_admin || m_admin == AccountStatus::Player)) {
m_admin = m_world_admin;
}
}
return true;
}
return false;
}
void ClientListEntry::ProcessTellQueue()
{
if (!Server()) {
return;
}
ServerPacket *pack;
auto it = m_tell_queue.begin();
while (it != m_tell_queue.end()) {
pack = new ServerPacket(
ServerOP_ChannelMessage,
sizeof(ServerChannelMessage_Struct) + strlen((*it)->message) + 1
);
memcpy(pack->pBuffer, *it, pack->size);
Server()->SendPacket(pack);
safe_delete(pack);
safe_delete_array(*it);
it = m_tell_queue.erase(it);
}
}