mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-14 03:11:28 +00:00
Added 'server ready' broadcast to UCS server so clients will reconnect after crash
This commit is contained in:
parent
c469571f62
commit
e547a1e778
@ -615,6 +615,7 @@ RULE_INT(Chat, KarmaGlobalChatLimit, 72) //amount of karma you need to be able t
|
|||||||
RULE_INT(Chat, GlobalChatLevelLimit, 8) //level limit you need to of reached to talk in ooc/auction/chat if your karma is too low.
|
RULE_INT(Chat, GlobalChatLevelLimit, 8) //level limit you need to of reached to talk in ooc/auction/chat if your karma is too low.
|
||||||
RULE_INT(Chat, ExpireClientVersionRequests, 3) // time in seconds to keep current cv requests active
|
RULE_INT(Chat, ExpireClientVersionRequests, 3) // time in seconds to keep current cv requests active
|
||||||
RULE_INT(Chat, ExpireClientVersionReplies, 30) // time in seconds to keep current cv replies active
|
RULE_INT(Chat, ExpireClientVersionReplies, 30) // time in seconds to keep current cv replies active
|
||||||
|
RULE_INT(Chat, UCSBroadcastServerReadyDelay, 60) // time in seconds to delay broadcast `server ready` after start-up
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Merchant)
|
RULE_CATEGORY(Merchant)
|
||||||
|
|||||||
@ -192,6 +192,7 @@
|
|||||||
#define ServerOP_CZSetEntityVariableByClientName 0x4012
|
#define ServerOP_CZSetEntityVariableByClientName 0x4012
|
||||||
#define ServerOP_UCSClientVersionRequest 0x4013
|
#define ServerOP_UCSClientVersionRequest 0x4013
|
||||||
#define ServerOP_UCSClientVersionReply 0x4014
|
#define ServerOP_UCSClientVersionReply 0x4014
|
||||||
|
#define ServerOP_UCSBroadcastServerReady 0x4015
|
||||||
/* Query Server OP Codes */
|
/* Query Server OP Codes */
|
||||||
#define ServerOP_QSPlayerLogTrades 0x5010
|
#define ServerOP_QSPlayerLogTrades 0x5010
|
||||||
#define ServerOP_QSPlayerLogHandins 0x5011
|
#define ServerOP_QSPlayerLogHandins 0x5011
|
||||||
@ -1289,6 +1290,11 @@ struct UCSClientVersionReply_Struct {
|
|||||||
EQEmu::versions::ClientVersion client_version;
|
EQEmu::versions::ClientVersion client_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UCSBroadcastServerReady_Struct {
|
||||||
|
char chat_prefix[128];
|
||||||
|
char mail_prefix[128];
|
||||||
|
};
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -110,6 +110,23 @@ uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) {
|
|||||||
return EntitledTime;
|
return EntitledTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey)
|
||||||
|
{
|
||||||
|
char MailKeyString[17];
|
||||||
|
|
||||||
|
if (RuleB(Chat, EnableMailKeyIPVerification) == true)
|
||||||
|
sprintf(MailKeyString, "%08X%08X", IPAddress, MailKey);
|
||||||
|
else
|
||||||
|
sprintf(MailKeyString, "%08X", MailKey);
|
||||||
|
|
||||||
|
std::string query = StringFormat("UPDATE character_data SET mailkey = '%s' WHERE id = '%i'",
|
||||||
|
MailKeyString, CharID);
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
if (!results.Success())
|
||||||
|
Log(Logs::General, Logs::Error, "SharedDatabase::SetMailKey(%i, %s) : %s", CharID, MailKeyString, results.ErrorMessage().c_str());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool SharedDatabase::SaveCursor(uint32 char_id, std::list<EQEmu::ItemInstance*>::const_iterator &start, std::list<EQEmu::ItemInstance*>::const_iterator &end)
|
bool SharedDatabase::SaveCursor(uint32 char_id, std::list<EQEmu::ItemInstance*>::const_iterator &start, std::list<EQEmu::ItemInstance*>::const_iterator &end)
|
||||||
{
|
{
|
||||||
// Delete cursor items
|
// Delete cursor items
|
||||||
|
|||||||
@ -72,6 +72,7 @@ class SharedDatabase : public Database
|
|||||||
void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message);
|
void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message);
|
||||||
bool GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings);
|
bool GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings);
|
||||||
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
|
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
|
||||||
|
void SetMailKey(int CharID, int IPAddress, int MailKey);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Character InventoryProfile
|
Character InventoryProfile
|
||||||
|
|||||||
@ -140,10 +140,12 @@ int main() {
|
|||||||
|
|
||||||
worldserver = new WorldServer;
|
worldserver = new WorldServer;
|
||||||
|
|
||||||
// now that we can send packets to world, see if there's a
|
worldserver->ActivateBroadcastServerReadyTimer();
|
||||||
// broadcast opcode that tells the client to relog into ucs
|
|
||||||
|
|
||||||
while(RunLoops) {
|
while(RunLoops) {
|
||||||
|
// this triggers clients to 'reconnect' to ucs after server crash
|
||||||
|
if (worldserver->HasBroadcastServerReadyTimer())
|
||||||
|
worldserver->ProcessBroadcastServerReady();
|
||||||
|
|
||||||
Timer::SetCurrentTime();
|
Timer::SetCurrentTime();
|
||||||
|
|
||||||
|
|||||||
@ -45,6 +45,8 @@ WorldServer::WorldServer()
|
|||||||
{
|
{
|
||||||
m_connection.reset(new EQ::Net::ServertalkClient(Config->WorldIP, Config->WorldTCPPort, false, "UCS", Config->SharedKey));
|
m_connection.reset(new EQ::Net::ServertalkClient(Config->WorldIP, Config->WorldTCPPort, false, "UCS", Config->SharedKey));
|
||||||
m_connection->OnMessage(std::bind(&WorldServer::ProcessMessage, this, std::placeholders::_1, std::placeholders::_2));
|
m_connection->OnMessage(std::bind(&WorldServer::ProcessMessage, this, std::placeholders::_1, std::placeholders::_2));
|
||||||
|
|
||||||
|
m_bsr_timer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldServer::~WorldServer()
|
WorldServer::~WorldServer()
|
||||||
@ -134,3 +136,37 @@ void WorldServer::ProcessClientVersionRequests(std::list<uint32>& id_list) {
|
|||||||
}
|
}
|
||||||
id_list.clear();
|
id_list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldServer::ProcessBroadcastServerReady() {
|
||||||
|
if (m_bsr_timer && (*m_bsr_timer) <= Timer::GetCurrentTime()) {
|
||||||
|
UCSBroadcastServerReady_Struct bsr;
|
||||||
|
memset(&bsr, 0, sizeof(UCSBroadcastServerReady_Struct));
|
||||||
|
|
||||||
|
sprintf(bsr.chat_prefix, "%s,%i,%s.",
|
||||||
|
Config->ChatHost.c_str(),
|
||||||
|
Config->ChatPort,
|
||||||
|
Config->ShortName.c_str()
|
||||||
|
);
|
||||||
|
sprintf(bsr.mail_prefix, "%s,%i,%s.",
|
||||||
|
Config->ChatHost.c_str(),
|
||||||
|
Config->MailPort,
|
||||||
|
Config->ShortName.c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
EQ::Net::DynamicPacket dp_bsr;
|
||||||
|
dp_bsr.PutData(0, &bsr, sizeof(UCSBroadcastServerReady_Struct));
|
||||||
|
m_connection->Send(ServerOP_UCSBroadcastServerReady, dp_bsr);
|
||||||
|
|
||||||
|
safe_delete(m_bsr_timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldServer::ActivateBroadcastServerReadyTimer() {
|
||||||
|
safe_delete(m_bsr_timer);
|
||||||
|
m_bsr_timer = new uint32;
|
||||||
|
|
||||||
|
// clients do not drop their connection to ucs immediately...
|
||||||
|
// it can take upwards of 60 seconds to process the drop
|
||||||
|
// and clients will not re-connect to ucs until that occurs
|
||||||
|
*m_bsr_timer = (Timer::GetCurrentTime() + (RuleI(Chat, UCSBroadcastServerReadyDelay) * 1000));
|
||||||
|
}
|
||||||
|
|||||||
@ -31,7 +31,12 @@ public:
|
|||||||
|
|
||||||
void ProcessClientVersionRequests(std::list<uint32>& id_list);
|
void ProcessClientVersionRequests(std::list<uint32>& id_list);
|
||||||
|
|
||||||
|
void ProcessBroadcastServerReady();
|
||||||
|
bool HasBroadcastServerReadyTimer() { return (m_bsr_timer != nullptr); }
|
||||||
|
void ActivateBroadcastServerReadyTimer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uint32* m_bsr_timer;
|
||||||
|
|
||||||
std::unique_ptr<EQ::Net::ServertalkClient> m_connection;
|
std::unique_ptr<EQ::Net::ServertalkClient> m_connection;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -52,6 +52,7 @@ void UCSConnection::ProcessPacket(uint16 opcode, EQ::Net::Packet &p)
|
|||||||
Log(Logs::Detail, Logs::UCS_Server, "Got authentication from UCS when they are already authenticated.");
|
Log(Logs::Detail, Logs::UCS_Server, "Got authentication from UCS when they are already authenticated.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ServerOP_UCSBroadcastServerReady:
|
||||||
case ServerOP_UCSClientVersionRequest:
|
case ServerOP_UCSClientVersionRequest:
|
||||||
{
|
{
|
||||||
zoneserver_list.SendPacket(pack);
|
zoneserver_list.SendPacket(pack);
|
||||||
|
|||||||
@ -516,23 +516,6 @@ void WorldDatabase::GetLauncherList(std::vector<std::string> &rl) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldDatabase::SetMailKey(int CharID, int IPAddress, int MailKey)
|
|
||||||
{
|
|
||||||
char MailKeyString[17];
|
|
||||||
|
|
||||||
if(RuleB(Chat, EnableMailKeyIPVerification) == true)
|
|
||||||
sprintf(MailKeyString, "%08X%08X", IPAddress, MailKey);
|
|
||||||
else
|
|
||||||
sprintf(MailKeyString, "%08X", MailKey);
|
|
||||||
|
|
||||||
std::string query = StringFormat("UPDATE character_data SET mailkey = '%s' WHERE id = '%i'",
|
|
||||||
MailKeyString, CharID);
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
if (!results.Success())
|
|
||||||
Log(Logs::General, Logs::Error, "WorldDatabase::SetMailKey(%i, %s) : %s", CharID, MailKeyString, results.ErrorMessage().c_str());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WorldDatabase::GetCharacterLevel(const char *name, int &level)
|
bool WorldDatabase::GetCharacterLevel(const char *name, int &level)
|
||||||
{
|
{
|
||||||
std::string query = StringFormat("SELECT level FROM character_data WHERE name = '%s'", name);
|
std::string query = StringFormat("SELECT level FROM character_data WHERE name = '%s'", name);
|
||||||
|
|||||||
@ -34,7 +34,6 @@ public:
|
|||||||
int MoveCharacterToBind(int CharID, uint8 bindnum = 0);
|
int MoveCharacterToBind(int CharID, uint8 bindnum = 0);
|
||||||
|
|
||||||
void GetLauncherList(std::vector<std::string> &result);
|
void GetLauncherList(std::vector<std::string> &result);
|
||||||
void SetMailKey(int CharID, int IPAddress, int MailKey);
|
|
||||||
bool GetCharacterLevel(const char *name, int &level);
|
bool GetCharacterLevel(const char *name, int &level);
|
||||||
|
|
||||||
bool LoadCharacterCreateAllocations();
|
bool LoadCharacterCreateAllocations();
|
||||||
|
|||||||
@ -1813,6 +1813,57 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ServerOP_UCSBroadcastServerReady:
|
||||||
|
{
|
||||||
|
UCSBroadcastServerReady_Struct* bsr = (UCSBroadcastServerReady_Struct*)pack->pBuffer;
|
||||||
|
EQApplicationPacket* outapp = nullptr;
|
||||||
|
std::string buffer;
|
||||||
|
|
||||||
|
for (auto liter : entity_list.GetClientList()) {
|
||||||
|
auto c = liter.second;
|
||||||
|
if (!c)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int MailKey = zone->random.Int(1, INT_MAX);
|
||||||
|
|
||||||
|
database.SetMailKey(c->CharacterID(), c->GetIP(), MailKey);
|
||||||
|
|
||||||
|
char ConnectionType;
|
||||||
|
|
||||||
|
// chat server packet
|
||||||
|
if (c->ClientVersionBit() & EQEmu::versions::bit_UFAndLater)
|
||||||
|
ConnectionType = 'U';
|
||||||
|
else if (c->ClientVersionBit() & EQEmu::versions::bit_SoFAndLater)
|
||||||
|
ConnectionType = 'S';
|
||||||
|
else
|
||||||
|
ConnectionType = 'C';
|
||||||
|
|
||||||
|
buffer = bsr->chat_prefix;
|
||||||
|
buffer.append(StringFormat("%s,%c%08X", c->GetName(), ConnectionType, MailKey));
|
||||||
|
|
||||||
|
outapp = new EQApplicationPacket(OP_SetChatServer, (buffer.length() + 1));
|
||||||
|
memcpy(outapp->pBuffer, buffer.c_str(), buffer.length());
|
||||||
|
outapp->pBuffer[buffer.length()] = '\0';
|
||||||
|
|
||||||
|
c->QueuePacket(outapp);
|
||||||
|
safe_delete(outapp);
|
||||||
|
|
||||||
|
// mail server packet
|
||||||
|
if (c->ClientVersionBit() & EQEmu::versions::bit_TitaniumAndEarlier)
|
||||||
|
ConnectionType = 'M';
|
||||||
|
|
||||||
|
buffer = bsr->mail_prefix;
|
||||||
|
buffer.append(StringFormat("%s,%c%08X", c->GetName(), ConnectionType, MailKey));
|
||||||
|
|
||||||
|
outapp = new EQApplicationPacket(OP_SetChatServer2, (buffer.length() + 1));
|
||||||
|
memcpy(outapp->pBuffer, buffer.c_str(), buffer.length());
|
||||||
|
outapp->pBuffer[buffer.length()] = '\0';
|
||||||
|
|
||||||
|
c->QueuePacket(outapp);
|
||||||
|
safe_delete(outapp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ServerOP_UCSClientVersionRequest:
|
case ServerOP_UCSClientVersionRequest:
|
||||||
{
|
{
|
||||||
UCSClientVersionRequest_Struct* cvreq = (UCSClientVersionRequest_Struct*)pack->pBuffer;
|
UCSClientVersionRequest_Struct* cvreq = (UCSClientVersionRequest_Struct*)pack->pBuffer;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user