Overhaul InvasiveList iteration
This commit is contained in:
parent
03839a2699
commit
a934f07f3a
7 changed files with 66 additions and 67 deletions
|
|
@ -5,49 +5,28 @@ namespace MHServerEmu.Core.Collections
|
|||
{
|
||||
public class InvasiveList<T>
|
||||
{
|
||||
private readonly Iterator[] _iterators;
|
||||
|
||||
private int _numIterators;
|
||||
|
||||
public int Id { get; private set; }
|
||||
public T Head { get; set; }
|
||||
public T Head { get; private set; }
|
||||
public T Tail { get; private set; }
|
||||
public int Count { get; private set; }
|
||||
|
||||
private Iterator[] _iterators;
|
||||
private int _numIterators;
|
||||
private int _maxIterators;
|
||||
public bool IsEmpty { get => Head == null; }
|
||||
|
||||
public InvasiveList(int maxIterators)
|
||||
public InvasiveList(int maxIterators, int id = 0)
|
||||
{
|
||||
_maxIterators = maxIterators;
|
||||
_iterators = new Iterator[_maxIterators];
|
||||
}
|
||||
|
||||
public InvasiveList(int maxIterators, int id)
|
||||
{
|
||||
_maxIterators = maxIterators;
|
||||
_iterators = new Iterator[_maxIterators];
|
||||
_iterators = new Iterator[maxIterators];
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public IEnumerable<T> Iterate()
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
var iterator = new Iterator(this);
|
||||
|
||||
try
|
||||
{
|
||||
while (iterator.End() == false)
|
||||
{
|
||||
var element = iterator.Current;
|
||||
iterator.MoveNext();
|
||||
yield return element;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
UnregisterIterator(iterator);
|
||||
}
|
||||
return new Iterator(this);
|
||||
}
|
||||
|
||||
public bool IsEmpty() => Head == null;
|
||||
|
||||
public void Remove(T element)
|
||||
{
|
||||
if (element == null || Contains(element) == false) return;
|
||||
|
|
@ -138,7 +117,10 @@ namespace MHServerEmu.Core.Collections
|
|||
Count++;
|
||||
}
|
||||
|
||||
public virtual ref InvasiveListNode<T> GetInvasiveListNode(T element, int listId) => ref Unsafe.NullRef<InvasiveListNode<T>>();
|
||||
public virtual ref InvasiveListNode<T> GetInvasiveListNode(T element, int listId)
|
||||
{
|
||||
return ref Unsafe.NullRef<InvasiveListNode<T>>();
|
||||
}
|
||||
|
||||
public bool Contains(T element)
|
||||
{
|
||||
|
|
@ -150,8 +132,8 @@ namespace MHServerEmu.Core.Collections
|
|||
|
||||
private void RegisterIterator(Iterator iterator)
|
||||
{
|
||||
if (_numIterators >= _maxIterators)
|
||||
throw new InvalidOperationException($"Too many iterators '{_maxIterators}' for invasive list");
|
||||
if (_numIterators >= _iterators.Length)
|
||||
throw new InvalidOperationException($"Too many iterators '{_iterators.Length}' for invasive list");
|
||||
|
||||
_iterators[_numIterators++] = iterator;
|
||||
}
|
||||
|
|
@ -172,36 +154,53 @@ namespace MHServerEmu.Core.Collections
|
|||
throw new InvalidOperationException("Iterator not found in iterator collection of invasive list!");
|
||||
}
|
||||
|
||||
public class Iterator : IEnumerator<T>
|
||||
public sealed class Iterator : IEnumerator<T>
|
||||
{
|
||||
private InvasiveList<T> _list;
|
||||
public bool SkipNext { get; set; }
|
||||
private readonly InvasiveList<T> _list;
|
||||
|
||||
private bool _start = true;
|
||||
|
||||
public T Current { get; private set; }
|
||||
object IEnumerator.Current { get => Current; }
|
||||
|
||||
public bool SkipNext { get; set; } = false;
|
||||
|
||||
public Iterator(InvasiveList<T> invasiveList)
|
||||
{
|
||||
_list = invasiveList;
|
||||
Current = _list.Head;
|
||||
SkipNext = false;
|
||||
_list.RegisterIterator(this);
|
||||
}
|
||||
|
||||
public T Current { get; private set; }
|
||||
object IEnumerator.Current => Current;
|
||||
public void Dispose() { }
|
||||
public void Reset() { }
|
||||
public void Dispose()
|
||||
{
|
||||
_list.UnregisterIterator(this);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_start = true;
|
||||
Current = default;
|
||||
SkipNext = false;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (SkipNext) SkipNext = false;
|
||||
else if (Current != null)
|
||||
Current = _list.GetInvasiveListNode(Current, _list.Id).Next;
|
||||
if (_start)
|
||||
{
|
||||
Current = _list.Head;
|
||||
_start = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SkipNext)
|
||||
SkipNext = false;
|
||||
else if (Current != null)
|
||||
Current = _list.GetInvasiveListNode(Current, _list.Id).Next;
|
||||
}
|
||||
|
||||
return true;
|
||||
return Current != null;
|
||||
}
|
||||
|
||||
public bool End() => Current == null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public struct InvasiveListNode<T>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace MHServerEmu.Games.Entities
|
|||
All = 3,
|
||||
}
|
||||
|
||||
public class EntityInvasiveCollection : InvasiveList<Entity>
|
||||
public sealed class EntityInvasiveCollection : InvasiveList<Entity>
|
||||
{
|
||||
public EntityInvasiveCollection(EntityCollection collectionType, int maxIterators = 8) : base(maxIterators, (int)collectionType) { }
|
||||
public override ref InvasiveListNode<Entity> GetInvasiveListNode(Entity element, int listId) => ref element.GetInvasiveListNode(listId);
|
||||
|
|
@ -449,7 +449,7 @@ namespace MHServerEmu.Games.Entities
|
|||
|
||||
public void LocomoteEntities()
|
||||
{
|
||||
foreach (var entity in LocomotionEntities.Iterate())
|
||||
foreach (var entity in LocomotionEntities)
|
||||
if (entity is WorldEntity worldEntity)
|
||||
worldEntity?.Locomotor.Locomote();
|
||||
}
|
||||
|
|
@ -586,7 +586,7 @@ namespace MHServerEmu.Games.Entities
|
|||
IsAIEnabled = enable;
|
||||
|
||||
if (enable)
|
||||
foreach (var entity in SimulatedEntities.Iterate())
|
||||
foreach (var entity in SimulatedEntities)
|
||||
if (entity is Agent agent) agent.AIController?.SetIsEnabled(true);
|
||||
|
||||
foreach (var entity in _entityDict.Values)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace MHServerEmu.Games.Entities.Physics
|
|||
}
|
||||
}
|
||||
|
||||
public class ForceSystemMemberList : InvasiveList<ForceSystemMember>
|
||||
public sealed class ForceSystemMemberList : InvasiveList<ForceSystemMember>
|
||||
{
|
||||
public ForceSystemMemberList(int maxIterators = 1) : base(maxIterators) { }
|
||||
public override ref InvasiveListNode<ForceSystemMember> GetInvasiveListNode(ForceSystemMember element, int listId) => ref element.InvasiveListNode;
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ namespace MHServerEmu.Games.Entities.Physics
|
|||
|
||||
EntityManager entityManager = _game.EntityManager;
|
||||
|
||||
foreach (var member in forceSystem.Members.Iterate())
|
||||
foreach (var member in forceSystem.Members)
|
||||
{
|
||||
if (member == null) continue;
|
||||
bool active = false;
|
||||
|
|
@ -684,7 +684,7 @@ namespace MHServerEmu.Games.Entities.Physics
|
|||
float distanceSq = Vector3.DistanceSquared(epicenter, member.Position);
|
||||
var pendingMembers = pendingForce.Members;
|
||||
|
||||
foreach (var pendingMember in pendingMembers.Iterate())
|
||||
foreach (var pendingMember in pendingMembers)
|
||||
if (distanceSq > Vector3.DistanceSquared(epicenter, pendingMember.Position))
|
||||
{
|
||||
pendingForce.Members.InsertBefore(member, pendingMember);
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ namespace MHServerEmu.Games.Navi
|
|||
|
||||
public void Release()
|
||||
{
|
||||
foreach (var triangle in TriangleList.Iterate())
|
||||
foreach (var triangle in TriangleList)
|
||||
RemoveTriangle(triangle);
|
||||
|
||||
_lastTriangle = null;
|
||||
|
|
@ -126,7 +126,7 @@ namespace MHServerEmu.Games.Navi
|
|||
using var collinearEdgesHandle = ListPool<NaviEdge>.Instance.Get(out List<NaviEdge> collinearEdges);
|
||||
using NaviSerialCheck naviSerialCheck = new(this);
|
||||
|
||||
foreach (var triangle in TriangleList.Iterate())
|
||||
foreach (var triangle in TriangleList)
|
||||
foreach (var edge in triangle.Edges)
|
||||
{
|
||||
if (edge.Triangles[0] == null || edge.Triangles[1] == null) continue;
|
||||
|
|
@ -925,7 +925,7 @@ namespace MHServerEmu.Games.Navi
|
|||
{
|
||||
StringBuilder hashes = new();
|
||||
int id = 0;
|
||||
foreach (var triangle in TriangleList.Iterate())
|
||||
foreach (var triangle in TriangleList)
|
||||
hashes.AppendLine($"[{id++}] {triangle.ToHashString()}");
|
||||
FileHelper.SaveTextFileToRoot(fileName, hashes.ToString());
|
||||
}
|
||||
|
|
@ -934,7 +934,7 @@ namespace MHServerEmu.Games.Navi
|
|||
{
|
||||
StringBuilder hashes = new();
|
||||
int id = 0;
|
||||
foreach (var triangle in TriangleList.Iterate())
|
||||
foreach (var triangle in TriangleList)
|
||||
hashes.AppendLine($"[{id++}] {triangle.ToHashString2()}");
|
||||
FileHelper.SaveTextFileToRoot(fileName, hashes.ToString());
|
||||
}
|
||||
|
|
@ -943,12 +943,12 @@ namespace MHServerEmu.Games.Navi
|
|||
{
|
||||
NaviSvgHelper svg = new(this);
|
||||
Stack<NaviPoint> influences = new();
|
||||
foreach (var triangle in TriangleList.Iterate())
|
||||
foreach (var triangle in TriangleList)
|
||||
foreach (var edge in triangle.Edges)
|
||||
foreach (var point in edge.Points)
|
||||
if (point.InfluenceRadius > 0 && influences.Contains(point) == false)
|
||||
influences.Push(point);
|
||||
foreach (var triangle in TriangleList.Iterate())
|
||||
foreach (var triangle in TriangleList)
|
||||
svg.AddTriangle(triangle);
|
||||
foreach (var point in influences)
|
||||
svg.AddCircle(point.Pos, point.InfluenceRadius);
|
||||
|
|
@ -962,7 +962,7 @@ namespace MHServerEmu.Games.Navi
|
|||
|
||||
// Vertices
|
||||
int newId = 1;
|
||||
foreach (var triangle in TriangleList.Iterate())
|
||||
foreach (var triangle in TriangleList)
|
||||
if (triangle.PathingFlags.HasFlag(filterFlags))
|
||||
foreach (var edge in triangle.Edges)
|
||||
foreach (var point in edge.Points)
|
||||
|
|
@ -975,7 +975,7 @@ namespace MHServerEmu.Games.Navi
|
|||
}
|
||||
|
||||
// Faces
|
||||
foreach (var triangle in TriangleList.Iterate())
|
||||
foreach (var triangle in TriangleList)
|
||||
if (triangle.PathingFlags.HasFlag(filterFlags))
|
||||
{
|
||||
var p0 = triangle.PointCW(0);
|
||||
|
|
|
|||
|
|
@ -345,7 +345,7 @@ namespace MHServerEmu.Games.Navi
|
|||
|
||||
private void ReverseMarkupMesh()
|
||||
{
|
||||
foreach (var triangle in TriangleList.Iterate())
|
||||
foreach (var triangle in TriangleList)
|
||||
for (int edgeIndex = 0; edgeIndex < 3; edgeIndex++)
|
||||
{
|
||||
NaviEdge edge = triangle.Edges[edgeIndex];
|
||||
|
|
@ -367,7 +367,7 @@ namespace MHServerEmu.Games.Navi
|
|||
|
||||
private void ClearMarkup()
|
||||
{
|
||||
foreach (var triangle in TriangleList.Iterate())
|
||||
foreach (var triangle in TriangleList)
|
||||
{
|
||||
triangle.ClearFlag(NaviTriangleFlags.Markup);
|
||||
triangle.PathingFlags = PathFlags.None;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace MHServerEmu.Games.Navi
|
|||
Markup = 1 << 1,
|
||||
}
|
||||
|
||||
public class TriangleList : InvasiveList<NaviTriangle>
|
||||
public sealed class TriangleList : InvasiveList<NaviTriangle>
|
||||
{
|
||||
public TriangleList(int maxIterators = 1) : base(maxIterators) { }
|
||||
public override ref InvasiveListNode<NaviTriangle> GetInvasiveListNode(NaviTriangle element, int listId) => ref element.InvasiveListNode;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue