Merge pull request #832 from eduardosmaniotto/bugfix/pathfind-overflow

bugfix: IndexOutOfRangeException in pathfinding due to byte overflow
(cherry picked from commit 26fc908ba8fccae04c5f7bee0b9a5784d89ae830)
This commit is contained in:
sven-n
2026-07-17 20:15:35 +02:00
committed by Acentech Dev
parent 54bdf901b8
commit dee0e014b1
2 changed files with 34 additions and 30 deletions

View File

@@ -24,17 +24,8 @@ public abstract class BaseGridNetwork : INetwork
/// </summary>
private const byte CostBitMask = 0b0111_1111;
private static readonly sbyte[,] DirectionOffsets =
{
{ 0, -1 },
{ 1, 0 },
{ 0, 1 },
{ -1, 0 },
{ 1, -1 },
{ 1, 1 },
{ -1, 1 },
{ -1, -1 },
};
private static readonly sbyte[] DirectionOffsetsX = { 0, 1, 0, -1, 1, 1, -1, -1 };
private static readonly sbyte[] DirectionOffsetsY = { -1, 0, 1, 0, -1, 1, 1, -1 };
private readonly int _numberOfDirections;
private ushort _gridWidth;
@@ -79,24 +70,31 @@ public abstract class BaseGridNetwork : INetwork
{
var grid = this._grid ?? throw new InvalidOperationException("Call Prepare before");
// ReSharper disable once TooWideLocalVariableScope performance improvement
byte newX;
// ReSharper disable once TooWideLocalVariableScope performance improvement
byte newY;
for (int i = 0; i < this._numberOfDirections; i++)
{
newX = (byte)(node.X + DirectionOffsets[i, 0]);
newY = (byte)(node.Y + DirectionOffsets[i, 1]);
if (!this._includeSafezone && (grid[newX, newY] & SafezoneBitFlag) > 0)
var calculatedX = node.X + DirectionOffsetsX[i];
var calculatedY = node.Y + DirectionOffsetsY[i];
if ((uint)calculatedX > byte.MaxValue || (uint)calculatedY > byte.MaxValue)
{
continue;
}
var costToNode = grid[newX, newY] & CostBitMask;
if (!this.IsWithinBounds(newX, newY) || costToNode == UnreachableGridNodeValue)
var newX = (byte)calculatedX;
var newY = (byte)calculatedY;
if (!this.IsWithinBounds(newX, newY))
{
continue;
}
var gridValue = grid[newX, newY];
if (!this._includeSafezone && (gridValue & SafezoneBitFlag) > 0)
{
continue;
}
var costToNode = gridValue & CostBitMask;
if (costToNode == UnreachableGridNodeValue)
{
continue;
}
@@ -108,7 +106,7 @@ public abstract class BaseGridNetwork : INetwork
continue;
}
var newG = node.CostUntilNow + this._grid[newNode.X, newNode.Y];
var newG = node.CostUntilNow + costToNode;
if (newNode.Status == NodeStatus.Open && newNode.CostUntilNow <= newG)
{

View File

@@ -82,16 +82,22 @@ public sealed class ScopedGridNetwork : BaseGridNetwork
var maxX = offsetX + this._actualSegmentSideLength;
var maxY = offsetY + this._actualSegmentSideLength;
for (byte x = offsetX; x < maxX; ++x)
// Must use int; a byte loop counter wraps at 256 and would not terminate.
for (int x = offsetX; x < maxX; ++x)
{
for (byte y = offsetY; y < maxY; ++y)
for (int y = offsetY; y < maxY; ++y)
{
var i = this.GetIndexOfPoint(x, y);
if (i < 0 || i >= this._gridNodes.Length)
{
continue;
}
var node = this._gridNodes[i];
if (node is not null)
{
node.Status = NodeStatus.Undefined;
node.Position = new(x, y);
node.Position = new((byte)x, (byte)y);
}
}
}
@@ -100,9 +106,9 @@ public sealed class ScopedGridNetwork : BaseGridNetwork
byte GetOffset(byte avgValue, int gridSize)
{
var offset = (byte)Math.Max(avgValue - (this._actualSegmentSideLength / 2), 0);
offset = (byte)Math.Min(offset, gridSize - this._actualSegmentSideLength);
return offset;
var offset = Math.Max(avgValue - (this._actualSegmentSideLength / 2), 0);
offset = Math.Min(offset, Math.Max(gridSize - this._actualSegmentSideLength, 0));
return (byte)offset;
}
}