mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 23:01:30 +00:00
Updated UCS versioning code - update your *.conf files
This commit is contained in:
parent
525db1819d
commit
e5e779c064
@ -1,5 +1,12 @@
|
|||||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
== 03/04/2018 ==
|
||||||
|
Uleat: Updated UCS versioning
|
||||||
|
- SoF and higher clients have a new opcode identified (update your *.conf files)
|
||||||
|
- Rework of previous ucs connectivity code
|
||||||
|
- Unrelated: Zone::weatherSend() now takes an optional parameter for singular updates (as in client entering zone)
|
||||||
|
-- prior to this, every client already in-zone received a weather update packet whenever a new client zoned in
|
||||||
|
|
||||||
== 02/18/2018 ==
|
== 02/18/2018 ==
|
||||||
Uleat: Bug reporting fix and overhaul.
|
Uleat: Bug reporting fix and overhaul.
|
||||||
- Fixed bug reporting for SoD+ clients
|
- Fixed bug reporting for SoD+ clients
|
||||||
|
|||||||
@ -393,6 +393,7 @@ N(OP_PVPLeaderBoardReply),
|
|||||||
N(OP_PVPLeaderBoardRequest),
|
N(OP_PVPLeaderBoardRequest),
|
||||||
N(OP_PVPStats),
|
N(OP_PVPStats),
|
||||||
N(OP_QueryResponseThing),
|
N(OP_QueryResponseThing),
|
||||||
|
N(OP_QueryUCSServerStatus),
|
||||||
N(OP_RaidInvite),
|
N(OP_RaidInvite),
|
||||||
N(OP_RaidJoin),
|
N(OP_RaidJoin),
|
||||||
N(OP_RaidUpdate),
|
N(OP_RaidUpdate),
|
||||||
|
|||||||
@ -121,6 +121,20 @@ namespace EQEmu
|
|||||||
ClientVersion ConvertOfflinePCMobVersionToClientVersion(MobVersion mob_version);
|
ClientVersion ConvertOfflinePCMobVersionToClientVersion(MobVersion mob_version);
|
||||||
MobVersion ConvertClientVersionToOfflinePCMobVersion(ClientVersion client_version);
|
MobVersion ConvertClientVersionToOfflinePCMobVersion(ClientVersion client_version);
|
||||||
|
|
||||||
|
|
||||||
|
enum UCSVersion : char {
|
||||||
|
ucsUnknown = '\0',
|
||||||
|
ucsClient62Chat = 'A',
|
||||||
|
ucsClient62Mail = 'a',
|
||||||
|
ucsTitaniumChat = 'B',
|
||||||
|
ucsTitaniumMail = 'b',
|
||||||
|
ucsSoFCombined = 'C',
|
||||||
|
ucsSoDCombined = 'D',
|
||||||
|
ucsUFCombined = 'E',
|
||||||
|
ucsRoFCombined = 'F',
|
||||||
|
ucsRoF2Combined = 'G'
|
||||||
|
};
|
||||||
|
|
||||||
} /*versions*/
|
} /*versions*/
|
||||||
|
|
||||||
} /*EQEmu*/
|
} /*EQEmu*/
|
||||||
|
|||||||
@ -614,9 +614,6 @@ RULE_INT(Chat, IntervalDurationMS, 60000)
|
|||||||
RULE_INT(Chat, KarmaUpdateIntervalMS, 1200000)
|
RULE_INT(Chat, KarmaUpdateIntervalMS, 1200000)
|
||||||
RULE_INT(Chat, KarmaGlobalChatLimit, 72) //amount of karma you need to be able to talk in ooc/auction/chat below the level limit
|
RULE_INT(Chat, KarmaGlobalChatLimit, 72) //amount of karma you need to be able to talk in ooc/auction/chat below the level limit
|
||||||
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, 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)
|
||||||
|
|||||||
@ -190,9 +190,8 @@
|
|||||||
#define ServerOP_ReloadLogs 0x4010
|
#define ServerOP_ReloadLogs 0x4010
|
||||||
#define ServerOP_ReloadPerlExportSettings 0x4011
|
#define ServerOP_ReloadPerlExportSettings 0x4011
|
||||||
#define ServerOP_CZSetEntityVariableByClientName 0x4012
|
#define ServerOP_CZSetEntityVariableByClientName 0x4012
|
||||||
#define ServerOP_UCSClientVersionRequest 0x4013
|
#define ServerOP_UCSServerStatusRequest 0x4013
|
||||||
#define ServerOP_UCSClientVersionReply 0x4014
|
#define ServerOP_UCSServerStatusReply 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
|
||||||
@ -1281,18 +1280,15 @@ struct ServerRequestTellQueue_Struct {
|
|||||||
char name[64];
|
char name[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UCSClientVersionRequest_Struct {
|
struct UCSServerStatus_Struct {
|
||||||
uint32 character_id;
|
uint8 available; // non-zero=true, 0=false
|
||||||
};
|
union {
|
||||||
|
struct {
|
||||||
struct UCSClientVersionReply_Struct {
|
uint16 port;
|
||||||
uint32 character_id;
|
uint16 unused;
|
||||||
EQEmu::versions::ClientVersion client_version;
|
};
|
||||||
};
|
uint32 timestamp;
|
||||||
|
};
|
||||||
struct UCSBroadcastServerReady_Struct {
|
|
||||||
char chat_prefix[128];
|
|
||||||
char mail_prefix[128];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|||||||
@ -127,6 +127,24 @@ void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string SharedDatabase::GetMailKey(int CharID, bool key_only)
|
||||||
|
{
|
||||||
|
std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `id`='%i' LIMIT 1", CharID);
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
Log(Logs::Detail, Logs::MySQLError, "Error retrieving mailkey from database: %s", results.ErrorMessage().c_str());
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
std::string mail_key = row[0];
|
||||||
|
|
||||||
|
if (mail_key.length() > 8 && key_only)
|
||||||
|
return mail_key.substr(8);
|
||||||
|
else
|
||||||
|
return mail_key;
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@ -73,6 +73,7 @@ class SharedDatabase : public Database
|
|||||||
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);
|
void SetMailKey(int CharID, int IPAddress, int MailKey);
|
||||||
|
std::string GetMailKey(int CharID, bool key_only = false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Character InventoryProfile
|
Character InventoryProfile
|
||||||
|
|||||||
@ -512,7 +512,6 @@ Client::Client(std::shared_ptr<EQStreamInterface> eqs) {
|
|||||||
AccountGrabUpdateTimer = new Timer(60000); //check every minute
|
AccountGrabUpdateTimer = new Timer(60000); //check every minute
|
||||||
GlobalChatLimiterTimer = new Timer(RuleI(Chat, IntervalDurationMS));
|
GlobalChatLimiterTimer = new Timer(RuleI(Chat, IntervalDurationMS));
|
||||||
|
|
||||||
RawConnectionType = '\0';
|
|
||||||
TypeOfConnection = ConnectionTypeUnknown;
|
TypeOfConnection = ConnectionTypeUnknown;
|
||||||
ClientVersion_ = EQEmu::versions::ClientVersion::Unknown;
|
ClientVersion_ = EQEmu::versions::ClientVersion::Unknown;
|
||||||
|
|
||||||
@ -645,10 +644,6 @@ void Clientlist::Process()
|
|||||||
|
|
||||||
database.GetAccountStatus((*it));
|
database.GetAccountStatus((*it));
|
||||||
|
|
||||||
// give world packet a chance to arrive and be processed
|
|
||||||
if ((*it)->GetCharID())
|
|
||||||
ClientVersionRequestQueue[(*it)->GetCharID()] = (Timer::GetCurrentTime() + (RuleI(Chat, ExpireClientVersionRequests) * 1000));
|
|
||||||
|
|
||||||
if ((*it)->GetConnectionType() == ConnectionTypeCombined)
|
if ((*it)->GetConnectionType() == ConnectionTypeCombined)
|
||||||
(*it)->SendFriends();
|
(*it)->SendFriends();
|
||||||
|
|
||||||
@ -688,34 +683,8 @@ void Clientlist::Process()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// initiate request if we don't already have a reply from 'world enter' (ucs crash recovery protocol)
|
|
||||||
if ((*it)->GetClientVersion() == EQEmu::versions::ClientVersion::Unknown) {
|
|
||||||
if (!CheckForClientVersionReply((*it)))
|
|
||||||
RequestClientVersion((*it)->GetCharID());
|
|
||||||
}
|
|
||||||
|
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete expired replies
|
|
||||||
auto repiter = ClientVersionReplyQueue.begin();
|
|
||||||
while (repiter != ClientVersionReplyQueue.end()) {
|
|
||||||
if ((*repiter).second.second <= Timer::GetCurrentTime()) {
|
|
||||||
repiter = ClientVersionReplyQueue.erase(repiter);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
++repiter;
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete expired requests
|
|
||||||
auto reqiter = ClientVersionRequestQueue.begin();
|
|
||||||
while (reqiter != ClientVersionRequestQueue.end()) {
|
|
||||||
if ((*reqiter).second <= Timer::GetCurrentTime()) {
|
|
||||||
reqiter = ClientVersionRequestQueue.erase(reqiter);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
++reqiter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clientlist::ProcessOPMailCommand(Client *c, std::string CommandString)
|
void Clientlist::ProcessOPMailCommand(Client *c, std::string CommandString)
|
||||||
@ -873,55 +842,6 @@ void Clientlist::ProcessOPMailCommand(Client *c, std::string CommandString)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clientlist::RequestClientVersion(uint32 character_id) {
|
|
||||||
if (!character_id)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (ClientVersionRequestQueue.find(character_id) != ClientVersionRequestQueue.end()) {
|
|
||||||
if (ClientVersionRequestQueue[character_id] > Timer::GetCurrentTime())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LogSys.log_settings[Logs::UCS_Server].is_category_enabled) {
|
|
||||||
Log(Logs::Detail, Logs::UCS_Server, "Requesting ClientVersion reply for character id: %u",
|
|
||||||
character_id);
|
|
||||||
}
|
|
||||||
ClientVersionRequestIDs.push_back(character_id);
|
|
||||||
ClientVersionRequestQueue[character_id] = (Timer::GetCurrentTime() + (RuleI(Chat, ExpireClientVersionRequests) * 1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Clientlist::QueueClientVersionReply(uint32 character_id, EQEmu::versions::ClientVersion client_version) {
|
|
||||||
if (!character_id)
|
|
||||||
return true;
|
|
||||||
if (client_version < EQEmu::versions::ClientVersion::Titanium || client_version > EQEmu::versions::ClientVersion::RoF2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (LogSys.log_settings[Logs::UCS_Server].is_category_enabled) {
|
|
||||||
Log(Logs::Detail, Logs::UCS_Server, "Queueing ClientVersion %u reply for character id: %u",
|
|
||||||
static_cast<uint32>(client_version), character_id);
|
|
||||||
}
|
|
||||||
ClientVersionReplyQueue[character_id] = cvt_pair(client_version, (Timer::GetCurrentTime() + (RuleI(Chat, ExpireClientVersionReplies) * 1000)));
|
|
||||||
ClientVersionRequestQueue.erase(character_id);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Clientlist::CheckForClientVersionReply(Client* c) {
|
|
||||||
if (!c)
|
|
||||||
return true;
|
|
||||||
if (ClientVersionReplyQueue.find(c->GetCharID()) == ClientVersionReplyQueue.end())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (LogSys.log_settings[Logs::UCS_Server].is_category_enabled) {
|
|
||||||
Log(Logs::General, Logs::UCS_Server, "Registering ClientVersion %s for stream %s:%u",
|
|
||||||
EQEmu::versions::ClientVersionName(ClientVersionReplyQueue[c->GetCharID()].first), c->ClientStream->GetRemoteAddr().c_str(), c->ClientStream->GetRemotePort());
|
|
||||||
}
|
|
||||||
c->SetClientVersion(ClientVersionReplyQueue[c->GetCharID()].first);
|
|
||||||
ClientVersionReplyQueue.erase(c->GetCharID());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clientlist::CloseAllConnections() {
|
void Clientlist::CloseAllConnections() {
|
||||||
|
|
||||||
|
|
||||||
@ -2214,39 +2134,64 @@ void Client::AccountUpdate()
|
|||||||
|
|
||||||
void Client::SetConnectionType(char c) {
|
void Client::SetConnectionType(char c) {
|
||||||
|
|
||||||
RawConnectionType = c;
|
|
||||||
|
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case 'S':
|
case EQEmu::versions::ucsTitaniumChat:
|
||||||
{
|
|
||||||
TypeOfConnection = ConnectionTypeCombined;
|
|
||||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Combined (SoF/SoD)");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'U':
|
|
||||||
{
|
|
||||||
TypeOfConnection = ConnectionTypeCombined;
|
|
||||||
UnderfootOrLater = true;
|
|
||||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Combined (Underfoot+)");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'M':
|
|
||||||
{
|
|
||||||
TypeOfConnection = ConnectionTypeMail;
|
|
||||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Mail (6.2 or Titanium client)");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'C':
|
|
||||||
{
|
{
|
||||||
TypeOfConnection = ConnectionTypeChat;
|
TypeOfConnection = ConnectionTypeChat;
|
||||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Chat (6.2 or Titanium client)");
|
ClientVersion_ = EQEmu::versions::ClientVersion::Titanium;
|
||||||
|
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Chat (Titanium)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EQEmu::versions::ucsTitaniumMail:
|
||||||
|
{
|
||||||
|
TypeOfConnection = ConnectionTypeMail;
|
||||||
|
ClientVersion_ = EQEmu::versions::ClientVersion::Titanium;
|
||||||
|
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Mail (Titanium)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EQEmu::versions::ucsSoFCombined:
|
||||||
|
{
|
||||||
|
TypeOfConnection = ConnectionTypeCombined;
|
||||||
|
ClientVersion_ = EQEmu::versions::ClientVersion::SoF;
|
||||||
|
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Combined (SoF)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EQEmu::versions::ucsSoDCombined:
|
||||||
|
{
|
||||||
|
TypeOfConnection = ConnectionTypeCombined;
|
||||||
|
ClientVersion_ = EQEmu::versions::ClientVersion::SoD;
|
||||||
|
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Combined (SoD)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EQEmu::versions::ucsUFCombined:
|
||||||
|
{
|
||||||
|
TypeOfConnection = ConnectionTypeCombined;
|
||||||
|
ClientVersion_ = EQEmu::versions::ClientVersion::UF;
|
||||||
|
UnderfootOrLater = true;
|
||||||
|
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Combined (Underfoot)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EQEmu::versions::ucsRoFCombined:
|
||||||
|
{
|
||||||
|
TypeOfConnection = ConnectionTypeCombined;
|
||||||
|
ClientVersion_ = EQEmu::versions::ClientVersion::RoF;
|
||||||
|
UnderfootOrLater = true;
|
||||||
|
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Combined (RoF)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EQEmu::versions::ucsRoF2Combined:
|
||||||
|
{
|
||||||
|
TypeOfConnection = ConnectionTypeCombined;
|
||||||
|
ClientVersion_ = EQEmu::versions::ClientVersion::RoF2;
|
||||||
|
UnderfootOrLater = true;
|
||||||
|
Log(Logs::Detail, Logs::UCS_Server, "Connection type is Combined (RoF2)");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
RawConnectionType = '\0';
|
|
||||||
TypeOfConnection = ConnectionTypeUnknown;
|
TypeOfConnection = ConnectionTypeUnknown;
|
||||||
|
ClientVersion_ = EQEmu::versions::ClientVersion::Unknown;
|
||||||
Log(Logs::Detail, Logs::UCS_Server, "Connection type is unknown.");
|
Log(Logs::Detail, Logs::UCS_Server, "Connection type is unknown.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -140,10 +140,8 @@ public:
|
|||||||
int GetMailBoxNumber() { return CurrentMailBox; }
|
int GetMailBoxNumber() { return CurrentMailBox; }
|
||||||
int GetMailBoxNumber(std::string CharacterName);
|
int GetMailBoxNumber(std::string CharacterName);
|
||||||
|
|
||||||
char GetRawConnectionType() { return RawConnectionType; }
|
|
||||||
void SetConnectionType(char c);
|
void SetConnectionType(char c);
|
||||||
ConnectionType GetConnectionType() { return TypeOfConnection; }
|
ConnectionType GetConnectionType() { return TypeOfConnection; }
|
||||||
void SetClientVersion(EQEmu::versions::ClientVersion client_version) { ClientVersion_ = client_version; }
|
|
||||||
EQEmu::versions::ClientVersion GetClientVersion() { return ClientVersion_; }
|
EQEmu::versions::ClientVersion GetClientVersion() { return ClientVersion_; }
|
||||||
|
|
||||||
inline bool IsMailConnection() { return (TypeOfConnection == ConnectionTypeMail) || (TypeOfConnection == ConnectionTypeCombined); }
|
inline bool IsMailConnection() { return (TypeOfConnection == ConnectionTypeMail) || (TypeOfConnection == ConnectionTypeCombined); }
|
||||||
@ -173,7 +171,6 @@ private:
|
|||||||
int AttemptedMessages;
|
int AttemptedMessages;
|
||||||
bool ForceDisconnect;
|
bool ForceDisconnect;
|
||||||
|
|
||||||
char RawConnectionType;
|
|
||||||
ConnectionType TypeOfConnection;
|
ConnectionType TypeOfConnection;
|
||||||
EQEmu::versions::ClientVersion ClientVersion_;
|
EQEmu::versions::ClientVersion ClientVersion_;
|
||||||
bool UnderfootOrLater;
|
bool UnderfootOrLater;
|
||||||
@ -190,22 +187,11 @@ public:
|
|||||||
Client *IsCharacterOnline(std::string CharacterName);
|
Client *IsCharacterOnline(std::string CharacterName);
|
||||||
void ProcessOPMailCommand(Client *c, std::string CommandString);
|
void ProcessOPMailCommand(Client *c, std::string CommandString);
|
||||||
|
|
||||||
std::list<uint32> ClientVersionRequestIDs;
|
|
||||||
|
|
||||||
void RequestClientVersion(uint32 character_id);
|
|
||||||
bool QueueClientVersionReply(uint32 character_id, EQEmu::versions::ClientVersion client_version);
|
|
||||||
bool CheckForClientVersionReply(Client* c);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::pair<EQEmu::versions::ClientVersion, uint32> cvt_pair;
|
|
||||||
|
|
||||||
EQ::Net::EQStreamManager *chatsf;
|
EQ::Net::EQStreamManager *chatsf;
|
||||||
|
|
||||||
std::list<Client*> ClientChatConnections;
|
std::list<Client*> ClientChatConnections;
|
||||||
|
|
||||||
std::map<uint32, uint32> ClientVersionRequestQueue;
|
|
||||||
std::map<uint32, cvt_pair> ClientVersionReplyQueue;
|
|
||||||
|
|
||||||
OpcodeManager *ChatOpMgr;
|
OpcodeManager *ChatOpMgr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -140,19 +140,12 @@ int main() {
|
|||||||
|
|
||||||
worldserver = new WorldServer;
|
worldserver = new WorldServer;
|
||||||
|
|
||||||
worldserver->ActivateBroadcastServerReadyTimer();
|
|
||||||
|
|
||||||
while(RunLoops) {
|
while(RunLoops) {
|
||||||
// this triggers clients to 'reconnect' to ucs after server crash
|
|
||||||
if (worldserver->HasBroadcastServerReadyTimer())
|
|
||||||
worldserver->ProcessBroadcastServerReady();
|
|
||||||
|
|
||||||
Timer::SetCurrentTime();
|
Timer::SetCurrentTime();
|
||||||
|
|
||||||
g_Clientlist->Process();
|
g_Clientlist->Process();
|
||||||
|
|
||||||
worldserver->ProcessClientVersionRequests(g_Clientlist->ClientVersionRequestIDs);
|
|
||||||
|
|
||||||
if(ChannelListProcessTimer.Check())
|
if(ChannelListProcessTimer.Check())
|
||||||
ChannelList->Process();
|
ChannelList->Process();
|
||||||
|
|
||||||
|
|||||||
@ -50,8 +50,6 @@ 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()
|
||||||
@ -140,59 +138,7 @@ void WorldServer::ProcessMessage(uint16 opcode, EQ::Net::Packet &p)
|
|||||||
std::string());
|
std::string());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ServerOP_UCSClientVersionReply:
|
|
||||||
{
|
|
||||||
UCSClientVersionReply_Struct* cvr = (UCSClientVersionReply_Struct*)pack->pBuffer;
|
|
||||||
g_Clientlist->QueueClientVersionReply(cvr->character_id, cvr->client_version);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldServer::ProcessClientVersionRequests(std::list<uint32>& id_list) {
|
|
||||||
UCSClientVersionRequest_Struct cvr;
|
|
||||||
EQ::Net::DynamicPacket dp_cvr;
|
|
||||||
for (auto iter : id_list) {
|
|
||||||
cvr.character_id = iter;
|
|
||||||
dp_cvr.PutData(0, &cvr, sizeof(cvr));
|
|
||||||
m_connection->Send(ServerOP_UCSClientVersionRequest, dp_cvr);
|
|
||||||
}
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client45ToServerSayLink(std::string& serverSayLink, const std::string& clientSayLink) {
|
void Client45ToServerSayLink(std::string& serverSayLink, const std::string& clientSayLink) {
|
||||||
|
|||||||
@ -29,14 +29,7 @@ public:
|
|||||||
~WorldServer();
|
~WorldServer();
|
||||||
void ProcessMessage(uint16 opcode, EQ::Net::Packet &);
|
void ProcessMessage(uint16 opcode, EQ::Net::Packet &);
|
||||||
|
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -165,6 +165,7 @@ OP_GMNameChange=0x3077 # Was 0x4434
|
|||||||
OP_GMLastName=0x4dd7 # Was 0x3077
|
OP_GMLastName=0x4dd7 # Was 0x3077
|
||||||
|
|
||||||
# Misc Opcodes
|
# Misc Opcodes
|
||||||
|
OP_QueryUCSServerStatus=0x6964
|
||||||
OP_InspectRequest=0x23f1
|
OP_InspectRequest=0x23f1
|
||||||
OP_InspectAnswer=0x5794
|
OP_InspectAnswer=0x5794
|
||||||
OP_InspectMessageUpdate=0x3064
|
OP_InspectMessageUpdate=0x3064
|
||||||
|
|||||||
@ -164,6 +164,7 @@ OP_GMNameChange=0x035f
|
|||||||
OP_GMLastName=0x46ce
|
OP_GMLastName=0x46ce
|
||||||
|
|
||||||
# Misc Opcodes
|
# Misc Opcodes
|
||||||
|
OP_QueryUCSServerStatus=0x398f
|
||||||
OP_InspectRequest=0x57bc
|
OP_InspectRequest=0x57bc
|
||||||
OP_InspectAnswer=0x71ac
|
OP_InspectAnswer=0x71ac
|
||||||
OP_InspectMessageUpdate=0x4d25
|
OP_InspectMessageUpdate=0x4d25
|
||||||
|
|||||||
@ -165,6 +165,7 @@ OP_GMKill=0x6685 # C
|
|||||||
OP_GMNameChange=0x565d # C
|
OP_GMNameChange=0x565d # C
|
||||||
OP_GMLastName=0x3563 # C
|
OP_GMLastName=0x3563 # C
|
||||||
|
|
||||||
|
OP_QueryUCSServerStatus=0x4036
|
||||||
OP_InspectAnswer=0x4938 # C
|
OP_InspectAnswer=0x4938 # C
|
||||||
OP_Action2=0x7e4d # C OP_Damage?
|
OP_Action2=0x7e4d # C OP_Damage?
|
||||||
OP_BeginCast=0x0d5a # C
|
OP_BeginCast=0x0d5a # C
|
||||||
|
|||||||
@ -168,6 +168,7 @@ OP_GMKill=0x799c # C
|
|||||||
OP_GMNameChange=0x0f48 # C
|
OP_GMNameChange=0x0f48 # C
|
||||||
OP_GMLastName=0x7bfb # C
|
OP_GMLastName=0x7bfb # C
|
||||||
|
|
||||||
|
OP_QueryUCSServerStatus=0x4481
|
||||||
OP_InspectAnswer=0x0c2b # C
|
OP_InspectAnswer=0x0c2b # C
|
||||||
OP_BeginCast=0x0d5a # C
|
OP_BeginCast=0x0d5a # C
|
||||||
OP_ColoredText=0x71bf # C
|
OP_ColoredText=0x71bf # C
|
||||||
|
|||||||
110
world/client.cpp
110
world/client.cpp
@ -84,6 +84,7 @@ extern ClientList client_list;
|
|||||||
extern EQEmu::Random emu_random;
|
extern EQEmu::Random emu_random;
|
||||||
extern uint32 numclients;
|
extern uint32 numclients;
|
||||||
extern volatile bool RunLoops;
|
extern volatile bool RunLoops;
|
||||||
|
extern volatile bool UCSServerAvailable_;
|
||||||
|
|
||||||
Client::Client(EQStreamInterface* ieqs)
|
Client::Client(EQStreamInterface* ieqs)
|
||||||
: autobootup_timeout(RuleI(World, ZoneAutobootTimeoutMS)),
|
: autobootup_timeout(RuleI(World, ZoneAutobootTimeoutMS)),
|
||||||
@ -891,52 +892,83 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
|||||||
QueuePacket(outapp);
|
QueuePacket(outapp);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
|
|
||||||
|
// set mailkey - used for duration of character session
|
||||||
int MailKey = emu_random.Int(1, INT_MAX);
|
int MailKey = emu_random.Int(1, INT_MAX);
|
||||||
|
|
||||||
database.SetMailKey(charid, GetIP(), MailKey);
|
database.SetMailKey(charid, GetIP(), MailKey);
|
||||||
|
if (UCSServerAvailable_) {
|
||||||
|
const WorldConfig *Config = WorldConfig::get();
|
||||||
|
std::string buffer;
|
||||||
|
|
||||||
char ConnectionType;
|
EQEmu::versions::UCSVersion ConnectionType = EQEmu::versions::ucsUnknown;
|
||||||
|
|
||||||
if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater)
|
// chat server packet
|
||||||
ConnectionType = 'U';
|
switch (GetClientVersion()) {
|
||||||
else if (m_ClientVersionBit & EQEmu::versions::bit_SoFAndLater)
|
case EQEmu::versions::ClientVersion::Titanium:
|
||||||
ConnectionType = 'S';
|
ConnectionType = EQEmu::versions::ucsTitaniumChat;
|
||||||
else
|
break;
|
||||||
ConnectionType = 'C';
|
case EQEmu::versions::ClientVersion::SoF:
|
||||||
|
ConnectionType = EQEmu::versions::ucsSoFCombined;
|
||||||
|
break;
|
||||||
|
case EQEmu::versions::ClientVersion::SoD:
|
||||||
|
ConnectionType = EQEmu::versions::ucsSoDCombined;
|
||||||
|
break;
|
||||||
|
case EQEmu::versions::ClientVersion::UF:
|
||||||
|
ConnectionType = EQEmu::versions::ucsUFCombined;
|
||||||
|
break;
|
||||||
|
case EQEmu::versions::ClientVersion::RoF:
|
||||||
|
ConnectionType = EQEmu::versions::ucsRoFCombined;
|
||||||
|
break;
|
||||||
|
case EQEmu::versions::ClientVersion::RoF2:
|
||||||
|
ConnectionType = EQEmu::versions::ucsRoF2Combined;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ConnectionType = EQEmu::versions::ucsUnknown;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
auto outapp2 = new EQApplicationPacket(OP_SetChatServer);
|
buffer = StringFormat("%s,%i,%s.%s,%c%08X",
|
||||||
char buffer[112];
|
Config->ChatHost.c_str(),
|
||||||
|
Config->ChatPort,
|
||||||
|
Config->ShortName.c_str(),
|
||||||
|
GetCharName(),
|
||||||
|
ConnectionType,
|
||||||
|
MailKey
|
||||||
|
);
|
||||||
|
|
||||||
const WorldConfig *Config = WorldConfig::get();
|
outapp = new EQApplicationPacket(OP_SetChatServer, (buffer.length() + 1));
|
||||||
|
memcpy(outapp->pBuffer, buffer.c_str(), buffer.length());
|
||||||
|
outapp->pBuffer[buffer.length()] = '\0';
|
||||||
|
|
||||||
sprintf(buffer,"%s,%i,%s.%s,%c%08X",
|
QueuePacket(outapp);
|
||||||
Config->ChatHost.c_str(),
|
safe_delete(outapp);
|
||||||
Config->ChatPort,
|
|
||||||
Config->ShortName.c_str(),
|
|
||||||
this->GetCharName(), ConnectionType, MailKey
|
|
||||||
);
|
|
||||||
outapp2->size=strlen(buffer)+1;
|
|
||||||
outapp2->pBuffer = new uchar[outapp2->size];
|
|
||||||
memcpy(outapp2->pBuffer,buffer,outapp2->size);
|
|
||||||
QueuePacket(outapp2);
|
|
||||||
safe_delete(outapp2);
|
|
||||||
|
|
||||||
outapp2 = new EQApplicationPacket(OP_SetChatServer2);
|
// mail server packet
|
||||||
|
switch (GetClientVersion()) {
|
||||||
|
case EQEmu::versions::ClientVersion::Titanium:
|
||||||
|
ConnectionType = EQEmu::versions::ucsTitaniumMail;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// retain value from previous switch
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_ClientVersionBit & EQEmu::versions::bit_TitaniumAndEarlier)
|
buffer = StringFormat("%s,%i,%s.%s,%c%08X",
|
||||||
ConnectionType = 'M';
|
Config->MailHost.c_str(),
|
||||||
|
Config->MailPort,
|
||||||
|
Config->ShortName.c_str(),
|
||||||
|
GetCharName(),
|
||||||
|
ConnectionType,
|
||||||
|
MailKey
|
||||||
|
);
|
||||||
|
|
||||||
sprintf(buffer,"%s,%i,%s.%s,%c%08X",
|
outapp = new EQApplicationPacket(OP_SetChatServer2, (buffer.length() + 1));
|
||||||
Config->MailHost.c_str(),
|
memcpy(outapp->pBuffer, buffer.c_str(), buffer.length());
|
||||||
Config->MailPort,
|
outapp->pBuffer[buffer.length()] = '\0';
|
||||||
Config->ShortName.c_str(),
|
|
||||||
this->GetCharName(), ConnectionType, MailKey
|
QueuePacket(outapp);
|
||||||
);
|
safe_delete(outapp);
|
||||||
outapp2->size=strlen(buffer)+1;
|
}
|
||||||
outapp2->pBuffer = new uchar[outapp2->size];
|
|
||||||
memcpy(outapp2->pBuffer,buffer,outapp2->size);
|
|
||||||
QueuePacket(outapp2);
|
|
||||||
safe_delete(outapp2);
|
|
||||||
|
|
||||||
EnterWorld();
|
EnterWorld();
|
||||||
|
|
||||||
@ -1215,14 +1247,6 @@ void Client::EnterWorld(bool TryBootup) {
|
|||||||
wtz->response = 0;
|
wtz->response = 0;
|
||||||
zone_server->SendPacket(pack);
|
zone_server->SendPacket(pack);
|
||||||
delete pack;
|
delete pack;
|
||||||
|
|
||||||
UCSClientVersionReply_Struct cvr;
|
|
||||||
cvr.character_id = GetCharID();
|
|
||||||
cvr.client_version = GetClientVersion();
|
|
||||||
EQ::Net::DynamicPacket dp_cvr;
|
|
||||||
dp_cvr.PutData(0, &cvr, sizeof(cvr));
|
|
||||||
zone_server->HandleMessage(ServerOP_UCSClientVersionReply, dp_cvr);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else { // if they havent seen character select screen, we can assume this is a zone
|
else { // if they havent seen character select screen, we can assume this is a zone
|
||||||
// to zone movement, which should be preauthorized before they leave the previous zone
|
// to zone movement, which should be preauthorized before they leave the previous zone
|
||||||
|
|||||||
@ -462,6 +462,8 @@ int main(int argc, char** argv) {
|
|||||||
connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID());
|
connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID());
|
||||||
|
|
||||||
UCSLink.SetConnection(connection);
|
UCSLink.SetConnection(connection);
|
||||||
|
|
||||||
|
zoneserver_list.UpdateUCSServerAvailable();
|
||||||
});
|
});
|
||||||
|
|
||||||
server_connection->OnConnectionRemoved("UCS", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
server_connection->OnConnectionRemoved("UCS", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||||
@ -469,6 +471,8 @@ int main(int argc, char** argv) {
|
|||||||
connection->GetUUID());
|
connection->GetUUID());
|
||||||
|
|
||||||
UCSLink.SetConnection(nullptr);
|
UCSLink.SetConnection(nullptr);
|
||||||
|
|
||||||
|
zoneserver_list.UpdateUCSServerAvailable(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
server_connection->OnConnectionIdentified("WebInterface", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
server_connection->OnConnectionIdentified("WebInterface", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||||
|
|||||||
@ -2,14 +2,11 @@
|
|||||||
#include "../common/eqemu_logsys.h"
|
#include "../common/eqemu_logsys.h"
|
||||||
#include "ucs.h"
|
#include "ucs.h"
|
||||||
#include "world_config.h"
|
#include "world_config.h"
|
||||||
#include "zonelist.h"
|
|
||||||
|
|
||||||
#include "../common/misc_functions.h"
|
#include "../common/misc_functions.h"
|
||||||
#include "../common/md5.h"
|
#include "../common/md5.h"
|
||||||
#include "../common/packet_dump.h"
|
#include "../common/packet_dump.h"
|
||||||
|
|
||||||
extern ZSList zoneserver_list;
|
|
||||||
|
|
||||||
UCSConnection::UCSConnection()
|
UCSConnection::UCSConnection()
|
||||||
{
|
{
|
||||||
Stream = 0;
|
Stream = 0;
|
||||||
@ -52,12 +49,6 @@ 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:
|
|
||||||
{
|
|
||||||
zoneserver_list.SendPacket(pack);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::UCS_Server, "Unknown ServerOPcode from UCS 0x%04x, size %d", opcode, pack->size);
|
Log(Logs::Detail, Logs::UCS_Server, "Unknown ServerOPcode from UCS 0x%04x, size %d", opcode, pack->size);
|
||||||
|
|||||||
@ -32,6 +32,7 @@ extern uint32 numzones;
|
|||||||
extern bool holdzones;
|
extern bool holdzones;
|
||||||
extern EQEmu::Random emu_random;
|
extern EQEmu::Random emu_random;
|
||||||
extern WebInterfaceList web_interface;
|
extern WebInterfaceList web_interface;
|
||||||
|
volatile bool UCSServerAvailable_ = false;
|
||||||
void CatchSignal(int sig_num);
|
void CatchSignal(int sig_num);
|
||||||
|
|
||||||
ZSList::ZSList()
|
ZSList::ZSList()
|
||||||
@ -669,6 +670,16 @@ void ZSList::GetZoneIDList(std::vector<uint32> &zones) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZSList::UpdateUCSServerAvailable(bool ucss_available) {
|
||||||
|
UCSServerAvailable_ = ucss_available;
|
||||||
|
auto outapp = new ServerPacket(ServerOP_UCSServerStatusReply, sizeof(UCSServerStatus_Struct));
|
||||||
|
auto ucsss = (UCSServerStatus_Struct*)outapp->pBuffer;
|
||||||
|
ucsss->available = (ucss_available ? 1 : 0);
|
||||||
|
ucsss->timestamp = Timer::GetCurrentTime();
|
||||||
|
SendPacket(outapp);
|
||||||
|
safe_delete(outapp);
|
||||||
|
}
|
||||||
|
|
||||||
void ZSList::WorldShutDown(uint32 time, uint32 interval)
|
void ZSList::WorldShutDown(uint32 time, uint32 interval)
|
||||||
{
|
{
|
||||||
if (time > 0) {
|
if (time > 0) {
|
||||||
|
|||||||
@ -54,7 +54,8 @@ public:
|
|||||||
Timer* reminder;
|
Timer* reminder;
|
||||||
void NextGroupIDs(uint32 &start, uint32 &end);
|
void NextGroupIDs(uint32 &start, uint32 &end);
|
||||||
void SendLSZones();
|
void SendLSZones();
|
||||||
uint16 GetAvailableZonePort();
|
uint16 GetAvailableZonePort();
|
||||||
|
void UpdateUCSServerAvailable(bool ucss_available = true);
|
||||||
|
|
||||||
int GetZoneCount();
|
int GetZoneCount();
|
||||||
void GetZoneIDList(std::vector<uint32> &zones);
|
void GetZoneIDList(std::vector<uint32> &zones);
|
||||||
|
|||||||
@ -41,6 +41,7 @@ extern GroupLFPList LFPGroupList;
|
|||||||
extern ZSList zoneserver_list;
|
extern ZSList zoneserver_list;
|
||||||
extern LoginServerList loginserverlist;
|
extern LoginServerList loginserverlist;
|
||||||
extern volatile bool RunLoops;
|
extern volatile bool RunLoops;
|
||||||
|
extern volatile bool UCSServerAvailable_;
|
||||||
extern AdventureManager adventure_manager;
|
extern AdventureManager adventure_manager;
|
||||||
extern UCSConnection UCSLink;
|
extern UCSConnection UCSLink;
|
||||||
extern QueryServConnection QSLink;
|
extern QueryServConnection QSLink;
|
||||||
@ -1262,12 +1263,29 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ServerOP_UCSClientVersionReply:
|
|
||||||
case ServerOP_UCSMailMessage:
|
case ServerOP_UCSMailMessage:
|
||||||
{
|
{
|
||||||
UCSLink.SendPacket(pack);
|
UCSLink.SendPacket(pack);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ServerOP_UCSServerStatusRequest:
|
||||||
|
{
|
||||||
|
auto ucsss = (UCSServerStatus_Struct*)pack->pBuffer;
|
||||||
|
auto zs = zoneserver_list.FindByPort(ucsss->port);
|
||||||
|
if (!zs)
|
||||||
|
break;
|
||||||
|
|
||||||
|
auto outapp = new ServerPacket(ServerOP_UCSServerStatusReply, sizeof(UCSServerStatus_Struct));
|
||||||
|
ucsss = (UCSServerStatus_Struct*)outapp->pBuffer;
|
||||||
|
ucsss->available = (UCSServerAvailable_ ? 1 : 0);
|
||||||
|
ucsss->timestamp = Timer::GetCurrentTime();
|
||||||
|
zs->SendPacket(outapp);
|
||||||
|
safe_delete(outapp);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case ServerOP_QSSendQuery:
|
case ServerOP_QSSendQuery:
|
||||||
case ServerOP_QueryServGeneric:
|
case ServerOP_QueryServGeneric:
|
||||||
case ServerOP_Speech:
|
case ServerOP_Speech:
|
||||||
|
|||||||
@ -316,6 +316,7 @@ void MapOpcodes()
|
|||||||
ConnectedOpcodes[OP_PurchaseLeadershipAA] = &Client::Handle_OP_PurchaseLeadershipAA;
|
ConnectedOpcodes[OP_PurchaseLeadershipAA] = &Client::Handle_OP_PurchaseLeadershipAA;
|
||||||
ConnectedOpcodes[OP_PVPLeaderBoardDetailsRequest] = &Client::Handle_OP_PVPLeaderBoardDetailsRequest;
|
ConnectedOpcodes[OP_PVPLeaderBoardDetailsRequest] = &Client::Handle_OP_PVPLeaderBoardDetailsRequest;
|
||||||
ConnectedOpcodes[OP_PVPLeaderBoardRequest] = &Client::Handle_OP_PVPLeaderBoardRequest;
|
ConnectedOpcodes[OP_PVPLeaderBoardRequest] = &Client::Handle_OP_PVPLeaderBoardRequest;
|
||||||
|
ConnectedOpcodes[OP_QueryUCSServerStatus] = &Client::Handle_OP_QueryUCSServerStatus;
|
||||||
ConnectedOpcodes[OP_RaidInvite] = &Client::Handle_OP_RaidCommand;
|
ConnectedOpcodes[OP_RaidInvite] = &Client::Handle_OP_RaidCommand;
|
||||||
ConnectedOpcodes[OP_RandomReq] = &Client::Handle_OP_RandomReq;
|
ConnectedOpcodes[OP_RandomReq] = &Client::Handle_OP_RandomReq;
|
||||||
ConnectedOpcodes[OP_ReadBook] = &Client::Handle_OP_ReadBook;
|
ConnectedOpcodes[OP_ReadBook] = &Client::Handle_OP_ReadBook;
|
||||||
@ -792,7 +793,7 @@ void Client::CompleteConnect()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (zone)
|
if (zone)
|
||||||
zone->weatherSend();
|
zone->weatherSend(this);
|
||||||
|
|
||||||
TotalKarma = database.GetKarma(AccountID());
|
TotalKarma = database.GetKarma(AccountID());
|
||||||
SendDisciplineTimers();
|
SendDisciplineTimers();
|
||||||
@ -11005,6 +11006,84 @@ void Client::Handle_OP_PVPLeaderBoardRequest(const EQApplicationPacket *app)
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::Handle_OP_QueryUCSServerStatus(const EQApplicationPacket *app)
|
||||||
|
{
|
||||||
|
if (zone->IsUCSServerAvailable()) {
|
||||||
|
EQApplicationPacket* outapp = nullptr;
|
||||||
|
std::string buffer;
|
||||||
|
|
||||||
|
std::string MailKey = database.GetMailKey(CharacterID(), true);
|
||||||
|
EQEmu::versions::UCSVersion ConnectionType = EQEmu::versions::ucsUnknown;
|
||||||
|
|
||||||
|
// chat server packet
|
||||||
|
switch (ClientVersion()) {
|
||||||
|
case EQEmu::versions::ClientVersion::Titanium:
|
||||||
|
ConnectionType = EQEmu::versions::ucsTitaniumChat;
|
||||||
|
break;
|
||||||
|
case EQEmu::versions::ClientVersion::SoF:
|
||||||
|
ConnectionType = EQEmu::versions::ucsSoFCombined;
|
||||||
|
break;
|
||||||
|
case EQEmu::versions::ClientVersion::SoD:
|
||||||
|
ConnectionType = EQEmu::versions::ucsSoDCombined;
|
||||||
|
break;
|
||||||
|
case EQEmu::versions::ClientVersion::UF:
|
||||||
|
ConnectionType = EQEmu::versions::ucsUFCombined;
|
||||||
|
break;
|
||||||
|
case EQEmu::versions::ClientVersion::RoF:
|
||||||
|
ConnectionType = EQEmu::versions::ucsRoFCombined;
|
||||||
|
break;
|
||||||
|
case EQEmu::versions::ClientVersion::RoF2:
|
||||||
|
ConnectionType = EQEmu::versions::ucsRoF2Combined;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ConnectionType = EQEmu::versions::ucsUnknown;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = StringFormat("%s,%i,%s.%s,%c%s",
|
||||||
|
Config->ChatHost.c_str(),
|
||||||
|
Config->ChatPort,
|
||||||
|
Config->ShortName.c_str(),
|
||||||
|
GetName(),
|
||||||
|
ConnectionType,
|
||||||
|
MailKey.c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
outapp = new EQApplicationPacket(OP_SetChatServer, (buffer.length() + 1));
|
||||||
|
memcpy(outapp->pBuffer, buffer.c_str(), buffer.length());
|
||||||
|
outapp->pBuffer[buffer.length()] = '\0';
|
||||||
|
|
||||||
|
QueuePacket(outapp);
|
||||||
|
safe_delete(outapp);
|
||||||
|
|
||||||
|
// mail server packet
|
||||||
|
switch (ClientVersion()) {
|
||||||
|
case EQEmu::versions::ClientVersion::Titanium:
|
||||||
|
ConnectionType = EQEmu::versions::ucsTitaniumMail;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// retain value from previous switch
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = StringFormat("%s,%i,%s.%s,%c%s",
|
||||||
|
Config->MailHost.c_str(),
|
||||||
|
Config->MailPort,
|
||||||
|
Config->ShortName.c_str(),
|
||||||
|
GetName(),
|
||||||
|
ConnectionType,
|
||||||
|
MailKey.c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
outapp = new EQApplicationPacket(OP_SetChatServer2, (buffer.length() + 1));
|
||||||
|
memcpy(outapp->pBuffer, buffer.c_str(), buffer.length());
|
||||||
|
outapp->pBuffer[buffer.length()] = '\0';
|
||||||
|
|
||||||
|
QueuePacket(outapp);
|
||||||
|
safe_delete(outapp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
||||||
{
|
{
|
||||||
if (app->size < sizeof(RaidGeneral_Struct)) {
|
if (app->size < sizeof(RaidGeneral_Struct)) {
|
||||||
|
|||||||
@ -228,6 +228,7 @@
|
|||||||
void Handle_OP_PurchaseLeadershipAA(const EQApplicationPacket *app);
|
void Handle_OP_PurchaseLeadershipAA(const EQApplicationPacket *app);
|
||||||
void Handle_OP_PVPLeaderBoardDetailsRequest(const EQApplicationPacket *app);
|
void Handle_OP_PVPLeaderBoardDetailsRequest(const EQApplicationPacket *app);
|
||||||
void Handle_OP_PVPLeaderBoardRequest(const EQApplicationPacket *app);
|
void Handle_OP_PVPLeaderBoardRequest(const EQApplicationPacket *app);
|
||||||
|
void Handle_OP_QueryUCSServerStatus(const EQApplicationPacket *app);
|
||||||
void Handle_OP_RaidCommand(const EQApplicationPacket *app);
|
void Handle_OP_RaidCommand(const EQApplicationPacket *app);
|
||||||
void Handle_OP_RandomReq(const EQApplicationPacket *app);
|
void Handle_OP_RandomReq(const EQApplicationPacket *app);
|
||||||
void Handle_OP_ReadBook(const EQApplicationPacket *app);
|
void Handle_OP_ReadBook(const EQApplicationPacket *app);
|
||||||
|
|||||||
@ -1814,69 +1814,10 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ServerOP_UCSBroadcastServerReady:
|
case ServerOP_UCSServerStatusReply:
|
||||||
{
|
{
|
||||||
UCSBroadcastServerReady_Struct* bsr = (UCSBroadcastServerReady_Struct*)pack->pBuffer;
|
auto ucsss = (UCSServerStatus_Struct*)pack->pBuffer;
|
||||||
EQApplicationPacket* outapp = nullptr;
|
zone->SetUCSServerAvailable((ucsss->available != 0), ucsss->timestamp);
|
||||||
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:
|
|
||||||
{
|
|
||||||
UCSClientVersionRequest_Struct* cvreq = (UCSClientVersionRequest_Struct*)pack->pBuffer;
|
|
||||||
Client* c = entity_list.GetClientByCharID(cvreq->character_id);
|
|
||||||
if (c) {
|
|
||||||
UCSClientVersionReply_Struct cvrep;
|
|
||||||
cvrep.character_id = c->CharacterID();
|
|
||||||
cvrep.client_version = c->ClientVersion();
|
|
||||||
EQ::Net::DynamicPacket dp_cvrep;
|
|
||||||
dp_cvrep.PutData(0, &cvrep, sizeof(cvrep));
|
|
||||||
worldserver.m_connection->Send(ServerOP_UCSClientVersionReply, dp_cvrep);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ServerOP_CZSetEntityVariableByNPCTypeID:
|
case ServerOP_CZSetEntityVariableByNPCTypeID:
|
||||||
|
|||||||
@ -146,6 +146,8 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
|
|||||||
UpdateWindowTitle();
|
UpdateWindowTitle();
|
||||||
zone->GetTimeSync();
|
zone->GetTimeSync();
|
||||||
|
|
||||||
|
zone->RequestUCSServerStatus();
|
||||||
|
|
||||||
/* Set Logging */
|
/* Set Logging */
|
||||||
|
|
||||||
LogSys.StartFileLogs(StringFormat("%s_version_%u_inst_id_%u_port_%u", zone->GetShortName(), zone->GetInstanceVersion(), zone->GetInstanceID(), ZoneConfig::get()->ZonePort));
|
LogSys.StartFileLogs(StringFormat("%s_version_%u_inst_id_%u_port_%u", zone->GetShortName(), zone->GetInstanceVersion(), zone->GetInstanceID(), ZoneConfig::get()->ZonePort));
|
||||||
@ -847,6 +849,9 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
|
|||||||
GuildBanks = new GuildBankManager;
|
GuildBanks = new GuildBankManager;
|
||||||
else
|
else
|
||||||
GuildBanks = nullptr;
|
GuildBanks = nullptr;
|
||||||
|
|
||||||
|
m_ucss_available = false;
|
||||||
|
m_last_ucss_update = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Zone::~Zone() {
|
Zone::~Zone() {
|
||||||
@ -1863,14 +1868,17 @@ bool ZoneDatabase::GetDecayTimes(npcDecayTimes_Struct* npcCorpseDecayTimes) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Zone::weatherSend()
|
void Zone::weatherSend(Client* client)
|
||||||
{
|
{
|
||||||
auto outapp = new EQApplicationPacket(OP_Weather, 8);
|
auto outapp = new EQApplicationPacket(OP_Weather, 8);
|
||||||
if(zone_weather>0)
|
if(zone_weather>0)
|
||||||
outapp->pBuffer[0] = zone_weather-1;
|
outapp->pBuffer[0] = zone_weather-1;
|
||||||
if(zone_weather>0)
|
if(zone_weather>0)
|
||||||
outapp->pBuffer[4] = zone->weather_intensity;
|
outapp->pBuffer[4] = zone->weather_intensity;
|
||||||
entity_list.QueueClients(0, outapp);
|
if (client)
|
||||||
|
client->QueuePacket(outapp);
|
||||||
|
else
|
||||||
|
entity_list.QueueClients(0, outapp);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2336,3 +2344,22 @@ void Zone::UpdateHotzone()
|
|||||||
is_hotzone = atoi(row[0]) == 0 ? false: true;
|
is_hotzone = atoi(row[0]) == 0 ? false: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Zone::RequestUCSServerStatus() {
|
||||||
|
auto outapp = new ServerPacket(ServerOP_UCSServerStatusRequest, sizeof(UCSServerStatus_Struct));
|
||||||
|
auto ucsss = (UCSServerStatus_Struct*)outapp->pBuffer;
|
||||||
|
ucsss->available = 0;
|
||||||
|
ucsss->port = Config->ZonePort;
|
||||||
|
ucsss->unused = 0;
|
||||||
|
worldserver.SendPacket(outapp);
|
||||||
|
safe_delete(outapp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Zone::SetUCSServerAvailable(bool ucss_available, uint32 update_timestamp) {
|
||||||
|
if (m_last_ucss_update == update_timestamp && m_ucss_available != ucss_available) {
|
||||||
|
m_ucss_available = false;
|
||||||
|
RequestUCSServerStatus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_last_ucss_update < update_timestamp)
|
||||||
|
m_ucss_available = ucss_available;
|
||||||
|
}
|
||||||
|
|||||||
@ -224,7 +224,7 @@ public:
|
|||||||
void SetDate(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute);
|
void SetDate(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute);
|
||||||
void SetTime(uint8 hour, uint8 minute, bool update_world = true);
|
void SetTime(uint8 hour, uint8 minute, bool update_world = true);
|
||||||
|
|
||||||
void weatherSend();
|
void weatherSend(Client* client = nullptr);
|
||||||
bool CanBind() const { return(can_bind); }
|
bool CanBind() const { return(can_bind); }
|
||||||
bool IsCity() const { return(is_city); }
|
bool IsCity() const { return(is_city); }
|
||||||
bool CanDoCombat() const { return(can_combat); }
|
bool CanDoCombat() const { return(can_combat); }
|
||||||
@ -275,6 +275,10 @@ public:
|
|||||||
inline void ShowZoneGlobalLoot(Client *to) { m_global_loot.ShowZoneGlobalLoot(to); }
|
inline void ShowZoneGlobalLoot(Client *to) { m_global_loot.ShowZoneGlobalLoot(to); }
|
||||||
inline void ShowNPCGlobalLoot(Client *to, NPC *who) { m_global_loot.ShowNPCGlobalLoot(to, who); }
|
inline void ShowNPCGlobalLoot(Client *to, NPC *who) { m_global_loot.ShowNPCGlobalLoot(to, who); }
|
||||||
|
|
||||||
|
void RequestUCSServerStatus();
|
||||||
|
void SetUCSServerAvailable(bool ucss_available, uint32 update_timestamp);
|
||||||
|
bool IsUCSServerAvailable() { return m_ucss_available; }
|
||||||
|
|
||||||
// random object that provides random values for the zone
|
// random object that provides random values for the zone
|
||||||
EQEmu::Random random;
|
EQEmu::Random random;
|
||||||
|
|
||||||
@ -355,6 +359,9 @@ private:
|
|||||||
Timer hotzone_timer;
|
Timer hotzone_timer;
|
||||||
|
|
||||||
GlobalLootManager m_global_loot;
|
GlobalLootManager m_global_loot;
|
||||||
|
|
||||||
|
bool m_ucss_available;
|
||||||
|
uint32 m_last_ucss_update;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1623,6 +1623,8 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla
|
|||||||
if (account_id <= 0)
|
if (account_id <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
std::string mail_key = database.GetMailKey(character_id);
|
||||||
|
|
||||||
clock_t t = std::clock(); /* Function timer start */
|
clock_t t = std::clock(); /* Function timer start */
|
||||||
std::string query = StringFormat(
|
std::string query = StringFormat(
|
||||||
"REPLACE INTO `character_data` ("
|
"REPLACE INTO `character_data` ("
|
||||||
@ -1719,7 +1721,8 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla
|
|||||||
" e_aa_effects, "
|
" e_aa_effects, "
|
||||||
" e_percent_to_aa, "
|
" e_percent_to_aa, "
|
||||||
" e_expended_aa_spent, "
|
" e_expended_aa_spent, "
|
||||||
" e_last_invsnapshot "
|
" e_last_invsnapshot, "
|
||||||
|
" mailkey "
|
||||||
") "
|
") "
|
||||||
"VALUES ("
|
"VALUES ("
|
||||||
"%u," // id " id, "
|
"%u," // id " id, "
|
||||||
@ -1815,7 +1818,8 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla
|
|||||||
"%u," // e_aa_effects
|
"%u," // e_aa_effects
|
||||||
"%u," // e_percent_to_aa
|
"%u," // e_percent_to_aa
|
||||||
"%u," // e_expended_aa_spent
|
"%u," // e_expended_aa_spent
|
||||||
"%u" // e_last_invsnapshot
|
"%u," // e_last_invsnapshot
|
||||||
|
"'%s'" // mailkey mail_key
|
||||||
")",
|
")",
|
||||||
character_id, // " id, "
|
character_id, // " id, "
|
||||||
account_id, // " account_id, "
|
account_id, // " account_id, "
|
||||||
@ -1910,7 +1914,8 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla
|
|||||||
m_epp->aa_effects,
|
m_epp->aa_effects,
|
||||||
m_epp->perAA,
|
m_epp->perAA,
|
||||||
m_epp->expended_aa,
|
m_epp->expended_aa,
|
||||||
m_epp->last_invsnapshot_time
|
m_epp->last_invsnapshot_time,
|
||||||
|
mail_key.c_str()
|
||||||
);
|
);
|
||||||
auto results = database.QueryDatabase(query);
|
auto results = database.QueryDatabase(query);
|
||||||
Log(Logs::General, Logs::None, "ZoneDatabase::SaveCharacterData %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC);
|
Log(Logs::General, Logs::None, "ZoneDatabase::SaveCharacterData %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user