mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-31 13:16:39 +00:00
Implement bazaar item identity and offline trading rework
This commit is contained in:
@@ -9,6 +9,7 @@ set(world_sources
|
||||
cli/cli_database_concurrency.cpp
|
||||
cli/cli_database_dump.cpp
|
||||
cli/cli_database_get_schema.cpp
|
||||
cli/cli_database_item_unique_ids.cpp
|
||||
cli/cli_database_set_account_status.cpp
|
||||
cli/cli_database_updates.cpp
|
||||
cli/cli_database_version.cpp
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "world/world_server_cli.h"
|
||||
|
||||
#include "world/worlddb.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
void WorldserverCLI::DatabaseItemUniqueIds(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||
{
|
||||
description = "Runs item_unique_id preflight, migration, and verification tasks";
|
||||
|
||||
std::vector<std::string> arguments = {};
|
||||
std::vector<std::string> options = {
|
||||
"--preflight",
|
||||
"--migrate",
|
||||
"--verify",
|
||||
"--verbose",
|
||||
"--keep-trading-state",
|
||||
};
|
||||
|
||||
if (cmd[{"-h", "--help"}]) {
|
||||
return;
|
||||
}
|
||||
|
||||
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
|
||||
|
||||
const bool verbose = cmd[{"-v", "--verbose"}];
|
||||
const bool migrate = cmd[{"--migrate"}];
|
||||
const bool verify = cmd[{"--verify"}];
|
||||
const bool preflight = cmd[{"--preflight"}] || (!migrate && !verify);
|
||||
const bool clear_trading_state = !cmd[{"--keep-trading-state"}];
|
||||
bool success = true;
|
||||
|
||||
if (preflight) {
|
||||
success = database.PreflightItemUniqueIdMigration(verbose) && success;
|
||||
}
|
||||
|
||||
if (migrate) {
|
||||
if (!database.MigrateItemUniqueIdData(clear_trading_state, verbose)) {
|
||||
LogError("Item unique id migration failed verification");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (verify) {
|
||||
if (!database.VerifyItemUniqueIdMigration(verbose)) {
|
||||
LogError("Item unique id verification failed");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -2403,7 +2403,7 @@ bool Client::StoreCharacter(
|
||||
e.ornament_icon = inst->GetOrnamentationIcon();
|
||||
e.ornament_idfile = inst->GetOrnamentationIDFile();
|
||||
e.ornament_hero_model = inst->GetOrnamentHeroModel();
|
||||
e.guid = inst->GetSerialNumber();
|
||||
e.item_unique_id = inst->GetUniqueID();
|
||||
|
||||
v.emplace_back(e);
|
||||
}
|
||||
|
||||
@@ -202,6 +202,9 @@ void ClientListEntry::Update(ZoneServer *iZS, ServerClientList_Struct *scl, CLE_
|
||||
m_lfg = scl->LFG;
|
||||
m_gm = scl->gm;
|
||||
m_client_version = scl->ClientVersion;
|
||||
m_trader = scl->trader;
|
||||
m_buyer = scl->buyer;
|
||||
m_offline = scl->offline;
|
||||
|
||||
// Fields from the LFG Window
|
||||
if ((scl->LFGFromLevel != 0) && (scl->LFGToLevel != 0)) {
|
||||
@@ -219,6 +222,10 @@ void ClientListEntry::LeavingZone(ZoneServer *iZS, CLE_Status iOnline)
|
||||
if (iZS != 0 && iZS != m_zone_server) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_trader = false;
|
||||
m_buyer = false;
|
||||
m_offline = false;
|
||||
SetOnline(iOnline);
|
||||
|
||||
SharedTaskManager::Instance()->RemoveActiveInvitationByCharacterID(CharID());
|
||||
@@ -260,6 +267,10 @@ void ClientListEntry::ClearVars(bool iAll)
|
||||
m_lfg = 0;
|
||||
m_gm = 0;
|
||||
m_client_version = 0;
|
||||
m_trader = false;
|
||||
m_buyer = false;
|
||||
m_offline = false;
|
||||
|
||||
for (auto &elem: m_tell_queue) {
|
||||
safe_delete_array(elem);
|
||||
}
|
||||
|
||||
+30
-21
@@ -13,7 +13,8 @@ typedef enum {
|
||||
Online,
|
||||
CharSelect,
|
||||
Zoning,
|
||||
InZone
|
||||
InZone,
|
||||
OfflineMode
|
||||
} CLE_Status;
|
||||
|
||||
static const char *CLEStatusString[] = {
|
||||
@@ -22,7 +23,8 @@ static const char *CLEStatusString[] = {
|
||||
"Online",
|
||||
"CharSelect",
|
||||
"Zoning",
|
||||
"InZone"
|
||||
"InZone",
|
||||
"OfflineMode"
|
||||
};
|
||||
|
||||
class ZoneServer;
|
||||
@@ -102,6 +104,10 @@ public:
|
||||
inline bool GetLFGMatchFilter() const { return m_lfg_match_filter; }
|
||||
inline const char *GetLFGComments() const { return m_lfg_comments; }
|
||||
inline uint8 GetClientVersion() { return m_client_version; }
|
||||
bool GetTrader() const { return m_trader; }
|
||||
bool GetBuyer() const { return m_buyer; }
|
||||
bool GetOfflineMode() const { return m_offline; }
|
||||
void SetOfflineMode(bool status) { m_offline = status; }
|
||||
|
||||
inline bool TellQueueFull() const { return m_tell_queue.size() >= RuleI(World, TellQueueSize); }
|
||||
inline bool TellQueueEmpty() const { return m_tell_queue.empty(); }
|
||||
@@ -134,25 +140,28 @@ private:
|
||||
|
||||
// Character info
|
||||
ZoneServer *m_zone_server{};
|
||||
uint32 m_zone{};
|
||||
uint16 m_instance{};
|
||||
uint32 m_char_id{};
|
||||
char m_char_name[64]{};
|
||||
uint8 m_level{};
|
||||
uint8 m_class_{};
|
||||
uint16 m_race{};
|
||||
uint8 m_anon{};
|
||||
uint8 m_tells_off{};
|
||||
uint32 m_guild_id{};
|
||||
uint32 m_guild_rank;
|
||||
bool m_guild_tribute_opt_in{};
|
||||
bool m_lfg{};
|
||||
uint8 m_gm{};
|
||||
uint8 m_client_version{};
|
||||
uint8 m_lfg_from_level{};
|
||||
uint8 m_lfg_to_level{};
|
||||
bool m_lfg_match_filter{};
|
||||
char m_lfg_comments[64]{};
|
||||
uint32 m_zone{};
|
||||
uint16 m_instance{};
|
||||
uint32 m_char_id{};
|
||||
char m_char_name[64]{};
|
||||
uint8 m_level{};
|
||||
uint8 m_class_{};
|
||||
uint16 m_race{};
|
||||
uint8 m_anon{};
|
||||
uint8 m_tells_off{};
|
||||
uint32 m_guild_id{};
|
||||
uint32 m_guild_rank;
|
||||
bool m_guild_tribute_opt_in{};
|
||||
bool m_lfg{};
|
||||
uint8 m_gm{};
|
||||
uint8 m_client_version{};
|
||||
uint8 m_lfg_from_level{};
|
||||
uint8 m_lfg_to_level{};
|
||||
bool m_lfg_match_filter{};
|
||||
char m_lfg_comments[64]{};
|
||||
bool m_trader = false;
|
||||
bool m_buyer = false;
|
||||
bool m_offline = false;
|
||||
|
||||
// Tell Queue -- really a vector :D
|
||||
std::vector<ServerChannelMessage_Struct *> m_tell_queue;
|
||||
|
||||
+59
-22
@@ -35,6 +35,7 @@
|
||||
#include "world/zoneserver.h"
|
||||
|
||||
#include <set>
|
||||
#include "../zone/string_ids.h"
|
||||
|
||||
uint32 numplayers = 0; //this really wants to be a member variable of ClientList...
|
||||
|
||||
@@ -427,7 +428,10 @@ void ClientList::ClientUpdate(ZoneServer *zoneserver, ServerClientList_Struct *s
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->GetID() == scl->wid) {
|
||||
cle = iterator.GetData();
|
||||
if (scl->remove == 2) {
|
||||
if (scl->remove == 3) {
|
||||
cle->Update(zoneserver, scl, CLE_Status::OfflineMode);
|
||||
}
|
||||
else if (scl->remove == 2) {
|
||||
cle->LeavingZone(zoneserver, CLE_Status::Offline);
|
||||
}
|
||||
else if (scl->remove == 1) {
|
||||
@@ -441,7 +445,11 @@ void ClientList::ClientUpdate(ZoneServer *zoneserver, ServerClientList_Struct *s
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
if (scl->remove == 2) {
|
||||
|
||||
if (scl->remove == 3) {
|
||||
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status::OfflineMode);
|
||||
}
|
||||
else if (scl->remove == 2) {
|
||||
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status::Online);
|
||||
}
|
||||
else if (scl->remove == 1) {
|
||||
@@ -479,7 +487,10 @@ void ClientList::ClientUpdate(ZoneServer *zoneserver, ServerClientList_Struct *s
|
||||
" LFGFromLevel [{}]"
|
||||
" LFGToLevel [{}]"
|
||||
" LFGMatchFilter [{}]"
|
||||
" LFGComments [{}]",
|
||||
" LFGComments [{}]"
|
||||
" Trader [{}]"
|
||||
" Buyer [{}]"
|
||||
" Offline [{}]",
|
||||
scl->remove,
|
||||
scl->wid,
|
||||
scl->IP,
|
||||
@@ -506,7 +517,10 @@ void ClientList::ClientUpdate(ZoneServer *zoneserver, ServerClientList_Struct *s
|
||||
scl->LFGFromLevel,
|
||||
scl->LFGToLevel,
|
||||
scl->LFGMatchFilter,
|
||||
scl->LFGComments
|
||||
scl->LFGComments,
|
||||
scl->trader,
|
||||
scl->buyer,
|
||||
scl->offline
|
||||
);
|
||||
|
||||
clientlist.Insert(cle);
|
||||
@@ -784,7 +798,14 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
||||
rankstring = 0;
|
||||
iterator.Advance();
|
||||
continue;
|
||||
} else if (cle->GetGM()) {
|
||||
}
|
||||
else if (cle->GetTrader()) {
|
||||
rankstring = TRADER;
|
||||
}
|
||||
else if (cle->GetBuyer()) {
|
||||
rankstring = BUYER;
|
||||
}
|
||||
else if (cle->GetGM()) {
|
||||
if (cle->Admin() >= AccountStatus::GMImpossible) {
|
||||
rankstring = 5021;
|
||||
} else if (cle->Admin() >= AccountStatus::GMMgmt) {
|
||||
@@ -877,6 +898,18 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
||||
strcpy(placcount,cle->AccountName());
|
||||
}
|
||||
|
||||
if (cle->GetOfflineMode()) {
|
||||
if (cle->GetTrader()) {
|
||||
pidstring = 0x0430;
|
||||
rankstring = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
if (cle->GetBuyer()) {
|
||||
pidstring = 0x0420;
|
||||
rankstring = 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(bufptr,&formatstring, sizeof(uint32));
|
||||
bufptr+=sizeof(uint32);
|
||||
memcpy(bufptr,&pidstring, sizeof(uint32));
|
||||
@@ -1631,25 +1664,29 @@ void ClientList::OnTick(EQ::Timer *t)
|
||||
outclient["Server"] = Json::Value();
|
||||
}
|
||||
|
||||
outclient["CharID"] = cle->CharID();
|
||||
outclient["name"] = cle->name();
|
||||
outclient["zone"] = cle->zone();
|
||||
outclient["instance"] = cle->instance();
|
||||
outclient["level"] = cle->level();
|
||||
outclient["class_"] = cle->class_();
|
||||
outclient["race"] = cle->race();
|
||||
outclient["Anon"] = cle->Anon();
|
||||
outclient["CharID"] = cle->CharID();
|
||||
outclient["name"] = cle->name();
|
||||
outclient["zone"] = cle->zone();
|
||||
outclient["instance"] = cle->instance();
|
||||
outclient["level"] = cle->level();
|
||||
outclient["class_"] = cle->class_();
|
||||
outclient["race"] = cle->race();
|
||||
outclient["Anon"] = cle->Anon();
|
||||
|
||||
outclient["TellsOff"] = cle->TellsOff();
|
||||
outclient["GuildID"] = cle->GuildID();
|
||||
outclient["LFG"] = cle->LFG();
|
||||
outclient["GM"] = cle->GetGM();
|
||||
outclient["LocalClient"] = cle->IsLocalClient();
|
||||
outclient["LFGFromLevel"] = cle->GetLFGFromLevel();
|
||||
outclient["LFGToLevel"] = cle->GetLFGToLevel();
|
||||
outclient["TellsOff"] = cle->TellsOff();
|
||||
outclient["GuildID"] = cle->GuildID();
|
||||
outclient["LFG"] = cle->LFG();
|
||||
outclient["GM"] = cle->GetGM();
|
||||
outclient["LocalClient"] = cle->IsLocalClient();
|
||||
outclient["LFGFromLevel"] = cle->GetLFGFromLevel();
|
||||
outclient["LFGToLevel"] = cle->GetLFGToLevel();
|
||||
outclient["LFGMatchFilter"] = cle->GetLFGMatchFilter();
|
||||
outclient["LFGComments"] = cle->GetLFGComments();
|
||||
outclient["ClientVersion"] = cle->GetClientVersion();
|
||||
outclient["LFGComments"] = cle->GetLFGComments();
|
||||
outclient["ClientVersion"] = cle->GetClientVersion();
|
||||
outclient["Trader"] = cle->GetTrader();
|
||||
outclient["Buyer"] = cle->GetBuyer();
|
||||
outclient["OfflineMode"] = cle->GetOfflineMode();
|
||||
|
||||
out["data"].append(outclient);
|
||||
|
||||
Iterator.Advance();
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ struct EQ::Net::ConsoleLoginStatus CheckLogin(const std::string &username, const
|
||||
const std::string& account_name = database.GetAccountName(ret.account_id);
|
||||
|
||||
ret.account_name = account_name;
|
||||
ret.status = database.GetAccountStatus(ret.account_id);
|
||||
ret.status = database.GetAccountStatus(ret.account_id).status;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+141
-11
@@ -4,6 +4,11 @@
|
||||
#include "common/eqemu_logsys.h"
|
||||
#include "common/misc_functions.h"
|
||||
#include "common/packet_dump.h"
|
||||
#include "common/repositories/account_repository.h"
|
||||
#include "common/repositories/buyer_repository.h"
|
||||
#include "common/repositories/character_data_repository.h"
|
||||
#include "common/repositories/offline_character_sessions_repository.h"
|
||||
#include "common/repositories/trader_repository.h"
|
||||
#include "common/servertalk.h"
|
||||
#include "common/strings.h"
|
||||
#include "common/version.h"
|
||||
@@ -43,9 +48,9 @@ void LoginServer::ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p)
|
||||
const WorldConfig *Config = WorldConfig::get();
|
||||
LogNetcode("Received ServerPacket from LS OpCode {:#04x}", opcode);
|
||||
|
||||
UsertoWorldRequestLegacy *utwr = (UsertoWorldRequestLegacy *) p.Data();
|
||||
uint32 id = database.GetAccountIDFromLSID("eqemu", utwr->lsaccountid);
|
||||
int16 status = database.GetAccountStatus(id);
|
||||
UsertoWorldRequestLegacy *utwr = (UsertoWorldRequestLegacy *) p.Data();
|
||||
uint32 id = database.GetAccountIDFromLSID("eqemu", utwr->lsaccountid);
|
||||
int16 status = database.GetAccountStatus(id).status;
|
||||
|
||||
LogDebug(
|
||||
"id [{}] status [{}] account_id [{}] world_id [{}] from_id [{}] to_id [{}] ip [{}]",
|
||||
@@ -123,14 +128,19 @@ void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p)
|
||||
const WorldConfig *Config = WorldConfig::get();
|
||||
LogNetcode("Received ServerPacket from LS OpCode {:#04x}", opcode);
|
||||
|
||||
UsertoWorldRequest *utwr = (UsertoWorldRequest *) p.Data();
|
||||
uint32 id = database.GetAccountIDFromLSID(utwr->login, utwr->lsaccountid);
|
||||
int16 status = database.GetAccountStatus(id);
|
||||
UsertoWorldRequest *utwr = (UsertoWorldRequest *) p.Data();
|
||||
uint32 id = database.GetAccountIDFromLSID(utwr->login, utwr->lsaccountid);
|
||||
auto status_record = database.GetAccountStatus(id);
|
||||
auto client = ClientList::Instance()->FindCLEByAccountID(id);
|
||||
|
||||
if (client) {
|
||||
client->SetOfflineMode(status_record.offline);
|
||||
}
|
||||
|
||||
LogDebug(
|
||||
"id [{}] status [{}] account_id [{}] world_id [{}] from_id [{}] to_id [{}] ip [{}]",
|
||||
id,
|
||||
status,
|
||||
status_record.status,
|
||||
utwr->lsaccountid,
|
||||
utwr->worldid,
|
||||
utwr->FromID,
|
||||
@@ -152,7 +162,7 @@ void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p)
|
||||
utwrs->response = UserToWorldStatusSuccess;
|
||||
|
||||
if (Config->Locked == true) {
|
||||
if (status < (RuleI(GM, MinStatusToBypassLockedServer))) {
|
||||
if (status_record.status < (RuleI(GM, MinStatusToBypassLockedServer))) {
|
||||
LogDebug(
|
||||
"Server locked and status is not high enough for account_id [{0}]",
|
||||
utwr->lsaccountid
|
||||
@@ -164,27 +174,34 @@ void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p)
|
||||
}
|
||||
|
||||
int32 x = Config->MaxClients;
|
||||
if ((int32) numplayers >= x && x != -1 && x != 255 && status < (RuleI(GM, MinStatusToBypassLockedServer))) {
|
||||
if ((int32) numplayers >= x && x != -1 && x != 255 && status_record.status < (RuleI(GM, MinStatusToBypassLockedServer))) {
|
||||
LogDebug("World at capacity account_id [{0}]", utwr->lsaccountid);
|
||||
utwrs->response = UserToWorldStatusWorldAtCapacity;
|
||||
SendPacket(&outpack);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == -1) {
|
||||
if (status_record.status == -1) {
|
||||
LogDebug("User suspended account_id [{0}]", utwr->lsaccountid);
|
||||
utwrs->response = UserToWorldStatusSuspended;
|
||||
SendPacket(&outpack);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == -2) {
|
||||
if (status_record.status == -2) {
|
||||
LogDebug("User banned account_id [{0}]", utwr->lsaccountid);
|
||||
utwrs->response = UserToWorldStatusBanned;
|
||||
SendPacket(&outpack);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status_record.offline || OfflineCharacterSessionsRepository::ExistsByAccountId(database, id)) {
|
||||
LogDebug("User has an offline character for account_id [{0}]", utwr->lsaccountid);
|
||||
utwrs->response = UserToWorldStatusOffilineTraderBuyer;
|
||||
SendPacket(&outpack);
|
||||
return;
|
||||
}
|
||||
|
||||
if (RuleB(World, EnforceCharacterLimitAtLogin)) {
|
||||
if (ClientList::Instance()->IsAccountInGame(utwr->lsaccountid)) {
|
||||
LogDebug("User already online account_id [{0}]", utwr->lsaccountid);
|
||||
@@ -572,6 +589,14 @@ bool LoginServer::Connect()
|
||||
std::placeholders::_2
|
||||
)
|
||||
);
|
||||
m_client->OnMessage(
|
||||
ServerOP_UsertoWorldCancelOfflineRequest,
|
||||
std::bind(
|
||||
&LoginServer::ProcessUserToWorldCancelOfflineRequest,
|
||||
this,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -687,3 +712,108 @@ void LoginServer::SendAccountUpdate(ServerPacket *pack)
|
||||
}
|
||||
}
|
||||
|
||||
void LoginServer::ProcessUserToWorldCancelOfflineRequest(uint16_t opcode, EQ::Net::Packet &p)
|
||||
{
|
||||
auto const Config = WorldConfig::get();
|
||||
LogNetcode("Received ServerPacket from LS OpCode {:#04x}", opcode);
|
||||
|
||||
auto utwr = static_cast<UsertoWorldRequest *>(p.Data());
|
||||
uint32 id = database.GetAccountIDFromLSID(utwr->login, utwr->lsaccountid);
|
||||
auto status_record = database.GetAccountStatus(id);
|
||||
|
||||
LogLoginserverDetail(
|
||||
"Step 4 - World received CancelOfflineRequest for client login server account id {} offline mode {}",
|
||||
id,
|
||||
status_record.offline
|
||||
);
|
||||
LogDebug(
|
||||
"id [{}] status [{}] account_id [{}] world_id [{}] ip [{}]",
|
||||
id,
|
||||
status_record.status,
|
||||
utwr->lsaccountid,
|
||||
utwr->worldid,
|
||||
utwr->IPAddr
|
||||
);
|
||||
|
||||
ServerPacket server_packet;
|
||||
server_packet.size = sizeof(UsertoWorldResponse);
|
||||
server_packet.pBuffer = new uchar[server_packet.size];
|
||||
memset(server_packet.pBuffer, 0, server_packet.size);
|
||||
|
||||
auto utwrs = reinterpret_cast<UsertoWorldResponse *>(server_packet.pBuffer);
|
||||
utwrs->lsaccountid = utwr->lsaccountid;
|
||||
utwrs->ToID = utwr->FromID;
|
||||
utwrs->worldid = utwr->worldid;
|
||||
utwrs->response = UserToWorldStatusSuccess;
|
||||
strn0cpy(utwrs->login, utwr->login, 64);
|
||||
|
||||
if (Config->Locked == true) {
|
||||
if (status_record.status < RuleI(GM, MinStatusToBypassLockedServer)) {
|
||||
LogDebug("Server locked and status is not high enough for account_id [{0}]", utwr->lsaccountid);
|
||||
server_packet.opcode = ServerOP_UsertoWorldCancelOfflineResponse;
|
||||
utwrs->response = UserToWorldStatusWorldUnavail;
|
||||
SendPacket(&server_packet);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int32 x = Config->MaxClients;
|
||||
if (static_cast<int32>(numplayers) >= x &&
|
||||
x != -1 &&
|
||||
x != 255 &&
|
||||
status_record.status < RuleI(GM, MinStatusToBypassLockedServer)
|
||||
) {
|
||||
LogDebug("World at capacity account_id [{0}]", utwr->lsaccountid);
|
||||
server_packet.opcode = ServerOP_UsertoWorldCancelOfflineResponse;
|
||||
utwrs->response = UserToWorldStatusWorldAtCapacity;
|
||||
SendPacket(&server_packet);
|
||||
return;
|
||||
}
|
||||
|
||||
auto session = OfflineCharacterSessionsRepository::GetByAccountId(database, id);
|
||||
auto trader = TraderRepository::GetAccountZoneIdAndInstanceIdByAccountId(database, id);
|
||||
uint32 zone_id = session.id ? session.zone_id : trader.char_zone_id;
|
||||
int32 instance_id = session.id ? session.instance_id : trader.char_zone_instance_id;
|
||||
uint32 character_id = session.id ? session.character_id : trader.character_id;
|
||||
|
||||
if ((session.id || trader.id) &&
|
||||
ZSList::Instance()->IsZoneBootedByZoneIdAndInstanceId(zone_id, instance_id)) {
|
||||
LogLoginserverDetail(
|
||||
"Step 5a(1) - World Checked offline users zone/instance is booted. "
|
||||
"Sending packet to zone id {} instance id {}",
|
||||
zone_id,
|
||||
instance_id);
|
||||
|
||||
server_packet.opcode = ServerOP_UsertoWorldCancelOfflineRequest;
|
||||
ZSList::Instance()->SendPacketToBootedZones(&server_packet);
|
||||
return;
|
||||
}
|
||||
|
||||
LogLoginserverDetail("Step 5b(1) - World determined offline users zone/instance is not booted. Ignoring zone.");
|
||||
|
||||
LogLoginserverDetail("Step 5b(2) - World clearing users offline status from account table.");
|
||||
database.TransactionBegin();
|
||||
AccountRepository::SetOfflineStatus(database, id, false);
|
||||
OfflineCharacterSessionsRepository::DeleteByAccountId(database, id);
|
||||
|
||||
LogLoginserverDetail("Step 5b(3) - World clearing trader and buyer tables.");
|
||||
if (character_id) {
|
||||
TraderRepository::DeleteWhere(database, fmt::format("`character_id` = '{}'", character_id));
|
||||
BuyerRepository::DeleteBuyer(database, character_id);
|
||||
}
|
||||
|
||||
auto commit_result = database.TransactionCommit();
|
||||
if (!commit_result.Success()) {
|
||||
database.TransactionRollback();
|
||||
LogError(
|
||||
"Failed clearing offline session state for account [{}]: ({}) {}",
|
||||
id,
|
||||
commit_result.ErrorNumber(),
|
||||
commit_result.ErrorMessage()
|
||||
);
|
||||
utwrs->response = UserToWorldStatusWorldUnavail;
|
||||
}
|
||||
|
||||
server_packet.opcode = ServerOP_UsertoWorldCancelOfflineResponse;
|
||||
SendPacket(&server_packet);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ private:
|
||||
void ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p);
|
||||
void ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p);
|
||||
void ProcessLSAccountUpdate(uint16_t opcode, EQ::Net::Packet &p);
|
||||
void ProcessUserToWorldCancelOfflineRequest(uint16_t opcode, EQ::Net::Packet &p);
|
||||
|
||||
std::unique_ptr<EQ::Timer> m_keepalive;
|
||||
|
||||
|
||||
@@ -634,4 +634,3 @@ void WorldBoot::SendDiscordMessage(int webhook_id, const std::string &message)
|
||||
safe_delete(pack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ void WorldserverCLI::CommandHandler(int argc, char **argv)
|
||||
function_map["database:schema"] = &WorldserverCLI::DatabaseGetSchema;
|
||||
function_map["database:dump"] = &WorldserverCLI::DatabaseDump;
|
||||
function_map["database:updates"] = &WorldserverCLI::DatabaseUpdates;
|
||||
function_map["database:item-unique-ids"] = &WorldserverCLI::DatabaseItemUniqueIds;
|
||||
function_map["test:test"] = &WorldserverCLI::TestCommand;
|
||||
function_map["test:colors"] = &WorldserverCLI::TestColors;
|
||||
function_map["test:expansion"] = &WorldserverCLI::ExpansionTestCommand;
|
||||
|
||||
@@ -17,6 +17,7 @@ public:
|
||||
static void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
static void DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
static void DatabaseUpdates(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
static void DatabaseItemUniqueIds(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
static void TestCommand(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
static void TestColors(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
static void ExpansionTestCommand(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
|
||||
+1
-1
@@ -876,7 +876,7 @@ bool WorldDatabase::GetCharSelInventory(
|
||||
continue;
|
||||
}
|
||||
|
||||
EQ::ItemInstance *inst = content_db.CreateBaseItem(item, e.charges);
|
||||
EQ::ItemInstance *inst = content_db.CreateBaseItem(item, e.charges, e.item_unique_id);
|
||||
|
||||
if (!inst) {
|
||||
continue;
|
||||
|
||||
@@ -1019,3 +1019,15 @@ void ZSList::QueueServerReload(ServerReload::Type &type)
|
||||
m_queued_reloads.emplace_back(type);
|
||||
m_queued_reloads_mutex.unlock();
|
||||
}
|
||||
|
||||
bool ZSList::IsZoneBootedByZoneIdAndInstanceId(uint32 zone_id, uint32 instance_id) const
|
||||
{
|
||||
for (auto const& z : zone_server_list) {
|
||||
auto r = z.get();
|
||||
if (r && r->GetZoneID() == zone_id && r->GetInstanceID() == instance_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ public:
|
||||
bool SendPacketToZonesWithGMs(ServerPacket *pack);
|
||||
bool SendPacketToBootedZones(ServerPacket* pack);
|
||||
bool SetLockedZone(uint16 iZoneID, bool iLock);
|
||||
bool IsZoneBootedByZoneIdAndInstanceId(uint32 zone_id, uint32 instance_id) const;
|
||||
|
||||
EQTime worldclock;
|
||||
|
||||
|
||||
+43
-16
@@ -1675,21 +1675,23 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
break;
|
||||
}
|
||||
case ServerOP_BazaarPurchase: {
|
||||
auto in = (BazaarPurchaseMessaging_Struct *)pack->pBuffer;
|
||||
if (in->trader_buy_struct.trader_id <= 0) {
|
||||
LogTrading(
|
||||
"World Message <red>[{}] received with invalid trader_id <red>[{}]",
|
||||
"ServerOP_BazaarPurchase",
|
||||
in->trader_buy_struct.trader_id
|
||||
);
|
||||
return;
|
||||
auto in = reinterpret_cast<BazaarPurchaseMessaging_Struct *>(pack->pBuffer);
|
||||
switch (in->transaction_status) {
|
||||
case BazaarPurchaseBuyerCompleteSendToSeller: {
|
||||
ZSList::Instance()->SendPacket(in->trader_zone_id, in->trader_zone_instance_id, pack);
|
||||
break;
|
||||
}
|
||||
case BazaarPurchaseTraderFailed:
|
||||
case BazaarPurchaseSuccess: {
|
||||
ZSList::Instance()->SendPacket(in->buyer_zone_id, in->buyer_zone_instance_id, pack);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogError(
|
||||
"ServerOP_BazaarPurchase received with no corresponding action for [{}]",
|
||||
in->transaction_status);
|
||||
}
|
||||
}
|
||||
|
||||
auto trader = ClientList::Instance()->FindCLEByCharacterID(in->trader_buy_struct.trader_id);
|
||||
if (trader) {
|
||||
ZSList::Instance()->SendPacket(trader->zone(), trader->instance(), pack);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ServerOP_BuyerMessaging: {
|
||||
@@ -1725,9 +1727,34 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_UsertoWorldCancelOfflineResponse: {
|
||||
auto utwr = reinterpret_cast<UsertoWorldResponse *>(pack->pBuffer);
|
||||
|
||||
ServerPacket server_packet;
|
||||
server_packet.opcode = ServerOP_UsertoWorldCancelOfflineResponse;
|
||||
server_packet.size = sizeof(UsertoWorldResponse);
|
||||
server_packet.pBuffer = new uchar[server_packet.size];
|
||||
memset(server_packet.pBuffer, 0, server_packet.size);
|
||||
|
||||
auto utwrs = reinterpret_cast<UsertoWorldResponse *>(server_packet.pBuffer);
|
||||
utwrs->lsaccountid = utwr->lsaccountid;
|
||||
utwrs->ToID = utwr->FromID;
|
||||
utwrs->worldid = utwr->worldid;
|
||||
utwrs->response = UserToWorldStatusSuccess;
|
||||
strn0cpy(utwrs->login, utwr->login, 64);
|
||||
|
||||
LogLoginserverDetail(
|
||||
"Step 7a - World received ServerOP_UsertoWorldCancelOfflineResponse back to login with success."
|
||||
);
|
||||
|
||||
LoginServerList::Instance()->SendPacket(&server_packet);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogInfo("Unknown ServerOPcode from zone {:#04x}, size [{}]", pack->opcode, pack->size);
|
||||
|
||||
Reference in New Issue
Block a user