From fe10353863956ac6adfe15bd00e4fb7fd16c6133 Mon Sep 17 00:00:00 2001 From: Emagi Date: Sun, 15 Dec 2024 15:22:21 -0500 Subject: [PATCH] Added public zone persistence of spawns back, command /location list respawns added, additionally added tracking of duplicate zones for exceeding player limits --- source/WorldServer/Commands/Commands.cpp | 11 +++++-- source/WorldServer/PlayerGroups.cpp | 6 ++-- source/WorldServer/Web/PeerManager.cpp | 21 ++++++++++--- source/WorldServer/Web/PeerManager.h | 5 +-- source/WorldServer/Web/WorldWeb.cpp | 13 ++++++-- source/WorldServer/World.cpp | 34 +++++++++++++++------ source/WorldServer/World.h | 2 +- source/WorldServer/WorldDatabase.cpp | 13 +++++--- source/WorldServer/zoneserver.cpp | 39 +++++++++++++++++++----- source/WorldServer/zoneserver.h | 5 +++ 10 files changed, 113 insertions(+), 36 deletions(-) diff --git a/source/WorldServer/Commands/Commands.cpp b/source/WorldServer/Commands/Commands.cpp index d749184..c59e196 100644 --- a/source/WorldServer/Commands/Commands.cpp +++ b/source/WorldServer/Commands/Commands.cpp @@ -7510,7 +7510,7 @@ void Commands::Command_Location(Client* client) client->SimpleMessage(CHANNEL_COLOR_YELLOW, "/location add [location id]"); client->SimpleMessage(CHANNEL_COLOR_YELLOW, "/location remove [location point id]"); client->SimpleMessage(CHANNEL_COLOR_YELLOW, "/location delete [location id]"); - client->SimpleMessage(CHANNEL_COLOR_YELLOW, "/location list [locations|points] [location id if points used]"); + client->SimpleMessage(CHANNEL_COLOR_YELLOW, "/location list [locations|points|respawns] [location id if points used]"); } /* @@ -7603,16 +7603,18 @@ void Commands::Command_LocationList(Client* client, Seperator* sep) if (strncmp(option, "locations", strlen(option)) == 0) database.ListLocations(client); + else if (strncmp(option, "respawns", strlen(option)) == 0) + client->GetPlayer()->GetZone()->SendRespawnTimerList(client); else if (strncmp(option, "points", strlen(option)) == 0 && sep->arg[1] && sep->IsNumber(1)) { int32 location_id = atoul(sep->arg[1]); database.ListLocationPoints(client, location_id); } else - client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Useage: /location list [locations|points] [location ID if points used]"); + client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Useage: /location list [locations|points|respawns] [location ID if points used]"); } else - client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Useage: /location list [locations|points] [location ID if points used]"); + client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Useage: /location list [locations|points|respawns] [location ID if points used]"); } /* @@ -10991,6 +10993,9 @@ void Commands::Command_Test(Client* client, EQ2_16BitString* command_parms) { guild->SendGuildMemberList(); } + else if(atoi(sep->arg[0]) == 38) { + client->GetPlayer()->GetZone()->SendFlightPathsPackets(client); + } } else { PacketStruct* packet2 = configReader.getStruct("WS_ExaminePartialSpellInfo", client->GetVersion()); diff --git a/source/WorldServer/PlayerGroups.cpp b/source/WorldServer/PlayerGroups.cpp index ff87a1e..8a218e3 100644 --- a/source/WorldServer/PlayerGroups.cpp +++ b/source/WorldServer/PlayerGroups.cpp @@ -1905,7 +1905,7 @@ bool PlayerGroupManager::IdentifyMemberInGroupOrRaid(ZoneChangeDetails* details, tmp->GetInstanceID(), tmp->GetSafeX(), tmp->GetSafeY(), tmp->GetSafeZ(), tmp->GetSafeHeading(), tmp->GetZoneLockState(), tmp->GetMinimumStatus(), tmp->GetMinimumLevel(), tmp->GetMaximumLevel(), tmp->GetMinimumVersion(), tmp->GetDefaultLockoutTime(), tmp->GetDefaultReenterTime(), - tmp->GetInstanceType(), tmp->NumPlayers()); + tmp->GetInstanceType(), tmp->NumPlayers(), tmp->IsCityZone()); safe_delete(tmp); succeed = true; break; @@ -1922,7 +1922,7 @@ bool PlayerGroupManager::IdentifyMemberInGroupOrRaid(ZoneChangeDetails* details, ret->GetSafeZ(), ret->GetSafeHeading(), ret->GetZoneLockState(), ret->GetMinimumStatus(), ret->GetMinimumLevel(), ret->GetMaximumLevel(), ret->GetMinimumVersion(), ret->GetDefaultLockoutTime(), ret->GetDefaultReenterTime(), - ret->GetInstanceType(), ret->NumPlayers(), ret); + ret->GetInstanceType(), ret->NumPlayers(), ret->IsCityZone(), ret); return true; } @@ -1946,7 +1946,7 @@ bool PlayerGroupManager::IdentifyMemberInGroupOrRaid(ZoneChangeDetails* details, tmp->GetInstanceID(), tmp->GetSafeX(), tmp->GetSafeY(), tmp->GetSafeZ(), tmp->GetSafeHeading(), tmp->GetZoneLockState(), tmp->GetMinimumStatus(), tmp->GetMinimumLevel(), tmp->GetMaximumLevel(), tmp->GetMinimumVersion(), tmp->GetDefaultLockoutTime(), tmp->GetDefaultReenterTime(), - tmp->GetInstanceType(), tmp->NumPlayers()); + tmp->GetInstanceType(), tmp->NumPlayers(), tmp->IsCityZone()); safe_delete(tmp); succeed = true; break; diff --git a/source/WorldServer/Web/PeerManager.cpp b/source/WorldServer/Web/PeerManager.cpp index bc83ef4..8fe88a6 100644 --- a/source/WorldServer/Web/PeerManager.cpp +++ b/source/WorldServer/Web/PeerManager.cpp @@ -96,7 +96,7 @@ void PeerManager::updateClientTree(const std::string& id, const boost::property_ void PeerManager::setZonePeerData(ZoneChangeDetails* opt_details, std::string peerId, std::string peerWorldAddress, std::string peerInternalWorldAddress, int16 peerWorldPort, std::string peerWebAddress, int16 peerWebPort, std::string zoneFileName, std::string zoneName, int32 zoneId, int32 instanceId, float safeX, float safeY, float safeZ, float safeHeading, bool lockState, sint16 minStatus, - int16 minLevel, int16 maxLevel, int16 minVersion, int32 defaultLockoutTime, int32 defaultReenterTime, int8 instanceType, int32 numPlayers) { + int16 minLevel, int16 maxLevel, int16 minVersion, int32 defaultLockoutTime, int32 defaultReenterTime, int8 instanceType, int32 numPlayers, bool isCityZone) { if (opt_details) { opt_details->peerId = peerId; opt_details->peerWorldAddress = peerWorldAddress; @@ -122,6 +122,7 @@ void PeerManager::setZonePeerData(ZoneChangeDetails* opt_details, std::string pe opt_details->defaultReenterTime = defaultReenterTime; opt_details->instanceType = instanceType; opt_details->numPlayers = numPlayers; + opt_details->isCityZone = isCityZone; opt_details->zonePtr = nullptr; opt_details->peerAuthorized = false; opt_details->zoneKey = 0; @@ -133,7 +134,7 @@ void PeerManager::setZonePeerData(ZoneChangeDetails* opt_details, std::string pe void PeerManager::setZonePeerDataSelf(ZoneChangeDetails* opt_details, std::string zoneFileName, std::string zoneName, int32 zoneId, int32 instanceId, float safeX, float safeY, float safeZ, float safeHeading, bool lockState, sint16 minStatus, int16 minLevel, int16 maxLevel, int16 minVersion, int32 defaultLockoutTime, int32 defaultReenterTime, int8 instanceType, - int32 numPlayers, void* zonePtr) { + int32 numPlayers, bool isCityZone, void* zonePtr) { if (opt_details) { opt_details->peerId = "self"; opt_details->peerWorldAddress = net.GetWorldAddress(); @@ -158,6 +159,7 @@ void PeerManager::setZonePeerDataSelf(ZoneChangeDetails* opt_details, std::strin opt_details->defaultReenterTime = defaultReenterTime; opt_details->instanceType = instanceType; opt_details->numPlayers = numPlayers; + opt_details->isCityZone = isCityZone; opt_details->zonePtr = zonePtr; opt_details->peerAuthorized = true; opt_details->zoneKey = 0; @@ -167,6 +169,8 @@ void PeerManager::setZonePeerDataSelf(ZoneChangeDetails* opt_details, std::strin } std::string PeerManager::getZonePeerId(const std::string& inc_zone_name, int32 inc_zone_id, int32 inc_instance_id, ZoneChangeDetails* opt_details, bool only_always_loaded) { + bool matchFullZone = false; + std::string fullZoneId = ""; for (auto& [peerId, peer] : peers) { if (peer->healthCheck.status != HealthStatus::OK) continue; @@ -210,10 +214,18 @@ std::string PeerManager::getZonePeerId(const std::string& inc_zone_name, int32 i else if (!instance_zone && inc_zone_name.length() > 0 && strncasecmp(zone_name.c_str(), inc_zone_name.c_str(), inc_zone_name.length()) == 0) { match = true; } + + if(!instance_zone && num_players >= 30 && !city_zone) { + match = false; + setZonePeerData(opt_details, peerId, peer->worldAddr, peer->internalWorldAddr, peer->worldPort, peer->webAddr, peer->webPort, zone_file_name, zone_name, zone_id, instance_id, + safe_x, safe_y, safe_z, safe_heading, lock_state, min_status, min_level, max_level, min_version, default_lockout_time, default_reenter_time, instance_type, num_players, city_zone); + matchFullZone = true; + fullZoneId = peerId; + } if (match) { setZonePeerData(opt_details, peerId, peer->worldAddr, peer->internalWorldAddr, peer->worldPort, peer->webAddr, peer->webPort, zone_file_name, zone_name, zone_id, instance_id, - safe_x, safe_y, safe_z, safe_heading, lock_state, min_status, min_level, max_level, min_version, default_lockout_time, default_reenter_time, instance_type, num_players); + safe_x, safe_y, safe_z, safe_heading, lock_state, min_status, min_level, max_level, min_version, default_lockout_time, default_reenter_time, instance_type, num_players, city_zone); return peerId; } } @@ -223,7 +235,8 @@ std::string PeerManager::getZonePeerId(const std::string& inc_zone_name, int32 i LogWrite(PEERING__ERROR, 0, "Peering", "%s: Error Parsing Zones for %s:%u", __FUNCTION__, peer->webAddr.c_str(), peer->webPort); } } - return ""; + + return fullZoneId; } void PeerManager::handlePrimaryConflict(const std::string& reconnectingPeerId) { diff --git a/source/WorldServer/Web/PeerManager.h b/source/WorldServer/Web/PeerManager.h index 484ce14..b1119cf 100644 --- a/source/WorldServer/Web/PeerManager.h +++ b/source/WorldServer/Web/PeerManager.h @@ -87,6 +87,7 @@ struct ZoneChangeDetails { int32 defaultReenterTime; int8 instanceType; int32 numPlayers; + bool isCityZone; void* zonePtr; bool peerAuthorized; int32 zoneKey; @@ -171,10 +172,10 @@ public: void setZonePeerData(ZoneChangeDetails* opt_details, std::string peerId, std::string peerWorldAddress, std::string peerInternalWorldAddress, int16 peerWorldPort, std::string peerWebAddress, int16 peerWebPort, std::string zoneFileName, std::string zoneName, int32 zoneId, int32 instanceId, float safeX, float safeY, float safeZ, float safeHeading, bool lockState, sint16 minStatus, - int16 minLevel, int16 maxLevel, int16 minVersion, int32 defaultLockoutTime, int32 defaultReenterTime, int8 instanceType, int32 numPlayers); + int16 minLevel, int16 maxLevel, int16 minVersion, int32 defaultLockoutTime, int32 defaultReenterTime, int8 instanceType, int32 numPlayers, bool isCityZone); void setZonePeerDataSelf(ZoneChangeDetails* opt_details, std::string zoneFileName, std::string zoneName, int32 zoneId, int32 instanceId, float safeX, float safeY, float safeZ, float safeHeading, bool lockState, sint16 minStatus, - int16 minLevel, int16 maxLevel, int16 minVersion, int32 defaultLockoutTime, int32 defaultReenterTime, int8 instanceType, int32 numPlayers, void* zonePtr = nullptr); + int16 minLevel, int16 maxLevel, int16 minVersion, int32 defaultLockoutTime, int32 defaultReenterTime, int8 instanceType, int32 numPlayers, bool isCityZone, void* zonePtr = nullptr); bool IsClientConnectedPeer(int32 account_id); std::string GetCharacterPeerId(std::string charName); void SendPeersChannelMessage(int32 group_id, std::string fromName, std::string message, int16 channel, int32 language_id = 0); diff --git a/source/WorldServer/Web/WorldWeb.cpp b/source/WorldServer/Web/WorldWeb.cpp index ca9f00d..b8ee205 100644 --- a/source/WorldServer/Web/WorldWeb.cpp +++ b/source/WorldServer/Web/WorldWeb.cpp @@ -503,6 +503,7 @@ void ZoneList::PopulateZoneList(boost::property_tree::ptree& pt) { zone_pt.put("default_reenter_time", tmp->GetDefaultReenterTime()); zone_pt.put("instance_type", static_cast(tmp->GetInstanceType())); zone_pt.put("always_loaded", tmp->AlwaysLoaded()); + zone_pt.put("duplicated_zone", tmp->DuplicatedZone()); maintree.push_back(std::make_pair("", zone_pt)); } @@ -627,7 +628,7 @@ void World::Web_worldhandle_startzone(const http::request& re int32 instanceId = 0; int32 zoneId = 0; std::string zoneName(""); - bool alwaysLoaded = false; + bool alwaysLoaded = false, duplicatedZone = false; int32 minLevel = 0, maxLevel = 0, avgLevel = 0, firstLevel = 0; if (auto inst_id = json_tree.get_optional("instance_id")) { instanceId = inst_id.get(); @@ -645,6 +646,10 @@ void World::Web_worldhandle_startzone(const http::request& re alwaysLoaded = always_loaded.get(); } + if (auto duplicated_zone = json_tree.get_optional("duplicated_zone")) { + duplicatedZone = duplicated_zone.get(); + } + if (auto level = json_tree.get_optional("min_level")) { minLevel = level.get(); } @@ -665,8 +670,12 @@ void World::Web_worldhandle_startzone(const http::request& re ZoneChangeDetails details; if (instanceId || zoneId || zoneName.length() > 0) { if (!instanceId) { - if ((zone_list.GetZone(&details, zoneId, zoneName, true, false, false, false, false, alwaysLoaded))) + if ((zone_list.GetZone(&details, zoneId, zoneName, true, false, false, false, false, alwaysLoaded, false, duplicatedZone))) { + if(details.zonePtr) { + ((ZoneServer*)details.zonePtr)->SetDuplicatedZone(duplicatedZone); + } success = 1; + } } else { if ((zone_list.GetZoneByInstance(&details, instanceId, zoneId, true, false, false, false, minLevel, maxLevel, avgLevel, firstLevel))) diff --git a/source/WorldServer/World.cpp b/source/WorldServer/World.cpp index c79b23d..f6bcb95 100644 --- a/source/WorldServer/World.cpp +++ b/source/WorldServer/World.cpp @@ -686,10 +686,11 @@ void ZoneList::Remove(ZoneServer* zone) { } } -bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::string opt_zone_name, bool loadZone, bool skip_existing_zones, bool increment_zone, bool check_peers, bool check_instances, bool only_always_loaded, bool skip_self, int32 minLevel, int32 maxLevel, int32 avgLevel, int32 firstLevel) { +bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::string opt_zone_name, bool loadZone, bool skip_existing_zones, bool increment_zone, bool check_peers, bool check_instances, bool only_always_loaded, bool skip_self, bool duplicated_zone, int32 minLevel, int32 maxLevel, int32 avgLevel, int32 firstLevel) { list::iterator zone_iter; ZoneServer* tmp = 0; ZoneServer* ret = 0; + bool hadFullZone = false; if(!skip_existing_zones) { if(!skip_self) { MZoneList.readlock(__FUNCTION__, __LINE__); @@ -706,6 +707,9 @@ bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std:: } break; } + else if(!tmp->IsCityZone()) { + hadFullZone = true; + } } } tmp = nullptr; @@ -715,8 +719,15 @@ bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std:: if(!ret && check_peers) { std::string peerId = peer_manager.getZonePeerId(opt_zone_name, opt_zone_id, 0, zone_details, only_always_loaded); if(peerId.size() > 0) { - LogWrite(WORLD__ERROR, 0, "World", "Peer %s is providing zone %s for zone %s id %u", peerId.c_str(), zone_details->zoneName.c_str(), opt_zone_name.c_str(), opt_zone_id); - return true; + + if(zone_details->instanceType == 0 && zone_details->numPlayers >= 30 && !zone_details->isCityZone) { + LogWrite(WORLD__WARNING, 0, "World", "Peer %s is providing zone %s for zone %s id %u, however the zone is full, omitting result.", peerId.c_str(), zone_details->zoneName.c_str(), opt_zone_name.c_str(), opt_zone_id); + hadFullZone = true; + } + else { + LogWrite(WORLD__INFO, 0, "World", "Peer %s is providing zone %s for zone %s id %u", peerId.c_str(), zone_details->zoneName.c_str(), opt_zone_name.c_str(), opt_zone_id); + return true; + } } } } @@ -738,6 +749,7 @@ bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std:: root.put("zone_name", opt_zone_name); root.put("zone_id", std::to_string(opt_zone_id)); root.put("always_loaded", only_always_loaded); + root.put("duplicated_zone", hadFullZone); root.put("min_level", minLevel); root.put("max_level", maxLevel); @@ -746,19 +758,20 @@ bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std:: std::ostringstream jsonStream; boost::property_tree::write_json(jsonStream, root); std::string jsonPayload = jsonStream.str(); - LogWrite(PEERING__DEBUG, 0, "Peering", "%s: Notify Peer %s StartZone %s (%u), always loaded %u", __FUNCTION__, peer->id.c_str(), opt_zone_name.c_str(), opt_zone_id, only_always_loaded); + LogWrite(PEERING__DEBUG, 0, "Peering", "%s: Notify Peer %s StartZone %s (%u), always loaded %u, had full zone %%u", __FUNCTION__, peer->id.c_str(), opt_zone_name.c_str(), opt_zone_id, only_always_loaded, hadFullZone); peer_https_pool.sendPostRequestToPeerAsync(peer->id, peer->webAddr, std::to_string(peer->webPort), "/startzone", jsonPayload); peer_manager.setZonePeerData(zone_details, peer->id, peer->worldAddr, peer->internalWorldAddr, peer->worldPort, peer->webAddr, peer->webPort, std::string(tmp->GetZoneFile()), std::string(tmp->GetZoneName()), tmp->GetZoneID(), tmp->GetInstanceID(), tmp->GetSafeX(), tmp->GetSafeY(), tmp->GetSafeZ(), tmp->GetSafeHeading(), tmp->GetZoneLockState(), tmp->GetMinimumStatus(), tmp->GetMinimumLevel(), tmp->GetMaximumLevel(), tmp->GetMinimumVersion(), tmp->GetDefaultLockoutTime(), tmp->GetDefaultReenterTime(), - tmp->GetInstanceType(), tmp->NumPlayers()); + tmp->GetInstanceType(), tmp->NumPlayers(), tmp->IsCityZone()); safe_delete(tmp); return true; } else { tmp = new ZoneServer(opt_zone_name.c_str()); database.LoadZoneInfo(tmp, minLevel, maxLevel, avgLevel, firstLevel); + tmp->SetDuplicatedZone(hadFullZone); tmp->Init(); tmp->SetAlwaysLoaded(only_always_loaded); } @@ -770,7 +783,7 @@ bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std:: tmp->GetInstanceID(), tmp->GetSafeX(), tmp->GetSafeY(), tmp->GetSafeZ(), tmp->GetSafeHeading(), tmp->GetZoneLockState(), tmp->GetMinimumStatus(), tmp->GetMinimumLevel(), tmp->GetMaximumLevel(), tmp->GetMinimumVersion(), tmp->GetDefaultLockoutTime(), tmp->GetDefaultReenterTime(), - tmp->GetInstanceType(), tmp->NumPlayers(), tmp); + tmp->GetInstanceType(), tmp->NumPlayers(), tmp->IsCityZone(), tmp); if(zone_details) { zone_details->zonePtr = (void*)tmp; } @@ -837,7 +850,7 @@ bool ZoneList::GetZoneByInstance(ZoneChangeDetails* zone_details, int32 instance instance_id, tmp->GetSafeX(), tmp->GetSafeY(), tmp->GetSafeZ(), tmp->GetSafeHeading(), tmp->GetZoneLockState(), tmp->GetMinimumStatus(), tmp->GetMinimumLevel(), tmp->GetMaximumLevel(), tmp->GetMinimumVersion(), tmp->GetDefaultLockoutTime(), tmp->GetDefaultReenterTime(), - tmp->GetInstanceType(), tmp->NumPlayers()); + tmp->GetInstanceType(), tmp->NumPlayers(), tmp->IsCityZone()); safe_delete(tmp); return true; } @@ -858,7 +871,7 @@ bool ZoneList::GetZoneByInstance(ZoneChangeDetails* zone_details, int32 instance tmp->GetInstanceID(), tmp->GetSafeX(), tmp->GetSafeY(), tmp->GetSafeZ(), tmp->GetSafeHeading(), tmp->GetZoneLockState(), tmp->GetMinimumStatus(), tmp->GetMinimumLevel(), tmp->GetMaximumLevel(), tmp->GetMinimumVersion(), tmp->GetDefaultLockoutTime(), tmp->GetDefaultReenterTime(), - tmp->GetInstanceType(), tmp->NumPlayers(), tmp); + tmp->GetInstanceType(), tmp->NumPlayers(), tmp->IsCityZone(), tmp); zone_details->zonePtr = (void*)tmp; } return (tmp != nullptr) ? true : false; @@ -1010,9 +1023,10 @@ void PeerManager::sendZonePeerList(Client* client) { int32 default_lockout_time = zone.second.get("default_lockout_time"); int32 default_reenter_time = zone.second.get("default_reenter_time"); int8 instance_type = zone.second.get("instance_type"); + bool duplicated_zone = zone.second.get("duplicated_zone") == "true"; - client->Message(CHANNEL_COLOR_YELLOW,"Zone (ID) (InstanceID): %s (%u) (%u), Peer: %s, NumPlayers: %u, Locked: %s, ShuttingDown: %s.",zone_name.c_str(),zone_id, - instance_id,peer->id.c_str(), num_players, lock_state ? "true" : "false", shutting_down ? "true" : "false"); + client->Message(CHANNEL_COLOR_YELLOW,"Zone (ID) (InstanceID): %s (%u) (%u), Peer: %s, NumPlayers: %u, Locked: %s, ShuttingDown: %s, DuplicateZone: %s.",zone_name.c_str(),zone_id, + instance_id,peer->id.c_str(), num_players, lock_state ? "true" : "false", shutting_down ? "true" : "false", duplicated_zone ? "true" : "false"); } } catch (const std::exception& e) { LogWrite(PEERING__ERROR, 0, "Peering", "%s: Zones Parsing Error %s for %s:%u/%s", __FUNCTION__, e.what() ? e.what() : "??", peer->webAddr.c_str(), peer->webPort); diff --git a/source/WorldServer/World.h b/source/WorldServer/World.h index 94a8989..2d823b8 100644 --- a/source/WorldServer/World.h +++ b/source/WorldServer/World.h @@ -419,7 +419,7 @@ class ZoneList { void Add(ZoneServer* zone); void Remove(ZoneServer* zone); - bool GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::string opt_zone_name = "", bool loadZone = true, bool skip_existing_zones = false, bool increment_zone = true, bool check_peers = true, bool check_instances = false, bool only_always_loaded = false, bool skip_self = false, int32 minLevel = 0, int32 maxLevel = 0, int32 avgLevel = 0, int32 firstLevel = 0); + bool GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::string opt_zone_name = "", bool loadZone = true, bool skip_existing_zones = false, bool increment_zone = true, bool check_peers = true, bool check_instances = false, bool only_always_loaded = false, bool skip_self = false, bool duplicated_zone = false, int32 minLevel = 0, int32 maxLevel = 0, int32 avgLevel = 0, int32 firstLevel = 0); bool GetZoneByInstance(ZoneChangeDetails* zone_details, int32 instance_id, int32 zone_id = 0, bool loadZone = true, bool skip_existing_zones = false, bool increment_zone = true, bool check_peers = true, int32 minLevel = 0, int32 maxLevel = 0, int32 avgLevel = 0, int32 firstLevel = 0); bool IsClientConnectedPeer(int32 account_id); diff --git a/source/WorldServer/WorldDatabase.cpp b/source/WorldServer/WorldDatabase.cpp index e73d6be..cc5f5d9 100644 --- a/source/WorldServer/WorldDatabase.cpp +++ b/source/WorldServer/WorldDatabase.cpp @@ -6138,11 +6138,16 @@ map* WorldDatabase::GetPersistedSpawns(int32 zone_id, int8 type) LogWrite(SPAWN__TRACE, 1, "Spawn", "Enter %s", __FUNCTION__); - LogWrite(INSTANCE__DEBUG, 0, "Instance", "Loading persisted spawns for zone_id: %u, spawn_type: %u", zone_id, type); + LogWrite(ZONE__DEBUG, 0, "Zone", "Loading persisted spawns for zone_id: %u, spawn_type: %u", zone_id, type); if( !database_new.Select(&result, "SELECT spawn_location_entry_id, respawn_time FROM persisted_respawns WHERE zone_id = %u AND spawn_type = %u", zone_id, type) ) { - LogWrite(INSTANCE__ERROR, 0, "Instance", "Error in GetInstanceRemovedSpawns() '%s': %i", database_new.GetErrorMsg(), database_new.GetError()); + if(database_new.GetError()) { + LogWrite(ZONE__ERROR, 0, "Zone", "Error in GetPersistedSpawns() '%s': %i", database_new.GetErrorMsg(), database_new.GetError()); + } + else { + + } return ret; } else @@ -6161,13 +6166,13 @@ map* WorldDatabase::GetPersistedSpawns(int32 zone_id, int8 type) */ int32 respawntime = result.GetInt32Str("respawn_time"); - LogWrite(INSTANCE__DEBUG, 5, "Instance", "Found persisted spawn point: %u, respawn time: %u", spawn_location_entry_id, respawntime); + LogWrite(ZONE__ERROR, 5, "Zone", "Found persisted spawn point: %u, respawn time: %u", spawn_location_entry_id, respawntime); ret->insert(make_pair(spawn_location_entry_id, respawntime)); } } else - LogWrite(INSTANCE__DEBUG, 0, "Instance", "No persisted spawns found for zone_id: %u, spawn_type: %u", zone_id, type); + LogWrite(ZONE__ERROR, 0, "Zone", "No persisted spawns found for zone_id: %u, spawn_type: %u", zone_id, type); } diff --git a/source/WorldServer/zoneserver.cpp b/source/WorldServer/zoneserver.cpp index 8586581..08c707f 100644 --- a/source/WorldServer/zoneserver.cpp +++ b/source/WorldServer/zoneserver.cpp @@ -183,6 +183,8 @@ ZoneServer::ZoneServer(const char* name) { groupraidFirstLevel = 0; is_initialized = false; + isInstance = false; + duplicated_zone = false; } typedef map ChangedSpawnMapType; @@ -2045,6 +2047,15 @@ void ZoneServer::CheckRespawns(){ } } +void ZoneServer::SendRespawnTimerList(Client* client){ + MutexMap::iterator itr = respawn_timers.begin(); + client->Message(CHANNEL_FACTION, "Respawn Timers:"); + client->Message(CHANNEL_FACTION, "Location ID : Time Remaining"); + while(itr.Next()){ + client->Message(CHANNEL_FACTION, "%u: %i seconds.", itr->first, (itr->second - Timer::GetCurrentTime2())/1000); + } +} + void ZoneServer::CheckSpawnExpireTimers() { MutexMap::iterator itr = spawn_expire_timers.begin(); while (itr.Next()) { @@ -2516,12 +2527,18 @@ Spawn* ZoneServer::ProcessSpawnLocation(SpawnLocation* spawnlocation, mapentities[i]->spawn_type == SPAWN_ENTRY_TYPE_NPC) + if(spawnlocation->entities[i]->spawn_type == SPAWN_ENTRY_TYPE_NPC) spawnTime = database.CheckSpawnRemoveInfo(instNPCs,spawnlocation->entities[i]->spawn_location_id); else if(spawnlocation->entities[i]->spawn_type == SPAWN_ENTRY_TYPE_OBJECT) spawnTime = database.CheckSpawnRemoveInfo(instObjSpawns,spawnlocation->entities[i]->spawn_location_id); + else if(spawnlocation->entities[i]->spawn_type == SPAWN_ENTRY_TYPE_WIDGET) + spawnTime = database.CheckSpawnRemoveInfo(instWidgetSpawns,spawnlocation->entities[i]->spawn_location_id); + else if(spawnlocation->entities[i]->spawn_type == SPAWN_ENTRY_TYPE_SIGN) + spawnTime = database.CheckSpawnRemoveInfo(instSignSpawns,spawnlocation->entities[i]->spawn_location_id); + else if(spawnlocation->entities[i]->spawn_type == SPAWN_ENTRY_TYPE_GROUNDSPAWN) + spawnTime = database.CheckSpawnRemoveInfo(instGroundSpawns,spawnlocation->entities[i]->spawn_location_id); if(spawnTime == 0) { // don't respawn return nullptr; @@ -2529,7 +2546,7 @@ Spawn* ZoneServer::ProcessSpawnLocation(SpawnLocation* spawnlocation, map 1) { // if not 1, respawn after time AddRespawn(spawnlocation->entities[i]->spawn_location_id, spawnTime); return nullptr; - }*/ + } if (spawnlocation->conditional > 0) { if ((spawnlocation->conditional & SPAWN_CONDITIONAL_DAY) == SPAWN_CONDITIONAL_DAY && isDusk) @@ -8722,12 +8739,20 @@ void ZoneServer::SendFlightPathsPackets(Client* client) { vector::iterator itr2; int32 j = 0; for (itr2 = m_flightPathRoutes[itr->first].begin(); itr2 != m_flightPathRoutes[itr->first].end(); itr2++, j++) { - packet->setSubArrayDataByName("x", (*itr2)->X, i, j); - packet->setSubArrayDataByName("y", (*itr2)->Y, i, j); - packet->setSubArrayDataByName("z", (*itr2)->Z, i, j); + if(client->GetVersion() <= 561) { + std::string fieldNum = std::to_string(i) + "_" + std::to_string(j); + packet->setDataByName(("x" + fieldNum).c_str(), (*itr2)->X); + packet->setDataByName(("y" + fieldNum).c_str(), (*itr2)->Y); + packet->setDataByName(("z" + fieldNum).c_str(), (*itr2)->Z); + } + else { + packet->setSubArrayDataByName("x", (*itr2)->X, i, j); + packet->setSubArrayDataByName("y", (*itr2)->Y, i, j); + packet->setSubArrayDataByName("z", (*itr2)->Z, i, j); + } } } - + packet->PrintPacket(); client->QueuePacket(packet->serialize()); safe_delete(packet); } diff --git a/source/WorldServer/zoneserver.h b/source/WorldServer/zoneserver.h index 344e619..639f70a 100644 --- a/source/WorldServer/zoneserver.h +++ b/source/WorldServer/zoneserver.h @@ -531,8 +531,10 @@ public: inline bool IsCityZone() { return cityzone; } inline bool AlwaysLoaded() { return always_loaded; } + inline bool DuplicatedZone() { return duplicated_zone; } void SetCityZone(bool val) { cityzone = val; } void SetAlwaysLoaded(bool val) { always_loaded = val; } + void SetDuplicatedZone(bool val) { duplicated_zone = val; } int32 NumPlayers() { return pNumPlayers; } void SetMinimumStatus(sint16 minStatus) { minimumStatus = minStatus; } sint16 GetMinimumStatus() { return minimumStatus; } @@ -732,6 +734,8 @@ public: void AddRespawn(Spawn* spawn); void AddRespawn(int32 locationID, int32 respawnTime); + + void SendRespawnTimerList(Client* client); private: #ifndef WIN32 pthread_t ZoneThread; @@ -934,6 +938,7 @@ private: std::atomic is_initialized; bool cityzone; bool always_loaded; + bool duplicated_zone; bool isInstance; std::atomic pNumPlayers;