Merge branch 'master' into lsid

This commit is contained in:
Akkadius
2019-06-26 00:56:13 -05:00
2172 changed files with 293887 additions and 87284 deletions
+1 -1
View File
@@ -65,6 +65,6 @@ TARGET_LINK_LIBRARIES(world ${SERVER_LIBS})
IF(EQEMU_BUILD_PERL)
TARGET_LINK_LIBRARIES(world ${PERL_LIBRARY})
ENDIF(EQEMU_BUILD_PERL)
ENDIF()
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
+95 -59
View File
@@ -84,6 +84,7 @@ extern ClientList client_list;
extern EQEmu::Random emu_random;
extern uint32 numclients;
extern volatile bool RunLoops;
extern volatile bool UCSServerAvailable_;
Client::Client(EQStreamInterface* ieqs)
: autobootup_timeout(RuleI(World, ZoneAutobootTimeoutMS)),
@@ -170,10 +171,12 @@ void Client::SendEnterWorld(std::string name)
void Client::SendExpansionInfo() {
auto outapp = new EQApplicationPacket(OP_ExpansionInfo, sizeof(ExpansionInfo_Struct));
ExpansionInfo_Struct *eis = (ExpansionInfo_Struct*)outapp->pBuffer;
if(RuleB(World, UseClientBasedExpansionSettings)) {
eis->Expansions = EQEmu::versions::ConvertClientVersionToExpansion(eqs->ClientVersion());
} else {
eis->Expansions = (RuleI(World, ExpansionSettings));
if (RuleB(World, UseClientBasedExpansionSettings)) {
eis->Expansions = EQEmu::expansions::ConvertClientVersionToExpansionsMask(eqs->ClientVersion());
}
else {
eis->Expansions = (RuleI(World, ExpansionSettings) & EQEmu::expansions::ConvertClientVersionToExpansionsMask(eqs->ClientVersion()));
}
QueuePacket(outapp);
@@ -185,7 +188,7 @@ void Client::SendCharInfo() {
cle->SetOnline(CLE_Status_CharSelect);
}
if (m_ClientVersionBit & EQEmu::versions::bit_RoFAndLater) {
if (m_ClientVersionBit & EQEmu::versions::maskRoFAndLater) {
SendMaxCharCreate();
SendMembership();
SendMembershipSettings();
@@ -210,9 +213,9 @@ void Client::SendMaxCharCreate() {
auto outapp = new EQApplicationPacket(OP_SendMaxCharacters, sizeof(MaxCharacters_Struct));
MaxCharacters_Struct* mc = (MaxCharacters_Struct*)outapp->pBuffer;
mc->max_chars = EQEmu::constants::Lookup(m_ClientVersion)->CharacterCreationLimit;
if (mc->max_chars > EQEmu::constants::CharacterCreationMax)
mc->max_chars = EQEmu::constants::CharacterCreationMax;
mc->max_chars = EQEmu::constants::StaticLookup(m_ClientVersion)->CharacterCreationLimit;
if (mc->max_chars > EQEmu::constants::CHARACTER_CREATION_LIMIT)
mc->max_chars = EQEmu::constants::CHARACTER_CREATION_LIMIT;
QueuePacket(outapp);
safe_delete(outapp);
@@ -251,7 +254,7 @@ void Client::SendMembership() {
mc->entries[1] = 0xffffffff; // Max Level Restriction
mc->entries[2] = 0xffffffff; // Max Char Slots per Account (not used by client?)
mc->entries[3] = 0xffffffff; // 1 for Silver
mc->entries[4] = 8; // Main Inventory Size (0xffffffff on Live for Gold, but limiting to 8 until 10 is supported)
mc->entries[4] = 0xffffffff; // Main Inventory Size (0xffffffff on Live for Gold, but limiting to 8 until 10 is supported)
mc->entries[5] = 0xffffffff; // Max Platinum per level
mc->entries[6] = 1; // 0 for Silver
mc->entries[7] = 1; // 0 for Silver
@@ -676,7 +679,7 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
}
else
{
if (m_ClientVersionBit & EQEmu::versions::bit_TitaniumAndEarlier)
if (m_ClientVersionBit & EQEmu::versions::maskTitaniumAndEarlier)
StartInTutorial = true;
SendCharInfo();
}
@@ -724,9 +727,9 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
// This can probably be moved outside and have another method return requested info (don't forget to remove the #include "../common/shareddb.h" above)
// (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration)
if (!is_player_zoning) {
size_t character_limit = EQEmu::constants::Lookup(eqs->ClientVersion())->CharacterCreationLimit;
if (character_limit > EQEmu::constants::CharacterCreationMax) { character_limit = EQEmu::constants::CharacterCreationMax; }
if (eqs->ClientVersion() == EQEmu::versions::ClientVersion::Titanium) { character_limit = 8; }
size_t character_limit = EQEmu::constants::StaticLookup(eqs->ClientVersion())->CharacterCreationLimit;
if (character_limit > EQEmu::constants::CHARACTER_CREATION_LIMIT) { character_limit = EQEmu::constants::CHARACTER_CREATION_LIMIT; }
if (eqs->ClientVersion() == EQEmu::versions::ClientVersion::Titanium) { character_limit = Titanium::constants::CHARACTER_CREATION_LIMIT; }
std::string tgh_query = StringFormat(
"SELECT "
@@ -850,53 +853,84 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
}
QueuePacket(outapp);
safe_delete(outapp);
// set mailkey - used for duration of character session
int MailKey = emu_random.Int(1, INT_MAX);
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)
ConnectionType = 'U';
else if (m_ClientVersionBit & EQEmu::versions::bit_SoFAndLater)
ConnectionType = 'S';
else
ConnectionType = 'C';
// chat server packet
switch (GetClientVersion()) {
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;
}
auto outapp2 = new EQApplicationPacket(OP_SetChatServer);
char buffer[112];
buffer = StringFormat("%s,%i,%s.%s,%c%08X",
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",
Config->ChatHost.c_str(),
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);
QueuePacket(outapp);
safe_delete(outapp);
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)
ConnectionType = 'M';
buffer = StringFormat("%s,%i,%s.%s,%c%08X",
Config->MailHost.c_str(),
Config->MailPort,
Config->ShortName.c_str(),
GetCharName(),
ConnectionType,
MailKey
);
sprintf(buffer,"%s,%i,%s.%s,%c%08X",
Config->MailHost.c_str(),
Config->MailPort,
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);
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);
}
EnterWorld();
@@ -917,7 +951,7 @@ bool Client::HandleDeleteCharacterPacket(const EQApplicationPacket *app) {
bool Client::HandleZoneChangePacket(const EQApplicationPacket *app) {
// HoT sends this to world while zoning and wants it echoed back.
if (m_ClientVersionBit & EQEmu::versions::bit_RoFAndLater)
if (m_ClientVersionBit & EQEmu::versions::maskRoFAndLater)
{
QueuePacket(app);
}
@@ -1370,6 +1404,11 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
PlayerProfile_Struct pp;
ExtendedProfile_Struct ext;
EQEmu::InventoryProfile inv;
pp.SetPlayerProfileVersion(EQEmu::versions::ConvertClientVersionToMobVersion(EQEmu::versions::ConvertClientVersionBitToClientVersion(m_ClientVersionBit)));
inv.SetInventoryVersion(EQEmu::versions::ConvertClientVersionBitToClientVersion(m_ClientVersionBit));
inv.SetGMInventory(false); // character cannot have gm flag at this point
time_t bday = time(nullptr);
char startzone[50]={0};
uint32 i;
@@ -1392,7 +1431,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
Log(Logs::Detail, Logs::World_Server, "Beard: %d Beardcolor: %d", cc->beard, cc->beardcolor);
/* Validate the char creation struct */
if (m_ClientVersionBit & EQEmu::versions::bit_SoFAndLater) {
if (m_ClientVersionBit & EQEmu::versions::maskSoFAndLater) {
if (!CheckCharCreateInfoSoF(cc)) {
Log(Logs::Detail, Logs::World_Server,"CheckCharCreateInfo did not validate the request (bad race/class/stats)");
return false;
@@ -1449,12 +1488,9 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
// strcpy(pp.servername, WorldConfig::get()->ShortName.c_str());
for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++)
pp.spell_book[i] = 0xFFFFFFFF;
for(i = 0; i < MAX_PP_MEMSPELL; i++)
pp.mem_spells[i] = 0xFFFFFFFF;
memset(pp.spell_book, 0xFF, (sizeof(uint32) * EQEmu::spells::SPELLBOOK_SIZE));
memset(pp.mem_spells, 0xFF, (sizeof(uint32) * EQEmu::spells::SPELL_GEM_COUNT));
for(i = 0; i < BUFF_COUNT; i++)
pp.buffs[i].spellid = 0xFFFF;
@@ -1463,7 +1499,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
pp.pvp = database.GetServerType() == 1 ? 1 : 0;
/* If it is an SoF Client and the SoF Start Zone rule is set, send new chars there */
if (m_ClientVersionBit & EQEmu::versions::bit_SoFAndLater) {
if (m_ClientVersionBit & EQEmu::versions::maskSoFAndLater) {
Log(Logs::Detail, Logs::World_Server,"Found 'SoFStartZoneID' rule setting: %i", RuleI(World, SoFStartZoneID));
if (RuleI(World, SoFStartZoneID) > 0) {
pp.zone_id = RuleI(World, SoFStartZoneID);
@@ -1479,7 +1515,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
}
}
/* use normal starting zone logic to either get defaults, or if startzone was set, load that from the db table.*/
bool ValidStartZone = database.GetStartZone(&pp, cc, m_ClientVersionBit & EQEmu::versions::bit_TitaniumAndEarlier);
bool ValidStartZone = database.GetStartZone(&pp, cc, m_ClientVersionBit & EQEmu::versions::maskTitaniumAndEarlier);
if (!ValidStartZone){
return false;
+1
View File
@@ -68,6 +68,7 @@ public:
inline const char* GetLSKey() { if (cle) { return cle->GetLSKey(); } return "NOKEY"; }
inline uint32 GetCharID() { return charid; }
inline const char* GetCharName() { return char_name; }
inline EQEmu::versions::ClientVersion GetClientVersion() { return m_ClientVersion; }
inline ClientListEntry* GetCLE() { return cle; }
inline void SetCLE(ClientListEntry* iCLE) { cle = iCLE; }
private:
+22
View File
@@ -493,6 +493,28 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
//uint32 x = 0;
int whomlen = 0;
if (whom) {
// fixes for client converting some queries into a race query instead of zone
if (whom->wrace == 221) {
whom->wrace = 0xFFFF;
strcpy(whom->whom, "scarlet");
}
if (whom->wrace == 327) {
whom->wrace = 0xFFFF;
strcpy(whom->whom, "crystal");
}
if (whom->wrace == 103) {
whom->wrace = 0xFFFF;
strcpy(whom->whom, "kedge");
}
if (whom->wrace == 230) {
whom->wrace = 0xFFFF;
strcpy(whom->whom, "akheva");
}
if (whom->wrace == 229) {
whom->wrace = 0xFFFF;
strcpy(whom->whom, "netherbian");
}
whomlen = strlen(whom->whom);
if(whom->wrace == 0x001A) // 0x001A is the old Froglok race number and is sent by the client for /who all froglok
whom->wrace = FROGLOK; // This is what EQEmu uses for the Froglok Race number.
+30
View File
@@ -336,6 +336,20 @@ void LoginServer::SendStatus() {
delete pack;
}
void LoginServer::SendPacket(ServerPacket *pack)
{
if (IsLegacy) {
if (legacy_client) {
legacy_client->SendPacket(pack);
}
}
else {
if (client) {
client->SendPacket(pack);
}
}
}
void LoginServer::SendAccountUpdate(ServerPacket* pack) {
ServerLSAccountUpdate_Struct* s = (ServerLSAccountUpdate_Struct *)pack->pBuffer;
if (CanUpdate()) {
@@ -345,3 +359,19 @@ void LoginServer::SendAccountUpdate(ServerPacket* pack) {
SendPacket(pack);
}
}
bool LoginServer::Connected()
{
if (IsLegacy) {
if (legacy_client) {
return legacy_client->Connected();
}
}
else {
if (client) {
return client->Connected();
}
}
return false;
}
+2 -1
View File
@@ -39,9 +39,10 @@ public:
void SendInfo();
void SendStatus();
void SendPacket(ServerPacket* pack) { if (IsLegacy) legacy_client->SendPacket(pack); else client->SendPacket(pack); }
void SendPacket(ServerPacket* pack);
void SendAccountUpdate(ServerPacket* pack);
bool Connected() { return IsLegacy ? legacy_client->Connected() : client->Connected(); }
bool MiniLogin() { return minilogin; }
bool CanUpdate() { return CanAccountUpdate; }
private:
+22 -5
View File
@@ -85,6 +85,7 @@ union semun {
#include "console.h"
#include "../common/net/servertalk_server.h"
#include "../zone/data_bucket.h"
ClientList client_list;
GroupLFPList LFPGroupList;
@@ -314,6 +315,9 @@ int main(int argc, char** argv) {
}
}
Log(Logs::General, Logs::World_Server, "Purging expired data buckets...");
database.PurgeAllDeletedDataBuckets();
Log(Logs::General, Logs::World_Server, "Loading zones..");
database.LoadZoneNames();
Log(Logs::General, Logs::World_Server, "Clearing groups..");
@@ -337,18 +341,21 @@ int main(int argc, char** argv) {
std::string tmp;
if (database.GetVariable("RuleSet", tmp)) {
Log(Logs::General, Logs::World_Server, "Loading rule set '%s'", tmp.c_str());
if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str())) {
if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) {
Log(Logs::General, Logs::World_Server, "Failed to load ruleset '%s', falling back to defaults.", tmp.c_str());
}
}
else {
if (!RuleManager::Instance()->LoadRules(&database, "default")) {
if (!RuleManager::Instance()->LoadRules(&database, "default", false)) {
Log(Logs::General, Logs::World_Server, "No rule set configured, using default rules");
}
else {
Log(Logs::General, Logs::World_Server, "Loaded default rule set 'default'", tmp.c_str());
}
}
EQEmu::InitializeDynamicLookups();
Log(Logs::General, Logs::World_Server, "Initialized dynamic dictionary entries");
}
if (RuleB(World, ClearTempMerchantlist)) {
@@ -394,6 +401,7 @@ int main(int argc, char** argv) {
Log(Logs::General, Logs::World_Server, "Purging expired instances");
database.PurgeExpiredInstances();
Timer PurgeInstanceTimer(450000);
PurgeInstanceTimer.Start(450000);
@@ -467,6 +475,8 @@ int main(int argc, char** argv) {
connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID());
UCSLink.SetConnection(connection);
zoneserver_list.UpdateUCSServerAvailable();
});
server_connection->OnConnectionRemoved("UCS", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
@@ -474,6 +484,8 @@ int main(int argc, char** argv) {
connection->GetUUID());
UCSLink.SetConnection(nullptr);
zoneserver_list.UpdateUCSServerAvailable(false);
});
server_connection->OnConnectionIdentified("WebInterface", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
@@ -491,6 +503,11 @@ int main(int argc, char** argv) {
});
EQ::Net::EQStreamManagerOptions opts(9000, false, false);
opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS);
opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor);
opts.daybreak_options.resend_delay_min = RuleI(Network, ResendDelayMinMS);
opts.daybreak_options.resend_delay_max = RuleI(Network, ResendDelayMaxMS);
EQ::Net::EQStreamManager eqsm(opts);
//register all the patches we have avaliable with the stream identifier.
@@ -546,9 +563,9 @@ int main(int argc, char** argv) {
client_list.Process();
if (PurgeInstanceTimer.Check())
{
if (PurgeInstanceTimer.Check()) {
database.PurgeExpiredInstances();
database.PurgeAllDeletedDataBuckets();
}
if (EQTimeTimer.Check()) {
@@ -618,4 +635,4 @@ void CheckForServerScript(bool force_download) {
system("wget -N --no-check-certificate --quiet -O eqemu_server.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl");
#endif
}
}
}
+149 -21
View File
@@ -36,11 +36,11 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou
{
/* Set Character Creation Limit */
EQEmu::versions::ClientVersion client_version = EQEmu::versions::ConvertClientVersionBitToClientVersion(clientVersionBit);
size_t character_limit = EQEmu::constants::Lookup(client_version)->CharacterCreationLimit;
size_t character_limit = EQEmu::constants::StaticLookup(client_version)->CharacterCreationLimit;
// Validate against absolute server max
if (character_limit > EQEmu::constants::CharacterCreationMax)
character_limit = EQEmu::constants::CharacterCreationMax;
if (character_limit > EQEmu::constants::CHARACTER_CREATION_LIMIT)
character_limit = EQEmu::constants::CHARACTER_CREATION_LIMIT;
// Force Titanium clients to use '8'
if (client_version == EQEmu::versions::ClientVersion::Titanium)
@@ -97,6 +97,11 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou
CharacterSelectEntry_Struct *cse = (CharacterSelectEntry_Struct *)buff_ptr;
PlayerProfile_Struct pp;
EQEmu::InventoryProfile inv;
pp.SetPlayerProfileVersion(EQEmu::versions::ConvertClientVersionToMobVersion(client_version));
inv.SetInventoryVersion(client_version);
inv.SetGMInventory(true); // charsel can not interact with items..but, no harm in setting to full expansion support
uint32 character_id = (uint32)atoi(row[0]);
uint8 has_home = 0;
uint8 has_bind = 0;
@@ -243,7 +248,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou
/* Load Inventory */
// If we ensure that the material data is updated appropriately, we can do away with inventory loads
if (GetInventory(accountID, cse->Name, &inv)) {
if (GetCharSelInventory(accountID, cse->Name, &inv)) {
const EQEmu::ItemData* item = nullptr;
const EQEmu::ItemInstance* inst = nullptr;
int16 invslot = 0;
@@ -516,23 +521,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)
{
std::string query = StringFormat("SELECT level FROM character_data WHERE name = '%s'", name);
@@ -607,3 +595,143 @@ bool WorldDatabase::LoadCharacterCreateCombos()
return true;
}
// this is a slightly modified version of SharedDatabase::GetInventory(...) for character select use-only
bool WorldDatabase::GetCharSelInventory(uint32 account_id, char *name, EQEmu::InventoryProfile *inv)
{
if (!account_id || !name || !inv)
return false;
std::string query = StringFormat(
"SELECT"
" slotid,"
" itemid,"
" charges,"
" color,"
" augslot1,"
" augslot2,"
" augslot3,"
" augslot4,"
" augslot5,"
" augslot6,"
" instnodrop,"
" custom_data,"
" ornamenticon,"
" ornamentidfile,"
" ornament_hero_model "
"FROM"
" inventory "
"INNER JOIN"
" character_data ch "
"ON"
" ch.id = charid "
"WHERE"
" ch.name = '%s' "
"AND"
" ch.account_id = %i "
"AND"
" slotid >= %i "
"AND"
" slotid <= %i",
name,
account_id,
EQEmu::invslot::slotHead,
EQEmu::invslot::slotFeet
);
auto results = QueryDatabase(query);
if (!results.Success())
return false;
for (auto row = results.begin(); row != results.end(); ++row) {
int16 slot_id = atoi(row[0]);
switch (slot_id) {
case EQEmu::invslot::slotFace:
case EQEmu::invslot::slotEar2:
case EQEmu::invslot::slotNeck:
case EQEmu::invslot::slotShoulders:
case EQEmu::invslot::slotBack:
case EQEmu::invslot::slotFinger1:
case EQEmu::invslot::slotFinger2:
continue;
default:
break;
}
uint32 item_id = atoi(row[1]);
int8 charges = atoi(row[2]);
uint32 color = atoul(row[3]);
uint32 aug[EQEmu::invaug::SOCKET_COUNT];
aug[0] = (uint32)atoi(row[4]);
aug[1] = (uint32)atoi(row[5]);
aug[2] = (uint32)atoi(row[6]);
aug[3] = (uint32)atoi(row[7]);
aug[4] = (uint32)atoi(row[8]);
aug[5] = (uint32)atoi(row[9]);
bool instnodrop = ((row[10] && (uint16)atoi(row[10])) ? true : false);
uint32 ornament_icon = (uint32)atoul(row[12]);
uint32 ornament_idfile = (uint32)atoul(row[13]);
uint32 ornament_hero_model = (uint32)atoul(row[14]);
const EQEmu::ItemData *item = GetItem(item_id);
if (!item)
continue;
EQEmu::ItemInstance *inst = CreateBaseItem(item, charges);
if (inst == nullptr)
continue;
inst->SetAttuned(instnodrop);
if (row[11]) {
std::string data_str(row[11]);
std::string idAsString;
std::string value;
bool use_id = true;
for (int i = 0; i < data_str.length(); ++i) {
if (data_str[i] == '^') {
if (!use_id) {
inst->SetCustomData(idAsString, value);
idAsString.clear();
value.clear();
}
use_id = !use_id;
continue;
}
char v = data_str[i];
if (use_id)
idAsString.push_back(v);
else
value.push_back(v);
}
}
inst->SetOrnamentIcon(ornament_icon);
inst->SetOrnamentationIDFile(ornament_idfile);
inst->SetOrnamentHeroModel(item->HerosForgeModel);
if (color > 0)
inst->SetColor(color);
inst->SetCharges(charges);
if (item->IsClassCommon()) {
for (int i = EQEmu::invaug::SOCKET_BEGIN; i <= EQEmu::invaug::SOCKET_END; i++) {
if (aug[i])
inst->PutAugment(this, i, aug[i]);
}
}
inv->PutItem(slot_id, *inst);
safe_delete(inst);
}
return true;
}
+2 -1
View File
@@ -34,7 +34,6 @@ public:
int MoveCharacterToBind(int CharID, uint8 bindnum = 0);
void GetLauncherList(std::vector<std::string> &result);
void SetMailKey(int CharID, int IPAddress, int MailKey);
bool GetCharacterLevel(const char *name, int &level);
bool LoadCharacterCreateAllocations();
@@ -42,6 +41,8 @@ public:
private:
void SetTitaniumDefaultStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc);
void SetSoFDefaultStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc);
bool GetCharSelInventory(uint32 account_id, char* name, EQEmu::InventoryProfile* inv);
};
extern WorldDatabase database;
+20 -1
View File
@@ -32,6 +32,7 @@ extern uint32 numzones;
extern bool holdzones;
extern EQEmu::Random emu_random;
extern WebInterfaceList web_interface;
volatile bool UCSServerAvailable_ = false;
void CatchSignal(int sig_num);
ZSList::ZSList()
@@ -42,6 +43,7 @@ ZSList::ZSList()
memset(pLockedZones, 0, sizeof(pLockedZones));
m_tick.reset(new EQ::Timer(5000, true, std::bind(&ZSList::OnTick, this, std::placeholders::_1)));
m_keepalive.reset(new EQ::Timer(2500, true, std::bind(&ZSList::OnKeepAlive, this, std::placeholders::_1)));
}
ZSList::~ZSList() {
@@ -669,6 +671,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)
{
if (time > 0) {
@@ -734,4 +746,11 @@ void ZSList::OnTick(EQ::Timer *t)
}
web_interface.SendEvent(out);
}
}
void ZSList::OnKeepAlive(EQ::Timer *t)
{
for (auto &zone : list) {
zone->SendKeepAlive();
}
}
+4 -1
View File
@@ -54,7 +54,8 @@ public:
Timer* reminder;
void NextGroupIDs(uint32 &start, uint32 &end);
void SendLSZones();
uint16 GetAvailableZonePort();
uint16 GetAvailableZonePort();
void UpdateUCSServerAvailable(bool ucss_available = true);
int GetZoneCount();
void GetZoneIDList(std::vector<uint32> &zones);
@@ -62,6 +63,7 @@ public:
private:
void OnTick(EQ::Timer *t);
void OnKeepAlive(EQ::Timer *t);
uint32 NextID;
std::list<std::unique_ptr<ZoneServer>> list;
uint16 pLockedZones[MaxLockedZones];
@@ -69,6 +71,7 @@ private:
uint16 LastAllocatedPort;
std::unique_ptr<EQ::Timer> m_tick;
std::unique_ptr<EQ::Timer> m_keepalive;
};
#endif /*ZONELIST_H_*/
+33 -2
View File
@@ -41,6 +41,7 @@ extern GroupLFPList LFPGroupList;
extern ZSList zoneserver_list;
extern LoginServerList loginserverlist;
extern volatile bool RunLoops;
extern volatile bool UCSServerAvailable_;
extern AdventureManager adventure_manager;
extern UCSConnection UCSLink;
extern QueryServConnection QSLink;
@@ -813,12 +814,12 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
}
case ServerOP_ReloadRules: {
zoneserver_list.SendPacket(pack);
RuleManager::Instance()->LoadRules(&database, "default");
RuleManager::Instance()->LoadRules(&database, "default", true);
break;
}
case ServerOP_ReloadRulesWorld:
{
RuleManager::Instance()->LoadRules(&database, "default");
RuleManager::Instance()->LoadRules(&database, "default", true);
break;
}
case ServerOP_ReloadPerlExportSettings:
@@ -980,6 +981,10 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
safe_delete(pack);
break;
}
case ServerOP_RefreshCensorship: {
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_SetWorldTime: {
Log(Logs::Detail, Logs::World_Server, "Received SetWorldTime");
eqTimeOfDay* newtime = (eqTimeOfDay*)pack->pBuffer;
@@ -1267,6 +1272,24 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
UCSLink.SendPacket(pack);
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_QueryServGeneric:
case ServerOP_Speech:
@@ -1276,6 +1299,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
case ServerOP_QSPlayerLogDeletes:
case ServerOP_QSPlayerLogMoves:
case ServerOP_QSPlayerLogMerchantTransactions:
case ServerOP_QSPlayerDropItem:
{
QSLink.SendPacket(pack);
break;
@@ -1381,6 +1405,13 @@ void ZoneServer::SendGroupIDs() {
delete pack;
}
void ZoneServer::SendKeepAlive()
{
ServerPacket pack(ServerOP_KeepAlive, 0);
SendPacket(&pack);
}
void ZoneServer::ChangeWID(uint32 iCharID, uint32 iWID) {
auto pack = new ServerPacket(ServerOP_ChangeWID, sizeof(ServerChangeWID_Struct));
ServerChangeWID_Struct* scw = (ServerChangeWID_Struct*)pack->pBuffer;
+1
View File
@@ -39,6 +39,7 @@ public:
void SendPacket(ServerPacket* pack) { tcpc->SendPacket(pack); }
void SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...);
void SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message);
void SendKeepAlive();
bool SetZone(uint32 iZoneID, uint32 iInstanceID = 0, bool iStaticZone = false);
void TriggerBootup(uint32 iZoneID = 0, uint32 iInstanceID = 0, const char* iAdminName = 0, bool iMakeStatic = false);
void Disconnect() { auto handle = tcpc->Handle(); if (handle) { handle->Disconnect(); } }