From d9eeb00dead215f9fd2951d85c09fd9f0341fdd0 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 7 Aug 2019 18:54:53 -0500 Subject: [PATCH] Adjust ghosting algorithm to work much better for super large zones as well --- zone/client_packet.cpp | 6 +-- zone/mob_movement_manager.cpp | 2 +- zone/zone.cpp | 70 +++++++++++++++++++++++++++++++++-- zone/zone.h | 7 +++- 4 files changed, 77 insertions(+), 8 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 688a448eb..4f819e7a4 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4498,7 +4498,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { */ float distance_moved = DistanceNoZ(GetLastPositionBeforeBulkUpdate(), GetPosition()); - bool moved_far_enough_before_bulk_update = distance_moved >= 1200; + bool moved_far_enough_before_bulk_update = distance_moved >= zone->GetNpcPositionUpdateDistance(); bool is_ready_to_update = ( client_zone_wide_full_position_update_timer.Check() || moved_far_enough_before_bulk_update ); @@ -4515,8 +4515,8 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { continue; } - float distance_from_client_to_ignore = zone->GetMaxMovementUpdateRange() - 100; - if (CalculateDistance(entity->GetX(), entity->GetY(), entity->GetZ()) <= distance_from_client_to_ignore) { + float distance_from_client_to_ignore = zone->GetNpcPositionUpdateDistance(); + if (entity->IsMoving() && CalculateDistance(entity->GetX(), entity->GetY(), entity->GetZ()) <= distance_from_client_to_ignore) { continue; } diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp index df1a38168..4bf1663d3 100644 --- a/zone/mob_movement_manager.cpp +++ b/zone/mob_movement_manager.cpp @@ -762,7 +762,7 @@ void MobMovementManager::SendCommandToClients( } else { float short_range = RuleR(Pathing, ShortMovementUpdateRange); - float long_range = zone->GetMaxMovementUpdateRange(); + float long_range = zone->GetNpcPositionUpdateDistance(); for (auto &c : _impl->Clients) { if (single_client && c != single_client) { diff --git a/zone/zone.cpp b/zone/zone.cpp index 2121642bb..d20b2934e 100755 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -55,6 +55,7 @@ #include "zone_config.h" #include "mob_movement_manager.h" #include "npc_scale_manager.h" +#include "../common/data_verification.h" #include #include @@ -864,6 +865,8 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) m_last_ucss_update = 0; mMovementManager = &MobMovementManager::Get(); + + SetNpcPositionUpdateDistance(0); } Zone::~Zone() { @@ -1194,9 +1197,9 @@ uint32 Zone::CountAuth() { bool Zone::Process() { spawn_conditions.Process(); - if(spawn2_timer.Check()) { + if (spawn2_timer.Check()) { - LinkedListIterator iterator(spawn2_list); + LinkedListIterator iterator(spawn2_list); EQEmu::InventoryProfile::CleanDirty(); @@ -1212,10 +1215,15 @@ bool Zone::Process() { } } - if(adv_data && !did_adventure_actions) + if (adv_data && !did_adventure_actions) { DoAdventureActions(); + } + if (GetNpcPositionUpdateDistance() == 0) { + CalculateNpcUpdateDistanceSpread(); + } } + if(initgrids_timer.Check()) { //delayed grid loading stuff. initgrids_timer.Disable(); @@ -2365,3 +2373,59 @@ void Zone::SetUCSServerAvailable(bool ucss_available, uint32 update_timestamp) { if (m_last_ucss_update < update_timestamp) m_ucss_available = ucss_available; } + +int Zone::GetNpcPositionUpdateDistance() const +{ + return npc_position_update_distance; +} + +void Zone::SetNpcPositionUpdateDistance(int in_npc_position_update_distance) +{ + Zone::npc_position_update_distance = in_npc_position_update_distance; +} + +void Zone::CalculateNpcUpdateDistanceSpread() +{ + float max_x = 0; + float max_y = 0; + float min_x = 0; + float min_y = 0; + + auto &mob_list = entity_list.GetMobList(); + + for (auto &it : mob_list) { + Mob *entity = it.second; + if (!entity->IsNPC()) { + continue; + } + + if (entity->GetX() <= min_x) { + min_x = entity->GetX(); + } + + if (entity->GetY() <= min_y) { + min_y = entity->GetY(); + } + + if (entity->GetX() >= max_x) { + max_x = entity->GetX(); + } + + if (entity->GetY() >= max_y) { + max_y = entity->GetY(); + } + } + + int x_spread = int(abs(max_x - min_x)); + int y_spread = int(abs(max_y - min_y)); + int combined_spread = int(abs((x_spread + y_spread) / 2)); + int update_distance = EQEmu::ClampLower(int(combined_spread / 4), int(zone->GetMaxMovementUpdateRange())); + + SetNpcPositionUpdateDistance(update_distance); + + Log(Logs::General, Logs::Debug, + "NPC update spread distance set to [%i] combined_spread [%i]", + update_distance, + combined_spread + ); +} \ No newline at end of file diff --git a/zone/zone.h b/zone/zone.h index a7de25ab4..176fe0cb3 100755 --- a/zone/zone.h +++ b/zone/zone.h @@ -126,6 +126,9 @@ public: bool Process(); bool SaveZoneCFG(); + int GetNpcPositionUpdateDistance() const; + void SetNpcPositionUpdateDistance(int in_npc_position_update_distance); + char *adv_data; const char *GetSpellBlockedMessage(uint32 spell_id, const glm::vec3 &location); @@ -219,6 +222,7 @@ public: void ChangeWeather(); void ClearBlockedSpells(); void ClearNPCTypeCache(int id); + void CalculateNpcUpdateDistanceSpread(); void DelAggroMob() { aggroedmobs--; } void DeleteQGlobal(std::string name, uint32 npcID, uint32 charID, uint32 zoneID); void Despawn(uint32 spawngroupID); @@ -290,7 +294,7 @@ public: */ find_replace(message, std::string("%"), std::string(".")); - if (message.find("\n") != std::string::npos) { + if (message.find('\n') != std::string::npos) { auto message_split = SplitString(message, '\n'); entity_list.MessageStatus( 0, @@ -345,6 +349,7 @@ private: glm::vec4 m_Graveyard; int default_ruleset; int totalBS; + int npc_position_update_distance; int32 aggroedmobs; uint8 zone_type; uint16 instanceversion;