From ff4e549ec0d34480eff01043bd10276f130a2905 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 26 Jul 2019 18:20:01 -0400 Subject: [PATCH 01/17] Fix for cmake 'zlib not found' defaulting to internal libs not working issue [skip ci] --- CMakeLists.txt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d58e2bd1f..6f3a25301 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -326,14 +326,10 @@ IF(ZLIB_FOUND) SET(SERVER_LIBS ${SERVER_LIBS} ${ZLIB_LIBRARY}) ENDIF() ELSE() - # NOTE: This processing chain is broken. - # Path "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" is added to ${SERVER_LIBS}..but, the current CMake process does not - # generate the "${CMAKE_CURRENT_SOURCE_DIR}/build/lib/zlibng" and create the required "zconf.h" file. A path to - # a valid ZLIB package is required to trigger this process. "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng/zconf.h" is not - # valid due to the extension name change to "../zlibng/zconf.h.in" during the ZLIB project creation process. + MESSAGE(STATUS "Could NOT find ZLIB - using ZLIBSTATIC package.") + SET(EQEMU_BUILD_ZLIB ON) INCLUDE_DIRECTORIES(BEFORE SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng") SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic") - MESSAGE(STATUS "Could NOT find ZLIB - using ZLIBSTATIC package.") ENDIF() IF(WIN32) From 979c8190757a1346ffda7385457136c3f23166bc Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Mon, 29 Jul 2019 17:28:58 -0500 Subject: [PATCH 02/17] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index e1126241c..5e4f919fe 100644 --- a/README.md +++ b/README.md @@ -70,3 +70,9 @@ forum, although pull requests will be much quicker and easier on all parties. * GPL Perl - GPL / ActiveState (under the assumption that this is a free project) * CPPUnit - GLP StringUtilities - Apache * LUA - MIT + +## Contributors + + + + From 9d9374ec194f96ef6ba1b3df017bb36e96c32cc6 Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Sat, 3 Aug 2019 01:32:56 -0500 Subject: [PATCH 03/17] Fix #gmzone to actually create bucket flags via version --- zone/command.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/command.cpp b/zone/command.cpp index bd5aa71c9..659acd1a1 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -4490,7 +4490,7 @@ void command_gmzone(Client *c, const Seperator *sep) identifier = sep->arg[3]; } - std::string bucket_key = StringFormat("%s-%s-instance", zone_short_name, identifier.c_str()); + std::string bucket_key = StringFormat("%s-%s-%u-instance", zone_short_name, zone_version, identifier.c_str()); std::string existing_zone_instance = DataBucket::GetData(bucket_key); if (existing_zone_instance.length() > 0) { From f5cfec529e97c08078c0f0b30a5d7d692d7fe046 Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Sat, 3 Aug 2019 04:10:40 -0500 Subject: [PATCH 04/17] Fix format ordering --- zone/command.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/command.cpp b/zone/command.cpp index 659acd1a1..6dda38f71 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -4490,7 +4490,7 @@ void command_gmzone(Client *c, const Seperator *sep) identifier = sep->arg[3]; } - std::string bucket_key = StringFormat("%s-%s-%u-instance", zone_short_name, zone_version, identifier.c_str()); + std::string bucket_key = StringFormat("%s-%s-%u-instance", zone_short_name, identifier.c_str(), zone_version); std::string existing_zone_instance = DataBucket::GetData(bucket_key); if (existing_zone_instance.length() > 0) { From 4aa8cecc55eba244e5fc2b721978ae5cfa660c49 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 4 Aug 2019 22:36:24 -0400 Subject: [PATCH 05/17] Fix for SoF client not being able to login --- common/patches/sof.cpp | 6 ++++++ common/patches/sof_limits.h | 4 ++++ common/patches/sof_structs.h | 6 +++--- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 7569b4c5d..bb310a76c 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1116,7 +1116,10 @@ namespace SoF } OUT(deity); OUT(intoxication); + OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT); + eq->spellSlotRefresh[9] = 0; // 10th slot is not valid in this release + OUT(abilitySlotRefresh); OUT(points); // Relocation Test // OUT(unknown0166[4]); @@ -1177,7 +1180,10 @@ namespace SoF } // OUT(unknown4184[128]); + OUT_array(mem_spells, spells::SPELL_GEM_COUNT); + eq->mem_spells[9] = 0xFFFFFFFFU; // 10th slot is not valid in this release + // OUT(unknown04396[32]); OUT(platinum); OUT(gold); diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 399ff8c1a..a03676f2d 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -328,7 +328,11 @@ namespace SoF const int SPELL_ID_MAX = 15999; const int SPELLBOOK_SIZE = 480; + // Be careful not to confuse these two..SoF disc release has a special requirement... + // - The number of available spell gems HAS NOT increased from 9 at this point + // - The profile allocation HAS increased to 10 at this point const int SPELL_GEM_COUNT = static_cast(CastingSlot::MaxGems); + const int SPELL_GEM_PROFILE_SIZE = 10; // special case declaration const int LONG_BUFFS = 25; const int SHORT_BUFFS = 15; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 93b185e23..4d4a591e1 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -885,7 +885,7 @@ struct PlayerProfile_Struct //23576 Octets /*00060*/ BindStruct binds[5]; // Bind points (primary is first) /*00160*/ uint32 deity; // deity /*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?) -/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_COUNT]; // Refresh time (millis) - 4 Octets Each +/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_PROFILE_SIZE]; // Refresh time (millis) - 4 Octets Each /*00208*/ uint32 abilitySlotRefresh; /*00212*/ uint8 haircolor; // Player hair color /*00213*/ uint8 beardcolor; // Player beard color @@ -912,7 +912,7 @@ struct PlayerProfile_Struct //23576 Octets /*04173*/ uint8 unknown02264[147]; // was [139] /*04312*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 480 = 60 pages /*06232*/ uint8 unknown4184[128]; // was [136] -/*06396*/ uint32 mem_spells[spells::SPELL_GEM_COUNT]; // List of spells memorized +/*06396*/ uint32 mem_spells[spells::SPELL_GEM_PROFILE_SIZE]; // List of spells memorized /*06436*/ uint8 unknown04396[28]; //#### uint8 unknown04396[32]; in Titanium ####[28] /*06464*/ uint32 platinum; // Platinum Pieces on player /*06468*/ uint32 gold; // Gold Pieces on player @@ -3768,7 +3768,7 @@ struct AnnoyingZoneUnknown_Struct { }; struct LoadSpellSet_Struct { - uint32 spell[spells::SPELL_GEM_COUNT]; + uint32 spell[spells::SPELL_GEM_PROFILE_SIZE]; uint32 unknown; }; From 8065cdb89dea85d1c755c707c4b5e5d105f18849 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 4 Aug 2019 22:54:22 -0400 Subject: [PATCH 06/17] Give Erudites their head coverings back (forced until we can sort out the packet building process...) --- zone/mob.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index ca844d459..3a307bf3f 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1128,7 +1128,10 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) UpdateActiveLight(); ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive]; - ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0; + if (IsNPC() && race == ERUDITE) + ns->spawn.showhelm = 1; + else + ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0; ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players ns->spawn.NPC = IsClient() ? 0 : 1; From b117be29fb94828e2c0d0ddb81ff6afbab1c0cfd Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 6 Aug 2019 01:59:54 -0500 Subject: [PATCH 07/17] Movement code readability --- .../submodules/libuv/CTestTestfile.cmake | 6 + zone/mob_movement_manager.cpp | 885 +++++++++++------- zone/mob_movement_manager.h | 26 +- 3 files changed, 569 insertions(+), 348 deletions(-) create mode 100644 cmake-build-debug/submodules/libuv/CTestTestfile.cmake diff --git a/cmake-build-debug/submodules/libuv/CTestTestfile.cmake b/cmake-build-debug/submodules/libuv/CTestTestfile.cmake new file mode 100644 index 000000000..22e3caa8a --- /dev/null +++ b/cmake-build-debug/submodules/libuv/CTestTestfile.cmake @@ -0,0 +1,6 @@ +# CMake generated Testfile for +# Source directory: /Users/cmiles/code/eqemu-docker-cloud/code/submodules/libuv +# Build directory: /Users/cmiles/code/eqemu-docker-cloud/code/cmake-build-debug/submodules/libuv +# +# This file includes the relevant testing commands required for +# testing this directory and lists subdirectories to be tested as well. diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp index 1fcc19187..398cd9c2a 100644 --- a/zone/mob_movement_manager.cpp +++ b/zone/mob_movement_manager.cpp @@ -14,40 +14,41 @@ #include extern double frame_time; -extern Zone *zone; +extern Zone *zone; -class IMovementCommand -{ +class IMovementCommand { public: IMovementCommand() = default; virtual ~IMovementCommand() = default; - virtual bool Process(MobMovementManager *mgr, Mob *m) = 0; + virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob) = 0; virtual bool Started() const = 0; }; -class RotateToCommand : public IMovementCommand -{ +class RotateToCommand : public IMovementCommand { public: - RotateToCommand(double rotate_to, double dir, MobMovementMode mode) { - m_rotate_to = rotate_to; - m_rotate_to_dir = dir; + RotateToCommand(double rotate_to, double dir, MobMovementMode mode) + { + m_rotate_to = rotate_to; + m_rotate_to_dir = dir; m_rotate_to_mode = mode; - m_started = false; + m_started = false; } - virtual ~RotateToCommand() { + virtual ~RotateToCommand() + { } - virtual bool Process(MobMovementManager *mgr, Mob *m) { - if (!m->IsAIControlled()) { + virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob) + { + if (!mob->IsAIControlled()) { return true; } - auto rotate_to_speed = m_rotate_to_mode == MovementRunning ? 200.0 : 16.0; //todo: get this from mob + auto rotate_to_speed = m_rotate_to_mode == MovementRunning ? 200.0 : 16.0; //todo: get this from mob - auto from = FixHeading(m->GetHeading()); - auto to = FixHeading(m_rotate_to); + auto from = FixHeading(mob->GetHeading()); + auto to = FixHeading(m_rotate_to); auto diff = to - from; while (diff < -256.0) { @@ -62,265 +63,282 @@ public: if (!m_started) { m_started = true; - m->SetMoving(true); - + mob->SetMoving(true); + if (dist > 15.0f && rotate_to_speed > 0.0 && rotate_to_speed <= 25.0) { //send basic rotation - mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, m_rotate_to_dir * rotate_to_speed, 0, ClientRangeClose); + mob_movement_manager->SendCommandToClients( + mob, + 0.0, + 0.0, + 0.0, + m_rotate_to_dir * rotate_to_speed, + 0, + ClientRangeClose + ); } } - + auto td = rotate_to_speed * 19.0 * frame_time; - + if (td >= dist) { - m->SetHeading(to); - m->SetMoving(false); - mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeCloseMedium); + mob->SetHeading(to); + mob->SetMoving(false); + mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeCloseMedium); return true; } - + from += td * m_rotate_to_dir; - m->SetHeading(FixHeading(from)); + mob->SetHeading(FixHeading(from)); return false; } - virtual bool Started() const { + virtual bool Started() const + { return m_started; } private: - double m_rotate_to; - double m_rotate_to_dir; + double m_rotate_to; + double m_rotate_to_dir; MobMovementMode m_rotate_to_mode; - bool m_started; + bool m_started; }; -class MoveToCommand : public IMovementCommand -{ +class MoveToCommand : public IMovementCommand { public: - MoveToCommand(float x, float y, float z, MobMovementMode mode) { + MoveToCommand(float x, float y, float z, MobMovementMode mob_movement_mode) + { m_distance_moved_since_correction = 0.0; - m_move_to_x = x; - m_move_to_y = y; - m_move_to_z = z; - m_move_to_mode = mode; - m_last_sent_time = 0.0; - m_last_sent_speed = 0; - m_started = false; - m_total_h_dist = 0.0; - m_total_v_dist = 0.0; + m_move_to_x = x; + m_move_to_y = y; + m_move_to_z = z; + m_move_to_mode = mob_movement_mode; + m_last_sent_time = 0.0; + m_last_sent_speed = 0; + m_started = false; + m_total_h_dist = 0.0; + m_total_v_dist = 0.0; } - virtual ~MoveToCommand() { + virtual ~MoveToCommand() + { } - virtual bool Process(MobMovementManager *mgr, Mob *m) { - if (!m->IsAIControlled()) { + /** + * @param mob_movement_manager + * @param mob + * @return + */ + virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob) + { + if (!mob->IsAIControlled()) { return true; } //Send a movement packet when you start moving - double current_time = static_cast(Timer::GetCurrentTime()) / 1000.0; - int current_speed = 0; + double current_time = static_cast(Timer::GetCurrentTime()) / 1000.0; + int current_speed = 0; if (m_move_to_mode == MovementRunning) { - if (m->IsFeared()) { - current_speed = m->GetFearSpeed(); + if (mob->IsFeared()) { + current_speed = mob->GetFearSpeed(); } else { - current_speed = m->GetRunspeed(); + current_speed = mob->GetRunspeed(); } } else { - current_speed = m->GetWalkspeed(); + current_speed = mob->GetWalkspeed(); } if (!m_started) { m_started = true; //rotate to the point - m->SetMoving(true); - m->SetHeading(m->CalculateHeadingToTarget(m_move_to_x, m_move_to_y)); + mob->SetMoving(true); + mob->SetHeading(mob->CalculateHeadingToTarget(m_move_to_x, m_move_to_y)); m_last_sent_speed = current_speed; - m_last_sent_time = current_time; - m_total_h_dist = DistanceNoZ(m->GetPosition(), glm::vec4(m_move_to_x, m_move_to_y, 0.0f, 0.0f)); - m_total_v_dist = m_move_to_z - m->GetZ(); - mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium); + m_last_sent_time = current_time; + m_total_h_dist = DistanceNoZ(mob->GetPosition(), glm::vec4(m_move_to_x, m_move_to_y, 0.0f, 0.0f)); + m_total_v_dist = m_move_to_z - mob->GetZ(); + mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium); } //When speed changes if (current_speed != m_last_sent_speed) { if (RuleB(Map, FixZWhenPathing)) { - m->FixZ(); + mob->FixZ(); } m_distance_moved_since_correction = 0.0; m_last_sent_speed = current_speed; - m_last_sent_time = current_time; - mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium); + m_last_sent_time = current_time; + mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium); } //If x seconds have passed without sending an update. if (current_time - m_last_sent_time >= 5.0) { if (RuleB(Map, FixZWhenPathing)) { - m->FixZ(); + mob->FixZ(); } m_distance_moved_since_correction = 0.0; m_last_sent_speed = current_speed; - m_last_sent_time = current_time; - mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium); + m_last_sent_time = current_time; + mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium); } - auto &p = m->GetPosition(); + auto &p = mob->GetPosition(); glm::vec2 tar(m_move_to_x, m_move_to_y); glm::vec2 pos(p.x, p.y); - double len = glm::distance(pos, tar); + double len = glm::distance(pos, tar); if (len == 0) { return true; } - m->SetMoved(true); + mob->SetMoved(true); - glm::vec2 dir = tar - pos; - glm::vec2 ndir = glm::normalize(dir); - double distance_moved = frame_time * current_speed * 0.4f * 1.45f; + glm::vec2 dir = tar - pos; + glm::vec2 ndir = glm::normalize(dir); + double distance_moved = frame_time * current_speed * 0.4f * 1.45f; - if (distance_moved > len) { - if (m->IsNPC()) { - entity_list.ProcessMove(m->CastToNPC(), m_move_to_x, m_move_to_y, m_move_to_z); + if (distance_moved > len) { + if (mob->IsNPC()) { + entity_list.ProcessMove(mob->CastToNPC(), m_move_to_x, m_move_to_y, m_move_to_z); } - m->SetPosition(m_move_to_x, m_move_to_y, m_move_to_z); - + mob->SetPosition(m_move_to_x, m_move_to_y, m_move_to_z); + if (RuleB(Map, FixZWhenPathing)) { - m->FixZ(); + mob->FixZ(); } return true; } else { glm::vec2 npos = pos + (ndir * static_cast(distance_moved)); - + len -= distance_moved; double total_distance_traveled = m_total_h_dist - len; - double start_z = m_move_to_z - m_total_v_dist; - double z_at_pos = start_z + (m_total_v_dist * (total_distance_traveled / m_total_h_dist)); + double start_z = m_move_to_z - m_total_v_dist; + double z_at_pos = start_z + (m_total_v_dist * (total_distance_traveled / m_total_h_dist)); - if (m->IsNPC()) { - entity_list.ProcessMove(m->CastToNPC(), npos.x, npos.y, z_at_pos); + if (mob->IsNPC()) { + entity_list.ProcessMove(mob->CastToNPC(), npos.x, npos.y, z_at_pos); } - m->SetPosition(npos.x, npos.y, z_at_pos); + mob->SetPosition(npos.x, npos.y, z_at_pos); if (RuleB(Map, FixZWhenPathing)) { m_distance_moved_since_correction += distance_moved; if (m_distance_moved_since_correction > RuleR(Map, DistanceCanTravelBeforeAdjustment)) { m_distance_moved_since_correction = 0.0; - m->FixZ(); + mob->FixZ(); } } } - + return false; } - virtual bool Started() const { + virtual bool Started() const + { return m_started; } protected: - double m_distance_moved_since_correction; - double m_move_to_x; - double m_move_to_y; - double m_move_to_z; + double m_distance_moved_since_correction; + double m_move_to_x; + double m_move_to_y; + double m_move_to_z; MobMovementMode m_move_to_mode; - bool m_started; + bool m_started; double m_last_sent_time; - int m_last_sent_speed; + int m_last_sent_speed; double m_total_h_dist; double m_total_v_dist; }; -class SwimToCommand : public MoveToCommand -{ +class SwimToCommand : public MoveToCommand { public: - SwimToCommand(float x, float y, float z, MobMovementMode mode) : MoveToCommand(x, y, z, mode) { + SwimToCommand(float x, float y, float z, MobMovementMode mode) : MoveToCommand(x, y, z, mode) + { } - virtual bool Process(MobMovementManager *mgr, Mob *m) + virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob) { - if (!m->IsAIControlled()) { + if (!mob->IsAIControlled()) { return true; } - //Send a movement packet when you start moving - double current_time = static_cast(Timer::GetCurrentTime()) / 1000.0; - int current_speed = 0; + //Send a movement packet when you start moving + double current_time = static_cast(Timer::GetCurrentTime()) / 1000.0; + int current_speed = 0; if (m_move_to_mode == MovementRunning) { - if (m->IsFeared()) { - current_speed = m->GetFearSpeed(); + if (mob->IsFeared()) { + current_speed = mob->GetFearSpeed(); } else { - current_speed = m->GetRunspeed(); + current_speed = mob->GetRunspeed(); } } else { - current_speed = m->GetWalkspeed(); + current_speed = mob->GetWalkspeed(); } if (!m_started) { m_started = true; //rotate to the point - m->SetMoving(true); - m->SetHeading(m->CalculateHeadingToTarget(m_move_to_x, m_move_to_y)); + mob->SetMoving(true); + mob->SetHeading(mob->CalculateHeadingToTarget(m_move_to_x, m_move_to_y)); m_last_sent_speed = current_speed; - m_last_sent_time = current_time; - m_total_h_dist = DistanceNoZ(m->GetPosition(), glm::vec4(m_move_to_x, m_move_to_y, 0.0f, 0.0f)); - m_total_v_dist = m_move_to_z - m->GetZ(); - mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium); + m_last_sent_time = current_time; + m_total_h_dist = DistanceNoZ(mob->GetPosition(), glm::vec4(m_move_to_x, m_move_to_y, 0.0f, 0.0f)); + m_total_v_dist = m_move_to_z - mob->GetZ(); + mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium); } //When speed changes if (current_speed != m_last_sent_speed) { m_last_sent_speed = current_speed; - m_last_sent_time = current_time; - mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium); + m_last_sent_time = current_time; + mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium); } //If x seconds have passed without sending an update. if (current_time - m_last_sent_time >= 1.5) { m_last_sent_speed = current_speed; - m_last_sent_time = current_time; - mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium); + m_last_sent_time = current_time; + mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium); } - auto &p = m->GetPosition(); + auto &p = mob->GetPosition(); glm::vec2 tar(m_move_to_x, m_move_to_y); glm::vec2 pos(p.x, p.y); - double len = glm::distance(pos, tar); + double len = glm::distance(pos, tar); if (len == 0) { return true; } - m->SetMoved(true); + mob->SetMoved(true); - glm::vec2 dir = tar - pos; - glm::vec2 ndir = glm::normalize(dir); - double distance_moved = frame_time * current_speed * 0.4f * 1.45f; + glm::vec2 dir = tar - pos; + glm::vec2 ndir = glm::normalize(dir); + double distance_moved = frame_time * current_speed * 0.4f * 1.45f; if (distance_moved > len) { - if (m->IsNPC()) { - entity_list.ProcessMove(m->CastToNPC(), m_move_to_x, m_move_to_y, m_move_to_z); + if (mob->IsNPC()) { + entity_list.ProcessMove(mob->CastToNPC(), m_move_to_x, m_move_to_y, m_move_to_z); } - m->SetPosition(m_move_to_x, m_move_to_y, m_move_to_z); + mob->SetPosition(m_move_to_x, m_move_to_y, m_move_to_z); return true; } else { @@ -328,51 +346,54 @@ public: len -= distance_moved; double total_distance_traveled = m_total_h_dist - len; - double start_z = m_move_to_z - m_total_v_dist; - double z_at_pos = start_z + (m_total_v_dist * (total_distance_traveled / m_total_h_dist)); + double start_z = m_move_to_z - m_total_v_dist; + double z_at_pos = start_z + (m_total_v_dist * (total_distance_traveled / m_total_h_dist)); - if (m->IsNPC()) { - entity_list.ProcessMove(m->CastToNPC(), npos.x, npos.y, z_at_pos); + if (mob->IsNPC()) { + entity_list.ProcessMove(mob->CastToNPC(), npos.x, npos.y, z_at_pos); } - m->SetPosition(npos.x, npos.y, z_at_pos); + mob->SetPosition(npos.x, npos.y, z_at_pos); } return false; } }; -class TeleportToCommand : public IMovementCommand -{ +class TeleportToCommand : public IMovementCommand { public: - TeleportToCommand(float x, float y, float z, float heading) { - m_teleport_to_x = x; - m_teleport_to_y = y; - m_teleport_to_z = z; + TeleportToCommand(float x, float y, float z, float heading) + { + m_teleport_to_x = x; + m_teleport_to_y = y; + m_teleport_to_z = z; m_teleport_to_heading = heading; } - virtual ~TeleportToCommand() { + virtual ~TeleportToCommand() + { } - virtual bool Process(MobMovementManager *mgr, Mob *m) { - if (!m->IsAIControlled()) { + virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob) + { + if (!mob->IsAIControlled()) { return true; } - if (m->IsNPC()) { - entity_list.ProcessMove(m->CastToNPC(), m_teleport_to_x, m_teleport_to_y, m_teleport_to_z); + if (mob->IsNPC()) { + entity_list.ProcessMove(mob->CastToNPC(), m_teleport_to_x, m_teleport_to_y, m_teleport_to_z); } - m->SetPosition(m_teleport_to_x, m_teleport_to_y, m_teleport_to_z); - m->SetHeading(mgr->FixHeading(m_teleport_to_heading)); - mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny); + mob->SetPosition(m_teleport_to_x, m_teleport_to_y, m_teleport_to_z); + mob->SetHeading(mob_movement_manager->FixHeading(m_teleport_to_heading)); + mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny); return true; } - virtual bool Started() const { + virtual bool Started() const + { return false; } @@ -384,93 +405,99 @@ private: double m_teleport_to_heading; }; -class StopMovingCommand : public IMovementCommand -{ +class StopMovingCommand : public IMovementCommand { public: - StopMovingCommand() { + StopMovingCommand() + { } - virtual ~StopMovingCommand() { + virtual ~StopMovingCommand() + { } - virtual bool Process(MobMovementManager *mgr, Mob *m) { - if (!m->IsAIControlled()) { + virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob) + { + if (!mob->IsAIControlled()) { return true; } - if (m->IsMoving()) { - m->SetMoving(false); + if (mob->IsMoving()) { + mob->SetMoving(false); if (RuleB(Map, FixZWhenPathing)) { - m->FixZ(); + mob->FixZ(); } - mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeCloseMedium); + mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeCloseMedium); } return true; } - virtual bool Started() const { + virtual bool Started() const + { return false; } }; -class EvadeCombatCommand : public IMovementCommand -{ +class EvadeCombatCommand : public IMovementCommand { public: - EvadeCombatCommand() { + EvadeCombatCommand() + { } - virtual ~EvadeCombatCommand() { + virtual ~EvadeCombatCommand() + { } - virtual bool Process(MobMovementManager *mgr, Mob *m) { - if (!m->IsAIControlled()) { + virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob) + { + if (!mob->IsAIControlled()) { return true; } - if (m->IsMoving()) { - m->SetMoving(false); - mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeCloseMedium); + if (mob->IsMoving()) { + mob->SetMoving(false); + mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeCloseMedium); } - m->BuffFadeAll(); - m->WipeHateList(); - m->Heal(); + mob->BuffFadeAll(); + mob->WipeHateList(); + mob->Heal(); return true; } - virtual bool Started() const { + virtual bool Started() const + { return false; } }; -struct MovementStats -{ - MovementStats() { - LastResetTime = static_cast(Timer::GetCurrentTime()) / 1000.0; - TotalSent = 0ULL; +struct MovementStats { + MovementStats() + { + LastResetTime = static_cast(Timer::GetCurrentTime()) / 1000.0; + TotalSent = 0ULL; TotalSentMovement = 0ULL; TotalSentPosition = 0ULL; - TotalSentHeading = 0ULL; + TotalSentHeading = 0ULL; } - double LastResetTime; + double LastResetTime; uint64_t TotalSent; uint64_t TotalSentMovement; uint64_t TotalSentPosition; uint64_t TotalSentHeading; }; -struct NavigateTo -{ - NavigateTo() { - navigate_to_x = 0.0; - navigate_to_y = 0.0; - navigate_to_z = 0.0; +struct NavigateTo { + NavigateTo() + { + navigate_to_x = 0.0; + navigate_to_y = 0.0; + navigate_to_z = 0.0; navigate_to_heading = 0.0; - last_set_time = 0.0; + last_set_time = 0.0; } double navigate_to_x; @@ -480,13 +507,13 @@ struct NavigateTo double last_set_time; }; -struct MobMovementEntry -{ +struct MobMovementEntry { std::deque> Commands; - NavigateTo NavTo; + NavigateTo NavTo; }; -void AdjustRoute(std::list &nodes, Mob *who) { +void AdjustRoute(std::list &nodes, Mob *who) +{ if (!zone->HasMap() || !zone->HasWaterMap()) { return; } @@ -494,7 +521,7 @@ void AdjustRoute(std::list &nodes, Mob *who) { auto offset = who->GetZOffset(); for (auto &node : nodes) { - if(!zone->watermap->InLiquid(node.pos)) { + if (!zone->watermap->InLiquid(node.pos)) { auto best_z = zone->zonemap->FindBestZ(node.pos, nullptr); if (best_z != BEST_Z_INVALID) { node.pos.z = best_z + offset; @@ -503,11 +530,10 @@ void AdjustRoute(std::list &nodes, Mob *who) { } } -struct MobMovementManager::Implementation -{ - std::map Entries; - std::vector Clients; - MovementStats Stats; +struct MobMovementManager::Implementation { + std::map Entries; + std::vector Clients; + MovementStats Stats; }; MobMovementManager::MobMovementManager() @@ -522,12 +548,12 @@ MobMovementManager::~MobMovementManager() void MobMovementManager::Process() { for (auto &iter : _impl->Entries) { - auto &ent = iter.second; + auto &ent = iter.second; auto &commands = ent.Commands; while (true != commands.empty()) { auto &cmd = commands.front(); - auto r = cmd->Process(this, iter.first); + auto r = cmd->Process(this, iter.first); if (true != r) { break; @@ -538,35 +564,49 @@ void MobMovementManager::Process() } } -void MobMovementManager::AddMob(Mob *m) +void MobMovementManager::AddMob(Mob *mob) { - _impl->Entries.insert(std::make_pair(m, MobMovementEntry())); + _impl->Entries.insert(std::make_pair(mob, MobMovementEntry())); } -void MobMovementManager::RemoveMob(Mob *m) +/** + * @param mob + */ +void MobMovementManager::RemoveMob(Mob *mob) { - _impl->Entries.erase(m); + _impl->Entries.erase(mob); } -void MobMovementManager::AddClient(Client *c) +/** + * @param client + */ +void MobMovementManager::AddClient(Client *client) { - _impl->Clients.push_back(c); + _impl->Clients.push_back(client); } -void MobMovementManager::RemoveClient(Client *c) +/** + * @param client + */ +void MobMovementManager::RemoveClient(Client *client) { auto iter = _impl->Clients.begin(); while (iter != _impl->Clients.end()) { - if (c == *iter) { + if (client == *iter) { _impl->Clients.erase(iter); return; } - + ++iter; } } -void MobMovementManager::RotateTo(Mob *who, float to, MobMovementMode mode) +/** + * @param who + * @param to + * @param mob_movement_mode + */ +void MobMovementManager::RotateTo(Mob *who, float to, MobMovementMode mob_movement_mode) { auto iter = _impl->Entries.find(who); auto &ent = (*iter); @@ -574,20 +614,34 @@ void MobMovementManager::RotateTo(Mob *who, float to, MobMovementMode mode) if (true != ent.second.Commands.empty()) { return; } - - PushRotateTo(ent.second, who, to, mode); + + PushRotateTo(ent.second, who, to, mob_movement_mode); } +/** + * @param who + * @param x + * @param y + * @param z + * @param heading + */ void MobMovementManager::Teleport(Mob *who, float x, float y, float z, float heading) { auto iter = _impl->Entries.find(who); auto &ent = (*iter); - + ent.second.Commands.clear(); PushTeleportTo(ent.second, x, y, z, heading); } +/** + * @param who + * @param x + * @param y + * @param z + * @param mode + */ void MobMovementManager::NavigateTo(Mob *who, float x, float y, float z, MobMovementMode mode) { if (IsPositionEqualWithinCertainZ(glm::vec3(x, y, z), glm::vec3(who->GetX(), who->GetY(), who->GetZ()), 6.0f)) { @@ -601,8 +655,13 @@ void MobMovementManager::NavigateTo(Mob *who, float x, float y, float z, MobMove double current_time = static_cast(Timer::GetCurrentTime()) / 1000.0; if ((current_time - nav.last_set_time) > 0.5) { //Can potentially recalc - - auto within = IsPositionWithinSimpleCylinder(glm::vec3(x, y, z), glm::vec3(nav.navigate_to_x, nav.navigate_to_y, nav.navigate_to_z), 1.5f, 6.0f); + + auto within = IsPositionWithinSimpleCylinder( + glm::vec3(x, y, z), + glm::vec3(nav.navigate_to_x, nav.navigate_to_y, nav.navigate_to_z), + 1.5f, + 6.0f + ); auto heading_match = IsHeadingEqual(0.0, nav.navigate_to_heading); if (false == within || false == heading_match || ent.second.Commands.size() == 0) { @@ -610,23 +669,27 @@ void MobMovementManager::NavigateTo(Mob *who, float x, float y, float z, MobMove //Path is no longer valid, calculate a new path UpdatePath(who, x, y, z, mode); - nav.navigate_to_x = x; - nav.navigate_to_y = y; - nav.navigate_to_z = z; + nav.navigate_to_x = x; + nav.navigate_to_y = y; + nav.navigate_to_z = z; nav.navigate_to_heading = 0.0; - nav.last_set_time = current_time; + nav.last_set_time = current_time; } } } -void MobMovementManager::StopNavigation(Mob *who) { +/** + * @param who + */ +void MobMovementManager::StopNavigation(Mob *who) +{ auto iter = _impl->Entries.find(who); auto &ent = (*iter); auto &nav = ent.second.NavTo; - nav.navigate_to_x = 0.0; - nav.navigate_to_y = 0.0; - nav.navigate_to_z = 0.0; + nav.navigate_to_x = 0.0; + nav.navigate_to_y = 0.0; + nav.navigate_to_z = 0.0; nav.navigate_to_heading = 0.0; if (true == ent.second.Commands.empty()) { @@ -643,15 +706,33 @@ void MobMovementManager::StopNavigation(Mob *who) { PushStopMoving(ent.second); } -void MobMovementManager::SendCommandToClients(Mob *m, float dx, float dy, float dz, float dh, int anim, ClientRange range) +/** + * @param mob + * @param delta_x + * @param delta_y + * @param delta_z + * @param delta_heading + * @param anim + * @param range + */ +void MobMovementManager::SendCommandToClients( + Mob *mob, + float delta_x, + float delta_y, + float delta_z, + float delta_heading, + int anim, + ClientRange range +) { if (range == ClientRangeNone) { return; } EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); - PlayerPositionUpdateServer_Struct *spu = (PlayerPositionUpdateServer_Struct*)outapp.pBuffer; - FillCommandStruct(spu, m, dx, dy, dz, dh, anim); + auto *spu = (PlayerPositionUpdateServer_Struct *) outapp.pBuffer; + + FillCommandStruct(spu, mob, delta_x, delta_y, delta_z, delta_heading, anim); if (range == ClientRangeAny) { for (auto &c : _impl->Clients) { @@ -660,7 +741,7 @@ void MobMovementManager::SendCommandToClients(Mob *m, float dx, float dy, float if (anim != 0) { _impl->Stats.TotalSentMovement++; } - else if (dh != 0) { + else if (delta_heading != 0) { _impl->Stats.TotalSentHeading++; } else { @@ -672,26 +753,26 @@ void MobMovementManager::SendCommandToClients(Mob *m, float dx, float dy, float } else { float short_range = RuleR(Pathing, ShortMovementUpdateRange); - float long_range = zone->GetMaxMovementUpdateRange(); + float long_range = zone->GetMaxMovementUpdateRange(); for (auto &c : _impl->Clients) { - float dist = c->CalculateDistance(m->GetX(), m->GetY(), m->GetZ()); + float distance = c->CalculateDistance(mob->GetX(), mob->GetY(), mob->GetZ()); bool match = false; if (range & ClientRangeClose) { - if (dist < short_range) { + if (distance < short_range) { match = true; } } if (!match && range & ClientRangeMedium) { - if (dist >= short_range && dist < long_range) { + if (distance >= short_range && distance < long_range) { match = true; } } if (!match && range & ClientRangeLong) { - if (dist >= long_range) { + if (distance >= long_range) { match = true; } } @@ -702,7 +783,7 @@ void MobMovementManager::SendCommandToClients(Mob *m, float dx, float dy, float if (anim != 0) { _impl->Stats.TotalSentMovement++; } - else if (dh != 0) { + else if (delta_heading != 0) { _impl->Stats.TotalSentHeading++; } else { @@ -715,6 +796,10 @@ void MobMovementManager::SendCommandToClients(Mob *m, float dx, float dy, float } } +/** + * @param in + * @return + */ float MobMovementManager::FixHeading(float in) { auto h = in; @@ -729,83 +814,139 @@ float MobMovementManager::FixHeading(float in) return h; } -void MobMovementManager::DumpStats(Client *to) +/** + * @param client + */ +void MobMovementManager::DumpStats(Client *client) { auto current_time = static_cast(Timer::GetCurrentTime()) / 1000.0; - auto total_time = current_time - _impl->Stats.LastResetTime; + auto total_time = current_time - _impl->Stats.LastResetTime; - to->Message(MT_System, "Dumping Movement Stats:"); - to->Message(MT_System, "Total Sent: %u (%.2f / sec)", _impl->Stats.TotalSent, static_cast(_impl->Stats.TotalSent) / total_time); - to->Message(MT_System, "Total Heading: %u (%.2f / sec)", _impl->Stats.TotalSentHeading, static_cast(_impl->Stats.TotalSentHeading) / total_time); - to->Message(MT_System, "Total Movement: %u (%.2f / sec)", _impl->Stats.TotalSentMovement, static_cast(_impl->Stats.TotalSentMovement) / total_time); - to->Message(MT_System, "Total Position: %u (%.2f / sec)", _impl->Stats.TotalSentPosition, static_cast(_impl->Stats.TotalSentPosition) / total_time); + client->Message(MT_System, "Dumping Movement Stats:"); + client->Message( + MT_System, + "Total Sent: %u (%.2f / sec)", + _impl->Stats.TotalSent, + static_cast(_impl->Stats.TotalSent) / total_time + ); + client->Message( + MT_System, + "Total Heading: %u (%.2f / sec)", + _impl->Stats.TotalSentHeading, + static_cast(_impl->Stats.TotalSentHeading) / total_time + ); + client->Message( + MT_System, + "Total Movement: %u (%.2f / sec)", + _impl->Stats.TotalSentMovement, + static_cast(_impl->Stats.TotalSentMovement) / total_time + ); + client->Message( + MT_System, + "Total Position: %u (%.2f / sec)", + _impl->Stats.TotalSentPosition, + static_cast(_impl->Stats.TotalSentPosition) / total_time + ); } void MobMovementManager::ClearStats() { - _impl->Stats.LastResetTime = static_cast(Timer::GetCurrentTime()) / 1000.0; - _impl->Stats.TotalSent = 0; - _impl->Stats.TotalSentHeading = 0; + _impl->Stats.LastResetTime = static_cast(Timer::GetCurrentTime()) / 1000.0; + _impl->Stats.TotalSent = 0; + _impl->Stats.TotalSentHeading = 0; _impl->Stats.TotalSentMovement = 0; _impl->Stats.TotalSentPosition = 0; } -void MobMovementManager::FillCommandStruct(PlayerPositionUpdateServer_Struct *spu, Mob *m, float dx, float dy, float dz, float dh, int anim) +/** + * @param position_update_server_struct + * @param mob + * @param delta_x + * @param delta_y + * @param delta_z + * @param delta_heading + * @param anim + */ +void MobMovementManager::FillCommandStruct( + PlayerPositionUpdateServer_Struct *position_update_server_struct, + Mob *mob, + float delta_x, + float delta_y, + float delta_z, + float delta_heading, + int anim +) { - memset(spu, 0x00, sizeof(PlayerPositionUpdateServer_Struct)); - spu->spawn_id = m->GetID(); - spu->x_pos = FloatToEQ19(m->GetX()); - spu->y_pos = FloatToEQ19(m->GetY()); - spu->z_pos = FloatToEQ19(m->GetZ()); - spu->heading = FloatToEQ12(m->GetHeading()); - spu->delta_x = FloatToEQ13(dx); - spu->delta_y = FloatToEQ13(dy); - spu->delta_z = FloatToEQ13(dz); - spu->delta_heading = FloatToEQ10(dh); - spu->animation = (m->IsBot() ? (int)((float)anim / 1.785714f) : anim); + memset(position_update_server_struct, 0x00, sizeof(PlayerPositionUpdateServer_Struct)); + position_update_server_struct->spawn_id = mob->GetID(); + position_update_server_struct->x_pos = FloatToEQ19(mob->GetX()); + position_update_server_struct->y_pos = FloatToEQ19(mob->GetY()); + position_update_server_struct->z_pos = FloatToEQ19(mob->GetZ()); + position_update_server_struct->heading = FloatToEQ12(mob->GetHeading()); + position_update_server_struct->delta_x = FloatToEQ13(delta_x); + position_update_server_struct->delta_y = FloatToEQ13(delta_y); + position_update_server_struct->delta_z = FloatToEQ13(delta_z); + position_update_server_struct->delta_heading = FloatToEQ10(delta_heading); + position_update_server_struct->animation = (mob->IsBot() ? (int) ((float) anim / 1.785714f) : anim); } -void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mode) +/** + * @param who + * @param x + * @param y + * @param z + * @param mob_movement_mode + */ +void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode) { if (!zone->HasMap() || !zone->HasWaterMap()) { auto iter = _impl->Entries.find(who); auto &ent = (*iter); - - PushMoveTo(ent.second, x, y, z, mode); + + PushMoveTo(ent.second, x, y, z, mob_movement_mode); PushStopMoving(ent.second); return; } - + if (who->IsBoat()) { - UpdatePathBoat(who, x, y, z, mode); - } else if (who->IsUnderwaterOnly()) { - UpdatePathUnderwater(who, x, y, z, mode); + UpdatePathBoat(who, x, y, z, mob_movement_mode); + } + else if (who->IsUnderwaterOnly()) { + UpdatePathUnderwater(who, x, y, z, mob_movement_mode); } else { - UpdatePathGround(who, x, y, z, mode); + UpdatePathGround(who, x, y, z, mob_movement_mode); } } -void MobMovementManager::UpdatePathGround(Mob * who, float x, float y, float z, MobMovementMode mode) +/** + * @param who + * @param x + * @param y + * @param z + * @param mode + */ +void MobMovementManager::UpdatePathGround(Mob *who, float x, float y, float z, MobMovementMode mode) { PathfinderOptions opts; opts.smooth_path = true; - opts.step_size = RuleR(Pathing, NavmeshStepSize); - opts.offset = who->GetZOffset(); - opts.flags = PathingNotDisabled ^ PathingZoneLine; + opts.step_size = RuleR(Pathing, NavmeshStepSize); + opts.offset = who->GetZOffset(); + opts.flags = PathingNotDisabled ^ PathingZoneLine; //This is probably pointless since the nav mesh tool currently sets zonelines to disabled anyway auto partial = false; - auto stuck = false; - auto route = zone->pathing->FindPath( + auto stuck = false; + auto route = zone->pathing->FindPath( glm::vec3(who->GetX(), who->GetY(), who->GetZ()), glm::vec3(x, y, z), partial, stuck, - opts); + opts + ); auto eiter = _impl->Entries.find(who); - auto &ent = (*eiter); + auto &ent = (*eiter); if (route.size() == 0) { HandleStuckBehavior(who, x, y, z, mode); @@ -813,31 +954,28 @@ void MobMovementManager::UpdatePathGround(Mob * who, float x, float y, float z, } AdjustRoute(route, who); - - - + + + //avoid doing any processing if the mob is stuck to allow normal stuck code to work. - if (!stuck) - { + if (!stuck) { //there are times when the routes returned are no differen than where the mob is currently standing. What basically happens - //is a mob will get 'stuck' in such a way that it should be moving but the 'moving' place is the exact same spot it is at. - //this is a problem and creates an area of ground that if a mob gets to, will stay there forever. If socal this creates a - //"Ball of Death" (tm). This code tries to prevent this by simply warping the mob to the requested x/y. Better to have a warp than + //is a mob will get 'stuck' in such a way that it should be moving but the 'moving' place is the exact same spot it is at. + //this is a problem and creates an area of ground that if a mob gets to, will stay there forever. If socal this creates a + //"Ball of Death" (tm). This code tries to prevent this by simply warping the mob to the requested x/y. Better to have a warp than //have stuck mobs. - auto routeNode = route.begin(); + auto routeNode = route.begin(); bool noValidPath = true; while (routeNode != route.end() && noValidPath == true) { auto ¤tNode = (*routeNode); - if (routeNode == route.end()) - { + if (routeNode == route.end()) { continue; } - if (!(currentNode.pos.x == who->GetX() && currentNode.pos.y == who->GetY())) - { + if (!(currentNode.pos.x == who->GetX() && currentNode.pos.y == who->GetY())) { //if one of the nodes to move to, is not our current node, pass it. noValidPath = false; break; @@ -847,47 +985,62 @@ void MobMovementManager::UpdatePathGround(Mob * who, float x, float y, float z, } - if (noValidPath) - { + if (noValidPath) { //we are 'stuck' in a path, lets just get out of this by 'teleporting' to the next position. - PushTeleportTo(ent.second, x, y, z, - CalculateHeadingAngleBetweenPositions(who->GetX(), who->GetY(), x, y)); + PushTeleportTo( + ent.second, + x, + y, + z, + CalculateHeadingAngleBetweenPositions(who->GetX(), who->GetY(), x, y) + ); + return; } } - + auto iter = route.begin(); + glm::vec3 previous_pos(who->GetX(), who->GetY(), who->GetZ()); + bool first_node = true; - - while (iter != route.end()) { auto ¤t_node = (*iter); - + iter++; - + if (iter == route.end()) { continue; } - + previous_pos = current_node.pos; auto &next_node = (*iter); - + if (first_node) { - + if (mode == MovementWalking) { auto h = who->CalculateHeadingToTarget(next_node.pos.x, next_node.pos.y); PushRotateTo(ent.second, who, h, mode); } - + first_node = false; } - + //move to / teleport to node + 1 if (next_node.teleport && next_node.pos.x != 0.0f && next_node.pos.y != 0.0f) { - PushTeleportTo(ent.second, next_node.pos.x, next_node.pos.y, next_node.pos.z, - CalculateHeadingAngleBetweenPositions(current_node.pos.x, current_node.pos.y, next_node.pos.x, next_node.pos.y)); + PushTeleportTo( + ent.second, + next_node.pos.x, + next_node.pos.y, + next_node.pos.z, + CalculateHeadingAngleBetweenPositions( + current_node.pos.x, + current_node.pos.y, + next_node.pos.x, + next_node.pos.y + ) + ); } else { if (zone->watermap->InLiquid(previous_pos)) { @@ -907,41 +1060,50 @@ void MobMovementManager::UpdatePathGround(Mob * who, float x, float y, float z, } } -void MobMovementManager::UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode mode) +/** + * @param who + * @param x + * @param y + * @param z + * @param movement_mode + */ +void MobMovementManager::UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode movement_mode) { auto eiter = _impl->Entries.find(who); - auto &ent = (*eiter); - if (zone->watermap->InLiquid(who->GetPosition()) && zone->watermap->InLiquid(glm::vec3(x, y, z)) && zone->zonemap->CheckLoS(who->GetPosition(), glm::vec3(x, y, z))) { - PushSwimTo(ent.second, x, y, z, mode); + auto &ent = (*eiter); + if (zone->watermap->InLiquid(who->GetPosition()) && zone->watermap->InLiquid(glm::vec3(x, y, z)) && + zone->zonemap->CheckLoS(who->GetPosition(), glm::vec3(x, y, z))) { + PushSwimTo(ent.second, x, y, z, movement_mode); PushStopMoving(ent.second); return; } PathfinderOptions opts; opts.smooth_path = true; - opts.step_size = RuleR(Pathing, NavmeshStepSize); - opts.offset = who->GetZOffset(); - opts.flags = PathingNotDisabled ^ PathingZoneLine; + opts.step_size = RuleR(Pathing, NavmeshStepSize); + opts.offset = who->GetZOffset(); + opts.flags = PathingNotDisabled ^ PathingZoneLine; auto partial = false; - auto stuck = false; - auto route = zone->pathing->FindPath( + auto stuck = false; + auto route = zone->pathing->FindPath( glm::vec3(who->GetX(), who->GetY(), who->GetZ()), glm::vec3(x, y, z), partial, stuck, - opts); + opts + ); if (route.size() == 0) { - HandleStuckBehavior(who, x, y, z, mode); + HandleStuckBehavior(who, x, y, z, movement_mode); return; } AdjustRoute(route, who); - auto iter = route.begin(); + auto iter = route.begin(); glm::vec3 previous_pos(who->GetX(), who->GetY(), who->GetZ()); - bool first_node = true; + bool first_node = true; while (iter != route.end()) { auto ¤t_node = (*iter); @@ -961,7 +1123,7 @@ void MobMovementManager::UpdatePathUnderwater(Mob *who, float x, float y, float } if (route.size() == 0) { - HandleStuckBehavior(who, x, y, z, mode); + HandleStuckBehavior(who, x, y, z, movement_mode); return; } @@ -981,9 +1143,9 @@ void MobMovementManager::UpdatePathUnderwater(Mob *who, float x, float y, float if (first_node) { - if (mode == MovementWalking) { + if (movement_mode == MovementWalking) { auto h = who->CalculateHeadingToTarget(next_node.pos.x, next_node.pos.y); - PushRotateTo(ent.second, who, h, mode); + PushRotateTo(ent.second, who, h, movement_mode); } first_node = false; @@ -991,46 +1153,86 @@ void MobMovementManager::UpdatePathUnderwater(Mob *who, float x, float y, float //move to / teleport to node + 1 if (next_node.teleport && next_node.pos.x != 0.0f && next_node.pos.y != 0.0f) { - PushTeleportTo(ent.second, next_node.pos.x, next_node.pos.y, next_node.pos.z, - CalculateHeadingAngleBetweenPositions(current_node.pos.x, current_node.pos.y, next_node.pos.x, next_node.pos.y)); + PushTeleportTo( + ent.second, next_node.pos.x, next_node.pos.y, next_node.pos.z, + CalculateHeadingAngleBetweenPositions( + current_node.pos.x, + current_node.pos.y, + next_node.pos.x, + next_node.pos.y + )); } else { - PushSwimTo(ent.second, next_node.pos.x, next_node.pos.y, next_node.pos.z, mode); + PushSwimTo(ent.second, next_node.pos.x, next_node.pos.y, next_node.pos.z, movement_mode); } } if (stuck) { - HandleStuckBehavior(who, x, y, z, mode); + HandleStuckBehavior(who, x, y, z, movement_mode); } else { PushStopMoving(ent.second); } } +/** + * @param who + * @param x + * @param y + * @param z + * @param mode + */ void MobMovementManager::UpdatePathBoat(Mob *who, float x, float y, float z, MobMovementMode mode) { auto eiter = _impl->Entries.find(who); - auto &ent = (*eiter); + auto &ent = (*eiter); PushSwimTo(ent.second, x, y, z, mode); PushStopMoving(ent.second); } +/** + * @param ent + * @param x + * @param y + * @param z + * @param heading + */ void MobMovementManager::PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading) { ent.Commands.push_back(std::unique_ptr(new TeleportToCommand(x, y, z, heading))); } +/** + * @param ent + * @param x + * @param y + * @param z + * @param mode + */ void MobMovementManager::PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode) { ent.Commands.push_back(std::unique_ptr(new MoveToCommand(x, y, z, mode))); } +/** + * @param ent + * @param x + * @param y + * @param z + * @param mode + */ void MobMovementManager::PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode) { ent.Commands.push_back(std::unique_ptr(new SwimToCommand(x, y, z, mode))); } +/** + * @param ent + * @param who + * @param to + * @param mode + */ void MobMovementManager::PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mode) { auto from = FixHeading(who->GetHeading()); @@ -1053,43 +1255,56 @@ void MobMovementManager::PushRotateTo(MobMovementEntry &ent, Mob *who, float to, ent.Commands.push_back(std::unique_ptr(new RotateToCommand(to, diff > 0 ? 1.0 : -1.0, mode))); } -void MobMovementManager::PushStopMoving(MobMovementEntry &ent) +/** + * @param mob_movement_entry + */ +void MobMovementManager::PushStopMoving(MobMovementEntry &mob_movement_entry) { - ent.Commands.push_back(std::unique_ptr(new StopMovingCommand())); + mob_movement_entry.Commands.push_back(std::unique_ptr(new StopMovingCommand())); } -void MobMovementManager::PushEvadeCombat(MobMovementEntry &ent) +/** + * @param mob_movement_entry + */ +void MobMovementManager::PushEvadeCombat(MobMovementEntry &mob_movement_entry) { - ent.Commands.push_back(std::unique_ptr(new EvadeCombatCommand())); + mob_movement_entry.Commands.push_back(std::unique_ptr(new EvadeCombatCommand())); } -void MobMovementManager::HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mode) +/** + * @param who + * @param x + * @param y + * @param z + * @param mob_movement_mode + */ +void MobMovementManager::HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode) { - auto sb = who->GetStuckBehavior(); + auto sb = who->GetStuckBehavior(); MobStuckBehavior behavior = RunToTarget; if (sb >= 0 && sb < MaxStuckBehavior) { - behavior = (MobStuckBehavior)sb; + behavior = (MobStuckBehavior) sb; } auto eiter = _impl->Entries.find(who); - auto &ent = (*eiter); + auto &ent = (*eiter); switch (sb) { - case RunToTarget: - PushMoveTo(ent.second, x, y, z, mode); - PushStopMoving(ent.second); - break; - case WarpToTarget: - PushTeleportTo(ent.second, x, y, z, 0.0f); - PushStopMoving(ent.second); - break; - case TakeNoAction: - PushStopMoving(ent.second); - break; - case EvadeCombat: - //PushEvadeCombat(ent.second); - PushStopMoving(ent.second); - break; + case RunToTarget: + PushMoveTo(ent.second, x, y, z, mob_movement_mode); + PushStopMoving(ent.second); + break; + case WarpToTarget: + PushTeleportTo(ent.second, x, y, z, 0.0f); + PushStopMoving(ent.second); + break; + case TakeNoAction: + PushStopMoving(ent.second); + break; + case EvadeCombat: + //PushEvadeCombat(ent.second); + PushStopMoving(ent.second); + break; } } diff --git a/zone/mob_movement_manager.h b/zone/mob_movement_manager.h index d9b2e7845..04c639ea1 100644 --- a/zone/mob_movement_manager.h +++ b/zone/mob_movement_manager.h @@ -41,18 +41,18 @@ class MobMovementManager public: ~MobMovementManager(); void Process(); - void AddMob(Mob *m); - void RemoveMob(Mob *m); - void AddClient(Client *c); - void RemoveClient(Client *c); + void AddMob(Mob *mob); + void RemoveMob(Mob *mob); + void AddClient(Client *client); + void RemoveClient(Client *client); - void RotateTo(Mob *who, float to, MobMovementMode mode = MovementRunning); + void RotateTo(Mob *who, float to, MobMovementMode mob_movement_mode = MovementRunning); void Teleport(Mob *who, float x, float y, float z, float heading); void NavigateTo(Mob *who, float x, float y, float z, MobMovementMode mode = MovementRunning); void StopNavigation(Mob *who); - void SendCommandToClients(Mob *m, float dx, float dy, float dz, float dh, int anim, ClientRange range); + void SendCommandToClients(Mob *mob, float delta_x, float delta_y, float delta_z, float delta_heading, int anim, ClientRange range); float FixHeading(float in); - void DumpStats(Client *to); + void DumpStats(Client *client); void ClearStats(); static MobMovementManager &Get() { @@ -65,18 +65,18 @@ private: MobMovementManager(const MobMovementManager&); MobMovementManager& operator=(const MobMovementManager&); - void FillCommandStruct(PlayerPositionUpdateServer_Struct *spu, Mob *m, float dx, float dy, float dz, float dh, int anim); - void UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mode); + void FillCommandStruct(PlayerPositionUpdateServer_Struct *position_update_server_struct, Mob *mob, float delta_x, float delta_y, float delta_z, float delta_heading, int anim); + void UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode); void UpdatePathGround(Mob *who, float x, float y, float z, MobMovementMode mode); - void UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode mode); + void UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode movement_mode); void UpdatePathBoat(Mob *who, float x, float y, float z, MobMovementMode mode); void PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading); void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode); void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode); void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mode); - void PushStopMoving(MobMovementEntry &ent); - void PushEvadeCombat(MobMovementEntry &ent); - void HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mode); + void PushStopMoving(MobMovementEntry &mob_movement_entry); + void PushEvadeCombat(MobMovementEntry &mob_movement_entry); + void HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode); struct Implementation; std::unique_ptr _impl; From 9f6976e852c147693a96119395f3343f14e7f87c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 6 Aug 2019 03:24:59 -0500 Subject: [PATCH 08/17] More readability changes --- zone/mob_movement_manager.cpp | 67 ++++++++++++++++++++--------------- zone/mob_movement_manager.h | 21 ++++++++--- 2 files changed, 55 insertions(+), 33 deletions(-) diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp index 398cd9c2a..df1a38168 100644 --- a/zone/mob_movement_manager.cpp +++ b/zone/mob_movement_manager.cpp @@ -26,11 +26,11 @@ public: class RotateToCommand : public IMovementCommand { public: - RotateToCommand(double rotate_to, double dir, MobMovementMode mode) + RotateToCommand(double rotate_to, double dir, MobMovementMode mob_movement_mode) { m_rotate_to = rotate_to; m_rotate_to_dir = dir; - m_rotate_to_mode = mode; + m_rotate_to_mode = mob_movement_mode; m_started = false; } @@ -265,7 +265,7 @@ protected: class SwimToCommand : public MoveToCommand { public: - SwimToCommand(float x, float y, float z, MobMovementMode mode) : MoveToCommand(x, y, z, mode) + SwimToCommand(float x, float y, float z, MobMovementMode mob_movement_mode) : MoveToCommand(x, y, z, mob_movement_mode) { } @@ -564,6 +564,9 @@ void MobMovementManager::Process() } } +/** + * @param mob + */ void MobMovementManager::AddMob(Mob *mob) { _impl->Entries.insert(std::make_pair(mob, MobMovementEntry())); @@ -714,6 +717,7 @@ void MobMovementManager::StopNavigation(Mob *who) * @param delta_heading * @param anim * @param range + * @param single_client */ void MobMovementManager::SendCommandToClients( Mob *mob, @@ -722,7 +726,8 @@ void MobMovementManager::SendCommandToClients( float delta_z, float delta_heading, int anim, - ClientRange range + ClientRange range, + Client* single_client ) { if (range == ClientRangeNone) { @@ -736,6 +741,10 @@ void MobMovementManager::SendCommandToClients( if (range == ClientRangeAny) { for (auto &c : _impl->Clients) { + if (single_client && c != single_client) { + continue; + } + _impl->Stats.TotalSent++; if (anim != 0) { @@ -756,6 +765,10 @@ void MobMovementManager::SendCommandToClients( float long_range = zone->GetMaxMovementUpdateRange(); for (auto &c : _impl->Clients) { + if (single_client && c != single_client) { + continue; + } + float distance = c->CalculateDistance(mob->GetX(), mob->GetY(), mob->GetZ()); bool match = false; @@ -859,7 +872,7 @@ void MobMovementManager::ClearStats() } /** - * @param position_update_server_struct + * @param position_update * @param mob * @param delta_x * @param delta_y @@ -868,7 +881,7 @@ void MobMovementManager::ClearStats() * @param anim */ void MobMovementManager::FillCommandStruct( - PlayerPositionUpdateServer_Struct *position_update_server_struct, + PlayerPositionUpdateServer_Struct *position_update, Mob *mob, float delta_x, float delta_y, @@ -877,17 +890,17 @@ void MobMovementManager::FillCommandStruct( int anim ) { - memset(position_update_server_struct, 0x00, sizeof(PlayerPositionUpdateServer_Struct)); - position_update_server_struct->spawn_id = mob->GetID(); - position_update_server_struct->x_pos = FloatToEQ19(mob->GetX()); - position_update_server_struct->y_pos = FloatToEQ19(mob->GetY()); - position_update_server_struct->z_pos = FloatToEQ19(mob->GetZ()); - position_update_server_struct->heading = FloatToEQ12(mob->GetHeading()); - position_update_server_struct->delta_x = FloatToEQ13(delta_x); - position_update_server_struct->delta_y = FloatToEQ13(delta_y); - position_update_server_struct->delta_z = FloatToEQ13(delta_z); - position_update_server_struct->delta_heading = FloatToEQ10(delta_heading); - position_update_server_struct->animation = (mob->IsBot() ? (int) ((float) anim / 1.785714f) : anim); + memset(position_update, 0x00, sizeof(PlayerPositionUpdateServer_Struct)); + position_update->spawn_id = mob->GetID(); + position_update->x_pos = FloatToEQ19(mob->GetX()); + position_update->y_pos = FloatToEQ19(mob->GetY()); + position_update->z_pos = FloatToEQ19(mob->GetZ()); + position_update->heading = FloatToEQ12(mob->GetHeading()); + position_update->delta_x = FloatToEQ13(delta_x); + position_update->delta_y = FloatToEQ13(delta_y); + position_update->delta_z = FloatToEQ13(delta_z); + position_update->delta_heading = FloatToEQ10(delta_heading); + position_update->animation = (mob->IsBot() ? (int) ((float) anim / 1.785714f) : anim); } /** @@ -955,8 +968,6 @@ void MobMovementManager::UpdatePathGround(Mob *who, float x, float y, float z, M AdjustRoute(route, who); - - //avoid doing any processing if the mob is stuck to allow normal stuck code to work. if (!stuck) { @@ -1208,11 +1219,11 @@ void MobMovementManager::PushTeleportTo(MobMovementEntry &ent, float x, float y, * @param x * @param y * @param z - * @param mode + * @param mob_movement_mode */ -void MobMovementManager::PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode) +void MobMovementManager::PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode) { - ent.Commands.push_back(std::unique_ptr(new MoveToCommand(x, y, z, mode))); + ent.Commands.push_back(std::unique_ptr(new MoveToCommand(x, y, z, mob_movement_mode))); } /** @@ -1220,20 +1231,20 @@ void MobMovementManager::PushMoveTo(MobMovementEntry &ent, float x, float y, flo * @param x * @param y * @param z - * @param mode + * @param mob_movement_mode */ -void MobMovementManager::PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode) +void MobMovementManager::PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode) { - ent.Commands.push_back(std::unique_ptr(new SwimToCommand(x, y, z, mode))); + ent.Commands.push_back(std::unique_ptr(new SwimToCommand(x, y, z, mob_movement_mode))); } /** * @param ent * @param who * @param to - * @param mode + * @param mob_movement_mode */ -void MobMovementManager::PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mode) +void MobMovementManager::PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mob_movement_mode) { auto from = FixHeading(who->GetHeading()); to = FixHeading(to); @@ -1252,7 +1263,7 @@ void MobMovementManager::PushRotateTo(MobMovementEntry &ent, Mob *who, float to, diff -= 512.0; } - ent.Commands.push_back(std::unique_ptr(new RotateToCommand(to, diff > 0 ? 1.0 : -1.0, mode))); + ent.Commands.push_back(std::unique_ptr(new RotateToCommand(to, diff > 0 ? 1.0 : -1.0, mob_movement_mode))); } /** diff --git a/zone/mob_movement_manager.h b/zone/mob_movement_manager.h index 04c639ea1..3c616cc5a 100644 --- a/zone/mob_movement_manager.h +++ b/zone/mob_movement_manager.h @@ -50,7 +50,18 @@ public: void Teleport(Mob *who, float x, float y, float z, float heading); void NavigateTo(Mob *who, float x, float y, float z, MobMovementMode mode = MovementRunning); void StopNavigation(Mob *who); - void SendCommandToClients(Mob *mob, float delta_x, float delta_y, float delta_z, float delta_heading, int anim, ClientRange range); + + void SendCommandToClients( + Mob *mob, + float delta_x, + float delta_y, + float delta_z, + float delta_heading, + int anim, + ClientRange range, + Client* single_client = nullptr + ); + float FixHeading(float in); void DumpStats(Client *client); void ClearStats(); @@ -65,15 +76,15 @@ private: MobMovementManager(const MobMovementManager&); MobMovementManager& operator=(const MobMovementManager&); - void FillCommandStruct(PlayerPositionUpdateServer_Struct *position_update_server_struct, Mob *mob, float delta_x, float delta_y, float delta_z, float delta_heading, int anim); + void FillCommandStruct(PlayerPositionUpdateServer_Struct *position_update, Mob *mob, float delta_x, float delta_y, float delta_z, float delta_heading, int anim); void UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode); void UpdatePathGround(Mob *who, float x, float y, float z, MobMovementMode mode); void UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode movement_mode); void UpdatePathBoat(Mob *who, float x, float y, float z, MobMovementMode mode); void PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading); - void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode); - void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode); - void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mode); + void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode); + void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode); + void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mob_movement_mode); void PushStopMoving(MobMovementEntry &mob_movement_entry); void PushEvadeCombat(MobMovementEntry &mob_movement_entry); void HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode); From 8fa76b91542fe8617a05cc29b548b3220a4218e2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 6 Aug 2019 03:27:33 -0500 Subject: [PATCH 09/17] Optimizations to movement updates to eliminate ghosting possibilities in larger zones --- changelog.txt | 3 +++ zone/client.cpp | 1 + zone/client.h | 1 + zone/client_packet.cpp | 35 +++++++++++++++++++++++++++++++---- zone/client_process.cpp | 5 +++-- 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/changelog.txt b/changelog.txt index 6b9d00a80..3f69bf570 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 8/6/2019 == +Akkadius: Optimizations to movement updates to eliminate ghosting possibilities in larger zones + == 7/22/2019 == Uleat: Added script 'vcxproj_dependencies.py' - a script to help determine conflicting project dependencies (alpha-stage) diff --git a/zone/client.cpp b/zone/client.cpp index 57f6ba865..ac696247a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -136,6 +136,7 @@ Client::Client(EQStreamInterface* ieqs) forget_timer(0), autosave_timer(RuleI(Character, AutosaveIntervalS) * 1000), client_scan_npc_aggro_timer(RuleI(Aggro, ClientAggroCheckInterval) * 1000), + client_zone_wide_full_position_update_timer(5 * 60 * 1000), tribute_timer(Tribute_duration), proximity_timer(ClientProximity_interval), TaskPeriodic_Timer(RuleI(TaskSystem, PeriodicCheckTimer) * 1000), diff --git a/zone/client.h b/zone/client.h index 0272fb21b..7b37c2b47 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1517,6 +1517,7 @@ private: Timer forget_timer; // our 2 min everybody forgets you timer Timer autosave_timer; Timer client_scan_npc_aggro_timer; + Timer client_zone_wide_full_position_update_timer; Timer tribute_timer; Timer proximity_timer; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f0eb00d13..2dc5cdbf9 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -60,6 +60,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "water_map.h" #include "worldserver.h" #include "zone.h" +#include "mob_movement_manager.h" #ifdef BOTS #include "bot.h" @@ -4466,16 +4467,16 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { /* Handle client aggro scanning timers NPCs */ is_client_moving = (ppu->y_pos == m_Position.y && ppu->x_pos == m_Position.x) ? false : true; - + if (is_client_moving) { Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is moving - scan timer is: %u", client_scan_npc_aggro_timer.GetDuration()); if (client_scan_npc_aggro_timer.GetDuration() > 1000) { client_scan_npc_aggro_timer.Disable(); client_scan_npc_aggro_timer.Start(500); - } - } else { + } + else { Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is NOT moving - scan timer is: %u", client_scan_npc_aggro_timer.GetDuration()); if (client_scan_npc_aggro_timer.GetDuration() < 1000) { @@ -4483,7 +4484,33 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { client_scan_npc_aggro_timer.Start(3000); } } - + + /** + * On a normal basis we limit mob movement updates based on distance + * This ensures we send a periodic full zone update to a client that has started + * moving after 5 or so minutes + */ + if (is_client_moving && client_zone_wide_full_position_update_timer.Check()) { + Log(Logs::Detail, Logs::Normal, "[%s] Client Zone Wide Position Update NPCs", GetCleanName()); + + auto &mob_movement_manager = MobMovementManager::Get(); + auto &mob_list = entity_list.GetMobList(); + + for (auto &it : mob_list) { + Mob *entity = it.second; + if (!entity->IsNPC()) { + continue; + } + + float distance_from_client_to_ignore = zone->GetMaxMovementUpdateRange() - 100; + if (CalculateDistance(entity->GetX(), entity->GetY(), entity->GetZ()) <= distance_from_client_to_ignore) { + continue; + } + + mob_movement_manager.SendCommandToClients(entity, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny, this); + } + } + float new_heading = EQ12toFloat(ppu->heading); int32 new_animation = ppu->animation; diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 5c750f03a..244f36580 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -592,8 +592,8 @@ bool Client::Process() { // only if client is not feigned if (zone->CanDoCombat() && ret && !GetFeigned() && client_scan_npc_aggro_timer.Check()) { int npc_scan_count = 0; - for (auto it = close_mobs.begin(); it != close_mobs.end(); ++it) { - Mob *mob = it->first; + for (auto & close_mob : close_mobs) { + Mob *mob = close_mob.first; if (!mob) continue; @@ -604,6 +604,7 @@ bool Client::Process() { if (mob->CheckWillAggro(this) && !mob->CheckAggro(this)) { mob->AddToHateList(this, 25); } + npc_scan_count++; } Log(Logs::General, Logs::Aggro, "Checking Reverse Aggro (client->npc) scanned_npcs (%i)", npc_scan_count); From 2014b6c251b9fbd88e78cc4e7f4235c20910ab9e Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Tue, 6 Aug 2019 03:28:17 -0500 Subject: [PATCH 10/17] Delete CTestTestfile.cmake --- cmake-build-debug/submodules/libuv/CTestTestfile.cmake | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 cmake-build-debug/submodules/libuv/CTestTestfile.cmake diff --git a/cmake-build-debug/submodules/libuv/CTestTestfile.cmake b/cmake-build-debug/submodules/libuv/CTestTestfile.cmake deleted file mode 100644 index 22e3caa8a..000000000 --- a/cmake-build-debug/submodules/libuv/CTestTestfile.cmake +++ /dev/null @@ -1,6 +0,0 @@ -# CMake generated Testfile for -# Source directory: /Users/cmiles/code/eqemu-docker-cloud/code/submodules/libuv -# Build directory: /Users/cmiles/code/eqemu-docker-cloud/code/cmake-build-debug/submodules/libuv -# -# This file includes the relevant testing commands required for -# testing this directory and lists subdirectories to be tested as well. From f1ee042de6291ae4fb8c383aed8954d1da103d9c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 6 Aug 2019 04:07:37 -0500 Subject: [PATCH 11/17] Add bulk force update by distance as well which we had similarily before the movement overhaul --- zone/client.cpp | 13 +++++++++++++ zone/client.h | 4 ++++ zone/client_packet.cpp | 21 ++++++++++++++++++--- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index ac696247a..3f0e33d2f 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -9116,3 +9116,16 @@ bool Client::GotoPlayer(std::string player_name) return false; } + +glm::vec4 &Client::GetLastPositionBeforeBulkUpdate() +{ + return last_position_before_bulk_update; +} + +/** + * @param in_last_position_before_bulk_update + */ +void Client::SetLastPositionBeforeBulkUpdate(glm::vec4 in_last_position_before_bulk_update) +{ + Client::last_position_before_bulk_update = in_last_position_before_bulk_update; +} \ No newline at end of file diff --git a/zone/client.h b/zone/client.h index 7b37c2b47..2ea27b108 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1309,6 +1309,9 @@ public: uint32 trapid; //ID of trap player has triggered. This is cleared when the player leaves the trap's radius, or it despawns. + void SetLastPositionBeforeBulkUpdate(glm::vec4 in_last_position_before_bulk_update); + glm::vec4 &GetLastPositionBeforeBulkUpdate(); + protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); @@ -1540,6 +1543,7 @@ private: Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */ glm::vec3 m_Proximity; + glm::vec4 last_position_before_bulk_update; void BulkSendInventoryItems(); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2dc5cdbf9..688a448eb 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -806,6 +806,8 @@ void Client::CompleteConnect() parse->EventPlayer(EVENT_ENTER_ZONE, this, "", 0); + SetLastPositionBeforeBulkUpdate(GetPosition()); + /* This sub event is for if a player logs in for the first time since entering world. */ if (firstlogon == 1) { parse->EventPlayer(EVENT_CONNECT, this, "", 0); @@ -4487,10 +4489,21 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { /** * On a normal basis we limit mob movement updates based on distance - * This ensures we send a periodic full zone update to a client that has started - * moving after 5 or so minutes + * This ensures we send a periodic full zone update to a client that has started moving after 5 or so minutes + * + * For very large zones we will also force a full update based on distance + * + * We ignore a small distance around us so that we don't interrupt already pathing deltas as those npcs will appear + * to full stop when they are actually still pathing */ - if (is_client_moving && client_zone_wide_full_position_update_timer.Check()) { + + float distance_moved = DistanceNoZ(GetLastPositionBeforeBulkUpdate(), GetPosition()); + bool moved_far_enough_before_bulk_update = distance_moved >= 1200; + bool is_ready_to_update = ( + client_zone_wide_full_position_update_timer.Check() || moved_far_enough_before_bulk_update + ); + + if (is_client_moving && is_ready_to_update) { Log(Logs::Detail, Logs::Normal, "[%s] Client Zone Wide Position Update NPCs", GetCleanName()); auto &mob_movement_manager = MobMovementManager::Get(); @@ -4509,6 +4522,8 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { mob_movement_manager.SendCommandToClients(entity, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny, this); } + + SetLastPositionBeforeBulkUpdate(GetPosition()); } float new_heading = EQ12toFloat(ppu->heading); From d9eeb00dead215f9fd2951d85c09fd9f0341fdd0 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 7 Aug 2019 18:54:53 -0500 Subject: [PATCH 12/17] 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; From 8df7bcc2c8df71c9867e3248e096128ddb7bbc94 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 8 Aug 2019 14:26:08 -0400 Subject: [PATCH 13/17] Fix double free in queryserv --- queryserv/database.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/queryserv/database.cpp b/queryserv/database.cpp index fcda884e4..1e06f229e 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -379,6 +379,7 @@ void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint3 } +// this function does not delete the ServerPacket, so it must be handled at call site void Database::GeneralQueryReceive(ServerPacket *pack) { /* These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again @@ -393,7 +394,6 @@ void Database::GeneralQueryReceive(ServerPacket *pack) { Log(Logs::Detail, Logs::QS_Server, "%s", query.c_str()); } - safe_delete(pack); safe_delete_array(queryBuffer); } From 19c92173d2b9f1b905849f80c3558dcf50b1ec72 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 8 Aug 2019 20:38:24 -0400 Subject: [PATCH 14/17] Added signal check for player EVENT_CAST_BEGIN --- zone/spells.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 8b1a08d19..fa09727a2 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -298,7 +298,8 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, if(IsClient()) { char temp[64]; sprintf(temp, "%d", spell_id); - parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), temp, 0); + if (parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), temp, 0) != 0) + return false; } else if(IsNPC()) { char temp[64]; sprintf(temp, "%d", spell_id); From 0d76e224fd3a4aea2ef41cc6b88bf712bbd184ab Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 9 Aug 2019 21:28:07 -0400 Subject: [PATCH 15/17] Updated eqemu_server.pl login server config example to json standard [skip ci] --- utils/scripts/eqemu_server.pl | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index f05c2c266..b2a53b864 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -1587,22 +1587,24 @@ sub add_login_server_firewall_rules { print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n"; print "\n"; print "[Install] Instructions \n"; - print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; + print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.json to your local server similar to the following:\n"; print " - - login.eqemulator.net - 5998 - - - - - 127.0.0.1 - 5998 - - - + \"loginserver1\" : { + \"account\" : \"\", + \"host\" : \"login.eqemulator.net\", + \"password\" : \"\", + \"port\" : \"5998\", + \"legacy\": \"1\" + }, + \"loginserver2\" : { + \"account\" : \"\", + \"host\" : \"192.168.197.129\", + \"password\" : \"\", + \"port\" : \"5998\" + }, + \"localaddress\" : \"192.168.197.129\", "; - print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; + print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 192.168.197.129) in the eqhosts.txt file\n"; } } From 461931f5bd360b5d112c733b776174ae97c60a6f Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 10 Aug 2019 01:59:58 -0500 Subject: [PATCH 16/17] Fix remainder of ghosting --- zone/client_packet.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 4f819e7a4..1cac556d9 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4515,12 +4515,17 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { continue; } - float distance_from_client_to_ignore = zone->GetNpcPositionUpdateDistance(); - if (entity->IsMoving() && CalculateDistance(entity->GetX(), entity->GetY(), entity->GetZ()) <= distance_from_client_to_ignore) { - continue; + int animation_speed = 0; + if (entity->IsMoving()) { + if (entity->IsRunning()) { + animation_speed = (entity->IsFeared() ? entity->GetFearSpeed() : entity->GetRunspeed()); + } + else { + animation_speed = entity->GetWalkspeed(); + } } - mob_movement_manager.SendCommandToClients(entity, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny, this); + mob_movement_manager.SendCommandToClients(entity, 0.0, 0.0, 0.0, 0.0, animation_speed, ClientRangeAny, this); } SetLastPositionBeforeBulkUpdate(GetPosition()); From 0884c57928344766654af632a4cfe1e6d842c07a Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 10 Aug 2019 02:27:07 -0500 Subject: [PATCH 17/17] Update minimum status for devtools --- common/emu_constants.h | 4 ++++ zone/client_packet.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/common/emu_constants.h b/common/emu_constants.h index 384aa3768..c6491b3b3 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -77,6 +77,10 @@ namespace EQEmu } // namespace invtype + namespace DevTools { + const int32 GM_ACCOUNT_STATUS_LEVEL = 150; + } + namespace popupresponse { const int32 SERVER_INTERNAL_USE_BASE = 2000000000; const int32 MOB_INFO_DISMISS = 2000000001; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 1cac556d9..39f959677 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1684,7 +1684,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) /** * DevTools Load Settings */ - if (Admin() >= 200) { + if (Admin() >= EQEmu::DevTools::GM_ACCOUNT_STATUS_LEVEL) { std::string dev_tools_window_key = StringFormat("%i-dev-tools-window-disabled", AccountID()); if (DataBucket::GetData(dev_tools_window_key) == "true") { dev_tools_window_enabled = false;