remove some dependencies #18
|
@ -7,13 +7,13 @@
|
|||
|
||||
steps:
|
||||
- name: test
|
||||
image: mcr.microsoft.com/dotnet/core/sdk:3.1
|
||||
image: mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim
|
||||
commands:
|
||||
- dotnet build -c Release
|
||||
- dotnet test -c Release
|
||||
|
||||
- name: deploy
|
||||
image: mcr.microsoft.com/dotnet/core/sdk:3.1
|
||||
image: mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim
|
||||
environment:
|
||||
API_KEY:
|
||||
from_secret: API_KEY
|
||||
|
|
7
TODO
7
TODO
|
@ -1,7 +0,0 @@
|
|||
- immutable component system?
|
||||
|
||||
- method to remove all components of a type without destroying Entities
|
||||
- method to remove a component of a type without destroying entity
|
||||
|
||||
- look at test coverage
|
||||
- docs
|
|
@ -0,0 +1,156 @@
|
|||
using System;
|
||||
|
||||
namespace Encompass
|
||||
{
|
||||
public static unsafe class MemoryHelper
|
||||
{
|
||||
public static void Copy(uint* src, uint* dest, int count)
|
||||
{
|
||||
for (; count != 0; count--) *dest++ = *src++;
|
||||
}
|
||||
|
||||
public static void Fill(uint* p, int count, uint value)
|
||||
{
|
||||
for (; count != 0; count--) *p++ = value;
|
||||
}
|
||||
|
||||
public static void And(uint* p, uint* q, uint* result, int count)
|
||||
{
|
||||
for (; count != 0; count--) *result++ = *p++ & *q++;
|
||||
}
|
||||
|
||||
public static void Or(uint* p, uint* q, uint* result, int count)
|
||||
{
|
||||
for (; count != 0; count--) *result++ = *p++ | *q++;
|
||||
}
|
||||
|
||||
public static void Not(uint* p, uint* result, int count)
|
||||
{
|
||||
for (; count != 0; count--) *result++ = ~*p++;
|
||||
}
|
||||
|
||||
public static bool Equal(uint* p, uint* q, int count)
|
||||
{
|
||||
for (; count != 0; count--) if (*p++ != *q++) { return false; }
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe struct BitSet512 : IEquatable<BitSet512>
|
||||
{
|
||||
public static BitSet512 Zero { get; } = new BitSet512(0);
|
||||
public static BitSet512 Ones { get; } = new BitSet512(uint.MaxValue);
|
||||
|
||||
private const int _uintLength = 16;
|
||||
|
||||
private fixed uint _buffer[_uintLength];
|
||||
|
||||
public BitSet512(uint value)
|
||||
{
|
||||
fixed (uint* p = _buffer) MemoryHelper.Fill(p, _uintLength, value);
|
||||
}
|
||||
|
||||
public BitSet512(uint* src)
|
||||
{
|
||||
fixed (uint* dest = _buffer) MemoryHelper.Copy(src, dest, _uintLength);
|
||||
}
|
||||
|
||||
public static BitSet512 operator &(BitSet512 a, BitSet512 b)
|
||||
{
|
||||
var tmp = stackalloc uint[_uintLength];
|
||||
MemoryHelper.And(a._buffer, b._buffer, tmp, _uintLength);
|
||||
return new BitSet512(tmp);
|
||||
}
|
||||
|
||||
public static BitSet512 operator |(BitSet512 a, BitSet512 b)
|
||||
{
|
||||
var tmp = stackalloc uint[_uintLength];
|
||||
MemoryHelper.Or(a._buffer, b._buffer, tmp, _uintLength);
|
||||
return new BitSet512(tmp);
|
||||
}
|
||||
|
||||
public static BitSet512 operator ~(BitSet512 a)
|
||||
{
|
||||
var tmp = stackalloc uint[_uintLength];
|
||||
MemoryHelper.Not(a._buffer, tmp, _uintLength);
|
||||
return new BitSet512(tmp);
|
||||
}
|
||||
|
||||
public static bool operator ==(BitSet512 left, BitSet512 right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
public static bool operator !=(BitSet512 left, BitSet512 right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
public BitSet512 Set(int index)
|
||||
{
|
||||
var tmp = stackalloc uint[_uintLength];
|
||||
fixed (uint* p = _buffer) MemoryHelper.Copy(p, tmp, _uintLength);
|
||||
tmp[index / 32] |= (uint)(1 << index % 32);
|
||||
return new BitSet512(tmp);
|
||||
}
|
||||
|
||||
public BitSet512 UnSet(int index)
|
||||
{
|
||||
var tmp = stackalloc uint[_uintLength];
|
||||
fixed (uint* p = _buffer) MemoryHelper.Copy(p, tmp, _uintLength);
|
||||
tmp[index / 32] &= ~(uint)(1 << index % 32);
|
||||
return new BitSet512(tmp);
|
||||
}
|
||||
|
||||
public bool Get(int bitIndex)
|
||||
{
|
||||
var bitInt = (uint)(1 << bitIndex % 32);
|
||||
return (_buffer[bitIndex / 32] & bitInt) == bitInt;
|
||||
}
|
||||
|
||||
public bool AllTrue()
|
||||
{
|
||||
return this == Ones;
|
||||
}
|
||||
|
||||
public bool AllFalse()
|
||||
{
|
||||
return this == Zero;
|
||||
}
|
||||
|
||||
public static BitSet512 BitwiseAnd(BitSet512 left, BitSet512 right)
|
||||
{
|
||||
return left & right;
|
||||
}
|
||||
|
||||
public static BitSet512 BitwiseOr(BitSet512 left, BitSet512 right)
|
||||
{
|
||||
return left | right;
|
||||
}
|
||||
|
||||
public static BitSet512 OnesComplement(BitSet512 bitSet)
|
||||
{
|
||||
return ~bitSet;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is BitSet512 set && Equals(set);
|
||||
}
|
||||
|
||||
public bool Equals(BitSet512 other)
|
||||
{
|
||||
fixed (uint* p = _buffer) return MemoryHelper.Equal(p, other._buffer, _uintLength);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hc = 0;
|
||||
for (var i = 0; i < _uintLength; i++)
|
||||
{
|
||||
hc ^= _buffer[i].GetHashCode();
|
||||
}
|
||||
return hc;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
using MoonTools.FastCollections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using Encompass.Exceptions;
|
||||
using MoonTools.FastCollections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ using System.Reflection;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Encompass.Exceptions;
|
||||
using MoonTools.FastCollections;
|
||||
|
||||
namespace Encompass
|
||||
{
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
using MoonTools.FastCollections;
|
||||
|
||||
namespace Encompass
|
||||
namespace Encompass
|
||||
{
|
||||
internal struct EntitySetQuery
|
||||
{
|
||||
|
|
|
@ -0,0 +1,390 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Encompass
|
||||
{
|
||||
internal class DirectedGraph<TNode> where TNode : IEquatable<TNode>
|
||||
{
|
||||
protected HashSet<TNode> nodes = new HashSet<TNode>();
|
||||
protected Dictionary<TNode, HashSet<TNode>> neighbors = new Dictionary<TNode, HashSet<TNode>>();
|
||||
|
||||
protected HashSet<(TNode, TNode)> edges = new HashSet<(TNode, TNode)>();
|
||||
|
||||
public IEnumerable<TNode> Nodes => nodes;
|
||||
public IEnumerable<(TNode, TNode)> Edges => edges;
|
||||
|
||||
public void AddNode(TNode node)
|
||||
{
|
||||
if (!Exists(node))
|
||||
{
|
||||
nodes.Add(node);
|
||||
neighbors.Add(node, new HashSet<TNode>());
|
||||
}
|
||||
}
|
||||
|
||||
public void AddNodes(params TNode[] nodes)
|
||||
{
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
AddNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveNode(TNode node)
|
||||
{
|
||||
CheckNodes(node);
|
||||
|
||||
var edgesToRemove = new List<(TNode, TNode)>();
|
||||
|
||||
foreach (var entry in neighbors)
|
||||
{
|
||||
if (entry.Value.Contains(node))
|
||||
{
|
||||
edgesToRemove.Add((entry.Key, node));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var edge in edgesToRemove)
|
||||
{
|
||||
RemoveEdge(edge.Item1, edge.Item2);
|
||||
}
|
||||
|
||||
nodes.Remove(node);
|
||||
neighbors.Remove(node);
|
||||
}
|
||||
|
||||
public void RemoveEdge(TNode v, TNode u)
|
||||
{
|
||||
CheckEdge(v, u);
|
||||
neighbors[v].Remove(u);
|
||||
edges.Remove((v, u));
|
||||
}
|
||||
|
||||
public void AddEdge(TNode v, TNode u)
|
||||
{
|
||||
CheckNodes(v, u);
|
||||
if (Exists(v, u)) { throw new ArgumentException($"Edge between {v} and {u} already exists in the graph"); }
|
||||
|
||||
if (v.Equals(u)) { throw new ArgumentException("Self-edges are not allowed in a simple graph. Use a multigraph instead"); }
|
||||
|
||||
neighbors[v].Add(u);
|
||||
edges.Add((v, u));
|
||||
}
|
||||
|
||||
public bool Exists(TNode node)
|
||||
{
|
||||
return nodes.Contains(node);
|
||||
}
|
||||
|
||||
public bool Exists(TNode v, TNode u)
|
||||
{
|
||||
CheckNodes(v, u);
|
||||
return edges.Contains((v, u));
|
||||
}
|
||||
|
||||
protected void CheckNodes(params TNode[] givenNodes)
|
||||
{
|
||||
foreach (var node in givenNodes)
|
||||
{
|
||||
if (!Exists(node))
|
||||
{
|
||||
throw new System.ArgumentException($"Vertex {node} does not exist in the graph");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void CheckEdge(TNode v, TNode u)
|
||||
{
|
||||
CheckNodes(v, u);
|
||||
if (!Exists(v, u)) { throw new ArgumentException($"Edge between vertex {v} and vertex {u} does not exist in the graph"); }
|
||||
}
|
||||
|
||||
public IEnumerable<TNode> Neighbors(TNode node)
|
||||
{
|
||||
CheckNodes(node);
|
||||
return neighbors[node];
|
||||
}
|
||||
|
||||
public DirectedGraph<TNode> Clone()
|
||||
{
|
||||
var clone = new DirectedGraph<TNode>();
|
||||
clone.AddNodes(Nodes.ToArray());
|
||||
|
||||
foreach (var v in Nodes)
|
||||
{
|
||||
foreach (var n in Neighbors(v))
|
||||
{
|
||||
clone.AddEdge(v, n);
|
||||
}
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
public DirectedGraph<TNode> SubGraph(params TNode[] subVertices)
|
||||
{
|
||||
var subGraph = new DirectedGraph<TNode>();
|
||||
subGraph.AddNodes(subVertices.ToArray());
|
||||
|
||||
foreach (var n in Nodes)
|
||||
{
|
||||
if (Nodes.Contains(n))
|
||||
{
|
||||
var neighbors = Neighbors(n);
|
||||
foreach (var u in neighbors)
|
||||
{
|
||||
if (subVertices.Contains(u))
|
||||
{
|
||||
subGraph.AddEdge(n, u);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return subGraph;
|
||||
}
|
||||
|
||||
private IEnumerable<TNode> PostorderNodeDFSHelper(HashSet<TNode> discovered, TNode v)
|
||||
{
|
||||
discovered.Add(v);
|
||||
|
||||
foreach (var neighbor in Neighbors(v))
|
||||
{
|
||||
if (!discovered.Contains(neighbor))
|
||||
{
|
||||
foreach (var node in PostorderNodeDFSHelper(discovered, neighbor))
|
||||
{
|
||||
yield return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
yield return v;
|
||||
}
|
||||
|
||||
protected IEnumerable<TNode> PostorderNodeDFS()
|
||||
{
|
||||
var dfsDiscovered = new HashSet<TNode>();
|
||||
|
||||
foreach (var node in Nodes)
|
||||
{
|
||||
if (!dfsDiscovered.Contains(node))
|
||||
{
|
||||
foreach (var thing in PostorderNodeDFSHelper(dfsDiscovered, node))
|
||||
{
|
||||
yield return thing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<TNode> TopologicalSort()
|
||||
{
|
||||
return PostorderNodeDFS().Reverse();
|
||||
}
|
||||
|
||||
public bool Cyclic()
|
||||
{
|
||||
return StronglyConnectedComponents().Any((scc) => scc.Count() > 1);
|
||||
}
|
||||
|
||||
public IEnumerable<IEnumerable<TNode>> SimpleCycles()
|
||||
{
|
||||
void unblock(TNode thisnode, HashSet<TNode> blocked, Dictionary<TNode, HashSet<TNode>> B) //refactor to remove closure
|
||||
{
|
||||
var stack = new Stack<TNode>();
|
||||
stack.Push(thisnode);
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var node = stack.Pop();
|
||||
if (blocked.Contains(thisnode))
|
||||
{
|
||||
blocked.Remove(thisnode);
|
||||
if (B.ContainsKey(node))
|
||||
{
|
||||
foreach (var n in B[node])
|
||||
{
|
||||
if (!stack.Contains(n))
|
||||
{
|
||||
stack.Push(n);
|
||||
}
|
||||
}
|
||||
B[node].Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<List<TNode>> result = new List<List<TNode>>();
|
||||
var subGraph = Clone();
|
||||
|
||||
var sccs = new Stack<IEnumerable<TNode>>();
|
||||
foreach (var scc in StronglyConnectedComponents())
|
||||
{
|
||||
sccs.Push(scc);
|
||||
}
|
||||
|
||||
while (sccs.Count > 0)
|
||||
{
|
||||
var scc = new Stack<TNode>(sccs.Pop());
|
||||
var startNode = scc.Pop();
|
||||
var path = new Stack<TNode>();
|
||||
path.Push(startNode);
|
||||
var blocked = new HashSet<TNode>
|
||||
{
|
||||
startNode
|
||||
};
|
||||
var closed = new HashSet<TNode>();
|
||||
var B = new Dictionary<TNode, HashSet<TNode>>();
|
||||
var stack = new Stack<(TNode, Stack<TNode>)>();
|
||||
stack.Push((startNode, new Stack<TNode>(subGraph.Neighbors(startNode))));
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var entry = stack.Peek();
|
||||
var thisnode = entry.Item1;
|
||||
var neighbors = entry.Item2;
|
||||
|
||||
if (neighbors.Count > 0)
|
||||
{
|
||||
var nextNode = neighbors.Pop();
|
||||
|
||||
if (nextNode.Equals(startNode))
|
||||
{
|
||||
var resultPath = new List<TNode>();
|
||||
foreach (var v in path)
|
||||
{
|
||||
resultPath.Add(v);
|
||||
}
|
||||
result.Add(resultPath);
|
||||
foreach (var v in path)
|
||||
{
|
||||
closed.Add(v);
|
||||
}
|
||||
}
|
||||
else if (!blocked.Contains(nextNode))
|
||||
{
|
||||
path.Push(nextNode);
|
||||
stack.Push((nextNode, new Stack<TNode>(subGraph.Neighbors(nextNode))));
|
||||
closed.Remove(nextNode);
|
||||
blocked.Add(nextNode);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (neighbors.Count == 0)
|
||||
{
|
||||
if (closed.Contains(thisnode))
|
||||
{
|
||||
unblock(thisnode, blocked, B);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var neighbor in subGraph.Neighbors(thisnode))
|
||||
{
|
||||
if (!B.ContainsKey(neighbor))
|
||||
{
|
||||
B[neighbor] = new HashSet<TNode>();
|
||||
}
|
||||
B[neighbor].Add(thisnode);
|
||||
}
|
||||
}
|
||||
|
||||
stack.Pop();
|
||||
path.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
subGraph.RemoveNode(startNode);
|
||||
var H = subGraph.SubGraph(scc.ToArray());
|
||||
var HSccs = H.StronglyConnectedComponents();
|
||||
foreach (var HScc in HSccs)
|
||||
{
|
||||
sccs.Push(HScc);
|
||||
}
|
||||
}
|
||||
|
||||
return result.Distinct(new SimpleCycleComparer<TNode>());
|
||||
}
|
||||
|
||||
protected IEnumerable<IEnumerable<TNode>> StronglyConnectedComponents()
|
||||
{
|
||||
var preorder = new Dictionary<TNode, uint>();
|
||||
var lowlink = new Dictionary<TNode, uint>();
|
||||
var sccFound = new Dictionary<TNode, bool>();
|
||||
var sccQueue = new Stack<TNode>();
|
||||
|
||||
uint preorderCounter = 0;
|
||||
|
||||
foreach (var source in Nodes)
|
||||
{
|
||||
if (!sccFound.ContainsKey(source))
|
||||
{
|
||||
var queue = new Stack<TNode>();
|
||||
queue.Push(source);
|
||||
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
var v = queue.Peek();
|
||||
if (!preorder.ContainsKey(v))
|
||||
{
|
||||
preorderCounter++;
|
||||
preorder[v] = preorderCounter;
|
||||
}
|
||||
|
||||
var done = true;
|
||||
var vNeighbors = Neighbors(v);
|
||||
foreach (var w in vNeighbors)
|
||||
{
|
||||
if (!preorder.ContainsKey(w))
|
||||
{
|
||||
queue.Push(w);
|
||||
done = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (done)
|
||||
{
|
||||
lowlink[v] = preorder[v];
|
||||
foreach (var w in vNeighbors)
|
||||
{
|
||||
if (!sccFound.ContainsKey(w))
|
||||
{
|
||||
if (preorder[w] > preorder[v])
|
||||
{
|
||||
lowlink[v] = Math.Min(lowlink[v], lowlink[w]);
|
||||
}
|
||||
else
|
||||
{
|
||||
lowlink[v] = Math.Min(lowlink[v], preorder[w]);
|
||||
}
|
||||
}
|
||||
}
|
||||
queue.Pop();
|
||||
if (lowlink[v] == preorder[v])
|
||||
{
|
||||
sccFound[v] = true;
|
||||
var scc = new List<TNode>() { v };
|
||||
while (sccQueue.Count > 0 && preorder[sccQueue.Peek()] > preorder[v])
|
||||
{
|
||||
var k = sccQueue.Pop();
|
||||
sccFound[k] = true;
|
||||
scc.Add(k);
|
||||
}
|
||||
|
||||
yield return scc;
|
||||
}
|
||||
else
|
||||
{
|
||||
sccQueue.Push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Encompass
|
||||
{
|
||||
internal class SimpleCycleComparer<TNode> : IEqualityComparer<IEnumerable<TNode>>
|
||||
{
|
||||
public bool Equals(IEnumerable<TNode> x, IEnumerable<TNode> y)
|
||||
{
|
||||
return x.SequenceEqual(y);
|
||||
}
|
||||
|
||||
public int GetHashCode(IEnumerable<TNode> obj)
|
||||
{
|
||||
return obj.Aggregate(0, (current, next) => current.GetHashCode() ^ next.GetHashCode());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,8 +3,6 @@ using System.Collections.Generic;
|
|||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using Encompass.Exceptions;
|
||||
using MoonTools.Core.Graph;
|
||||
using MoonTools.Core.Graph.Extensions;
|
||||
|
||||
namespace Encompass
|
||||
{
|
||||
|
@ -20,7 +18,7 @@ namespace Encompass
|
|||
{
|
||||
private readonly int _entityCapacity;
|
||||
private readonly List<Engine> _engines = new List<Engine>();
|
||||
private readonly DirectedGraph<Engine, Unit> _engineGraph = GraphBuilder.DirectedGraph<Engine>();
|
||||
private readonly DirectedGraph<Engine> _engineGraph = new DirectedGraph<Engine>();
|
||||
private readonly ComponentStore _startingExistingComponentStore;
|
||||
private readonly ComponentStore _startingUpToDateComponentStore;
|
||||
|
||||
|
@ -130,16 +128,29 @@ namespace Encompass
|
|||
var messageReceiveTypes = engine.ReceiveTypes;
|
||||
var messageSendTypes = engine.SendTypes;
|
||||
|
||||
RegisterMessageTypes(engine.ReceiveTypes.Union(engine.SendTypes));
|
||||
RegisterMessageTypes(engine.ReceiveTypes);
|
||||
RegisterMessageTypes(engine.SendTypes);
|
||||
|
||||
foreach (var writeImmediateType in engine.WriteImmediateTypes.Intersect(engine.ReadImmediateTypes))
|
||||
foreach (var writeImmediateType in engine.WriteImmediateTypes)
|
||||
{
|
||||
throw new EngineSelfCycleException("Engine {0} both writes and reads immediate Component {1}", engine.GetType().Name, writeImmediateType.Name);
|
||||
foreach (var readImmediateType in engine.ReadImmediateTypes)
|
||||
{
|
||||
if (readImmediateType == writeImmediateType)
|
||||
{
|
||||
throw new EngineSelfCycleException("Engine {0} both writes and reads immediate Component {1}", engine.GetType().Name, writeImmediateType.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var messageType in messageReceiveTypes.Intersect(messageSendTypes))
|
||||
foreach (var messageReceiveType in messageReceiveTypes)
|
||||
{
|
||||
throw new EngineSelfCycleException("Engine {0} both receives and sends Message {1}", engine.GetType().Name, messageType.Name);
|
||||
foreach (var messageSendType in messageSendTypes)
|
||||
{
|
||||
if (messageReceiveType == messageSendType)
|
||||
{
|
||||
throw new EngineSelfCycleException("Engine {0} both receives and sends Message {1}", engine.GetType().Name, messageReceiveType.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (messageSendTypes.Count > 0 || engine.WriteImmediateTypes.Count > 0)
|
||||
|
@ -147,7 +158,7 @@ namespace Encompass
|
|||
_senders.Add(engine);
|
||||
}
|
||||
|
||||
foreach (var componentType in engine.QueryWithTypes.Union(engine.QueryWithoutTypes))
|
||||
foreach (var componentType in engine.QueryWithTypes)
|
||||
{
|
||||
_trackingManager.RegisterComponentTypeToEngine(componentType, engine);
|
||||
if (engine.ReadImmediateTypes.Contains(componentType))
|
||||
|
@ -156,7 +167,26 @@ namespace Encompass
|
|||
}
|
||||
}
|
||||
|
||||
foreach (var receiveType in engine.ReceiveTypes.Union(engine.ReadImmediateTypes))
|
||||
foreach (var componentType in engine.QueryWithoutTypes)
|
||||
{
|
||||
_trackingManager.RegisterComponentTypeToEngine(componentType, engine);
|
||||
if (engine.ReadImmediateTypes.Contains(componentType))
|
||||
{
|
||||
_trackingManager.RegisterImmediateComponentTypeToEngine(componentType, engine);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var receiveType in engine.ReceiveTypes)
|
||||
{
|
||||
if (!_typeToReaders.ContainsKey(receiveType))
|
||||
{
|
||||
_typeToReaders.Add(receiveType, new HashSet<Engine>());
|
||||
}
|
||||
|
||||
_typeToReaders[receiveType].Add(engine);
|
||||
}
|
||||
|
||||
foreach (var receiveType in engine.ReadImmediateTypes)
|
||||
{
|
||||
if (!_typeToReaders.ContainsKey(receiveType))
|
||||
{
|
||||
|
@ -214,7 +244,24 @@ namespace Encompass
|
|||
{
|
||||
foreach (var senderEngine in _senders)
|
||||
{
|
||||
foreach (var messageType in senderEngine.SendTypes.Union(senderEngine.WriteImmediateTypes))
|
||||
foreach (var messageType in senderEngine.SendTypes)
|
||||
{
|
||||
if (_typeToReaders.ContainsKey(messageType))
|
||||
{
|
||||
foreach (var readerEngine in _typeToReaders[messageType])
|
||||
{
|
||||
if (senderEngine != readerEngine)
|
||||
{
|
||||
if (!_engineGraph.Exists(senderEngine, readerEngine))
|
||||
{
|
||||
_engineGraph.AddEdge(senderEngine, readerEngine);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var messageType in senderEngine.WriteImmediateTypes)
|
||||
{
|
||||
if (_typeToReaders.ContainsKey(messageType))
|
||||
{
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MoonTools.Core.Graph" Version="1.0.0" />
|
||||
<PackageReference Include="MoonTools.FastCollections" Version="1.0.0" />
|
||||
<PackageReference Include="System.Collections.Immutable" Version="1.7.0" />
|
||||
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<RootNamespace>Tests</RootNamespace>
|
||||
<AssemblyName>EncompassECS.Framework.Tests</AssemblyName>
|
||||
|
|
Loading…
Reference in New Issue