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)
This commit is contained in:
Hondacrx
2024-08-18 21:07:00 -04:00
parent da8b685c14
commit 7d83729d84
3 changed files with 36 additions and 34 deletions
@@ -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()
+2 -1
View File
@@ -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<int> spline = new();
+34 -14
View File
@@ -1,10 +1,12 @@
// Copyright (c) CypherCore <http://github.com/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;
}
}