From 7d83729d84a9294e521263305bf263104bdfa7e3 Mon Sep 17 00:00:00 2001 From: Hondacrx Date: Sun, 18 Aug 2024 21:07:00 -0400 Subject: [PATCH] Core/Movement: Switch to uncompressed paths in spline packets automatically when too large or too small delta between points is detected Port From (https://github.com/TrinityCore/TrinityCore/commit/377b51f76828befaaf6a6e7c3a9405fc8798d93d) --- .../Movement/Generators/WaypointMovement.cs | 19 -------- Source/Game/Movement/MoveSpline.cs | 3 +- Source/Game/Movement/MoveSplineInitArgs.cs | 48 +++++++++++++------ 3 files changed, 36 insertions(+), 34 deletions(-) diff --git a/Source/Game/Movement/Generators/WaypointMovement.cs b/Source/Game/Movement/Generators/WaypointMovement.cs index 8d043f387..7289c1b60 100644 --- a/Source/Game/Movement/Generators/WaypointMovement.cs +++ b/Source/Game/Movement/Generators/WaypointMovement.cs @@ -489,25 +489,6 @@ namespace Game.Movement if (_speed.HasValue) init.SetVelocity(_speed.Value); - if (init.Path().Count > 2) - { - Vector3 mid = (init.Path().First() + init.Path().Last()) / 2.0f; - var index = 0;// init.Path()[1..]; - var endIndex = (init.Path().Count - 2); - while (index != endIndex) - { - Vector3 offset = init.Path()[index] - mid; - if (MathF.Abs(offset.X) >= 128.0f || MathF.Abs(offset.Y) >= 128.0f || MathF.Abs(offset.Z) >= 64.0f) - { - // when distance is too great, send path in uncompressed state otherwise too much precision is lost on each point - init.SetUncompressed(); - break; - } - - ++index; - } - } - TimeSpan duration = TimeSpan.FromMilliseconds(init.Launch()); if (!IsExactSplinePath() diff --git a/Source/Game/Movement/MoveSpline.cs b/Source/Game/Movement/MoveSpline.cs index 506834cea..b886810a4 100644 --- a/Source/Game/Movement/MoveSpline.cs +++ b/Source/Game/Movement/MoveSpline.cs @@ -120,6 +120,7 @@ namespace Game.Movement } public Vector3[] GetPath() { return spline.GetPoints(); } + public int timeRemaining() { return Duration() - time_passed; } public int TimePassed() { return time_passed; } public int Duration() { return spline.Length(); } @@ -339,7 +340,7 @@ namespace Game.Movement public Vector3 CurrentDestination() { return Initialized() ? spline.GetPoint(point_Idx + 1) : Vector3.Zero; } public AnimTier? GetAnimation() { return anim_tier != null ? (AnimTier)anim_tier.AnimTier : null; } - + #region Fields public MoveSplineInitArgs InitArgs; public Spline spline = new(); diff --git a/Source/Game/Movement/MoveSplineInitArgs.cs b/Source/Game/Movement/MoveSplineInitArgs.cs index 38b35b04a..ad6873340 100644 --- a/Source/Game/Movement/MoveSplineInitArgs.cs +++ b/Source/Game/Movement/MoveSplineInitArgs.cs @@ -1,10 +1,12 @@ // Copyright (c) CypherCore All rights reserved. // Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +using Framework.Constants; using Game.DataStorage; using Game.Entities; using System; using System.Collections.Generic; +using System.Linq; using System.Numerics; namespace Game.Movement @@ -43,12 +45,12 @@ namespace Game.Movement // Returns true to show that the arguments were configured correctly and MoveSpline initialization will succeed. public bool Validate(Unit unit) { - bool CHECK(bool exp, bool verbose) + bool CHECK(bool exp, string verbose) { if (!exp) { if (unit != null) - Log.outError(LogFilter.Movement, $"MoveSplineInitArgs::Validate: expression '{exp}' failed for {(verbose ? unit.GetDebugInfo() : unit.GetGUID().ToString())}"); + Log.outError(LogFilter.Movement, $"MoveSplineInitArgs::Validate: expression '{exp}' failed for {verbose}"); else Log.outError(LogFilter.Movement, $"MoveSplineInitArgs::Validate: expression '{exp}' failed for cyclic spline continuation"); return false; @@ -56,23 +58,19 @@ namespace Game.Movement return true; } - if (!CHECK(path.Count > 1, true)) + if (!CHECK(path.Count > 1, unit.GetDebugInfo())) return false; - if (!CHECK(velocity >= 0.01f, true)) + if (!CHECK(velocity >= 0.01f, unit.GetDebugInfo())) return false; - if (!CHECK(effect_start_time_percent >= 0.0f && effect_start_time_percent <= 1.0f, true)) + if (!CHECK(effect_start_time_percent >= 0.0f && effect_start_time_percent <= 1.0f, unit.GetDebugInfo())) return false; - if (!CHECK(_checkPathLengths(), false)) + if (!CHECK(_checkPathLengths(), unit.GetGUID().ToString())) return false; if (spellEffectExtra != null) { - if (!CHECK(spellEffectExtra.ProgressCurveId == 0 || CliDB.CurveStorage.ContainsKey(spellEffectExtra.ProgressCurveId), false)) + if (!CHECK(spellEffectExtra.ProgressCurveId == 0 || CliDB.CurveStorage.ContainsKey(spellEffectExtra.ProgressCurveId), unit.GetDebugInfo())) return false; - if (!CHECK(spellEffectExtra.ParabolicCurveId == 0 || CliDB.CurveStorage.ContainsKey(spellEffectExtra.ParabolicCurveId), false)) - return false; - if (!CHECK(spellEffectExtra.ProgressCurveId == 0 || CliDB.CurveStorage.ContainsKey(spellEffectExtra.ProgressCurveId), true)) - return false; - if (!CHECK(spellEffectExtra.ParabolicCurveId == 0 || CliDB.CurveStorage.ContainsKey(spellEffectExtra.ParabolicCurveId), true)) + if (!CHECK(spellEffectExtra.ParabolicCurveId == 0 || CliDB.CurveStorage.ContainsKey(spellEffectExtra.ParabolicCurveId), unit.GetDebugInfo())) return false; } return true; @@ -80,10 +78,32 @@ namespace Game.Movement bool _checkPathLengths() { - if (path.Count > 2 || facing.type == Framework.Constants.MonsterMoveType.Normal) - for (int i = 0; i < path.Count - 1; ++i) + float MIN_OFFSET = 1.0f / 4.0f; + float MAX_XY_OFFSET = (1 << 11) / 4.0f; + float MAX_Z_OFFSET = (1 << 10) / 4.0f; + + var isValidPackedXYOffset = (float coord) => coord < MAX_XY_OFFSET && (coord < 0.1f || coord >= MIN_OFFSET); + var isValidPackedZOffset = (float coord) => coord < MAX_Z_OFFSET && (coord < 0.1f || coord >= MIN_OFFSET); + + if (path.Count > 2) + { + if ((path[2] - path[1]).Length() < 0.1f) + return false; + + Vector3 middle = (path.First() + path.Last()) / 2; + for (int i = 1; i < path.Count - 1; ++i) + { if ((path[i + 1] - path[i]).Length() < 0.1f) return false; + + // when compression is enabled, each point coord is packed into 11 bits (10 for Z) + if (!flags.HasFlag(SplineFlag.UncompressedPath)) + if (!isValidPackedXYOffset(MathF.Abs(path[i].X - middle.X)) + || !isValidPackedXYOffset(MathF.Abs(path[i].Y - middle.Y)) + || !isValidPackedZOffset(MathF.Abs(path[i].Z - middle.Z))) + flags.SetUnsetFlag(SplineFlag.UncompressedPath, true); + } + } return true; } }