- I overcomplicated in the beginning - It doesn't shorten the code that much but it provides a stable interface and it's easier to use so I guess it's nicefeature/tb.update
@@ -281,17 +281,14 @@ namespace TechbloxModdingAPI.Blocks.Engines | |||
for (int startIndex = 0; startIndex < startPorts.Length; startIndex++) | |||
{ | |||
PortEntityStruct startPES = entitiesDB.QueryEntity<PortEntityStruct>(startPorts[startIndex]); | |||
foreach (var wire in entitiesDB.QueryEntitiesOptional<WireEntityStruct>( | |||
foreach (var wireOpt in entitiesDB.QueryEntitiesOptional<WireEntityStruct>( | |||
NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group)) | |||
{ | |||
} | |||
for (int w = 0; w < count; w++) | |||
{ | |||
if ((wires[w].destinationPortUsage == endPES.usage && wires[w].destinationBlockEGID == endBlock) | |||
&& (wires[w].sourcePortUsage == startPES.usage && wires[w].sourceBlockEGID == startBlock)) | |||
var wire = wireOpt.Get(); | |||
if ((wire.destinationPortUsage == endPES.usage && wire.destinationBlockEGID == endBlock) | |||
&& (wire.sourcePortUsage == startPES.usage && wire.sourceBlockEGID == startBlock)) | |||
{ | |||
return new EGID(ids[w], NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group); | |||
return wireOpt.EGID; | |||
} | |||
} | |||
} | |||
@@ -68,9 +68,10 @@ namespace TechbloxModdingAPI.Utility | |||
/// <typeparam name="T"></typeparam> | |||
/// <typeparam name="TR"></typeparam> | |||
/// <returns></returns> | |||
public static RefCollection<T> QueryEntitiesOptional<T>(this EntitiesDB entitiesDB, ExclusiveGroupStruct group) where T : struct, IBaseEntityComponent | |||
public static RefCollection<T> QueryEntitiesOptional<T>(this EntitiesDB entitiesDB, ExclusiveGroupStruct group) where T : struct, IEntityViewComponent | |||
{ | |||
return entitiesDB.QueryEntities<T>(group); | |||
var (buffer, ids, count) = entitiesDB.QueryEntities<T>(group); | |||
return new RefCollection<T>(count, buffer, ids, group); | |||
} | |||
} | |||
} |
@@ -102,14 +102,19 @@ namespace TechbloxModdingAPI.Utility | |||
ChangesToPublish[typeof(T)] = (0, changes); | |||
} | |||
public static IEnumerable<TR> QueryEntities<T, TR>(this EntitiesDB entitiesDB, ExclusiveGroupStruct group, | |||
ManagedApiExtensions.EntityEnumeratorSelect<T, TR> select) where T : unmanaged, IEntityComponent | |||
/// <summary> | |||
/// Query entities as OptionalRefs. The elements always exist, it's just a nice way to encapsulate the data. | |||
/// </summary> | |||
/// <param name="entitiesDB"></param> | |||
/// <param name="group"></param> | |||
/// <param name="select"></param> | |||
/// <typeparam name="T"></typeparam> | |||
/// <typeparam name="TR"></typeparam> | |||
/// <returns></returns> | |||
public static RefCollection<T> QueryEntitiesOptional<T>(this EntitiesDB entitiesDB, ExclusiveGroupStruct group) where T : unmanaged, IEntityComponent | |||
{ | |||
var (coll, ids, count) = entitiesDB.QueryEntities<T>(group); | |||
for (uint i = 0; i < count; i++) | |||
{ | |||
yield return select(ref coll[i], new EGID(ids[i], group)); | |||
} | |||
var (buffer, ids, count) = entitiesDB.QueryEntities<T>(group); | |||
return new RefCollection<T>(count, buffer, ids, group); | |||
} | |||
} | |||
} |
@@ -77,6 +77,11 @@ namespace TechbloxModdingAPI.Utility | |||
set => Get() = value; | |||
} | |||
/// <summary> | |||
/// The ID of the entity this component belongs to. | |||
/// </summary> | |||
public EGID EGID => entityId; | |||
public bool Exists => state != State.Empty; | |||
public T? Nullable() => this ? Get() : default; | |||
@@ -6,83 +6,66 @@ using Svelto.ECS.Internal; | |||
namespace TechbloxModdingAPI.Utility | |||
{ | |||
public ref struct RefCollection<T> where T : struct, IBaseEntityComponent | |||
public readonly ref struct RefCollection<T> where T : struct, IBaseEntityComponent | |||
{ | |||
private readonly bool managed; | |||
private int count; | |||
private NB<T> nativeArray; | |||
private MB<T> managedArray; | |||
private NativeEntityIDs nativeIDs; | |||
private ManagedEntityIDs managedIDs; | |||
private readonly int count; | |||
private readonly NB<T> nativeArray; | |||
private readonly MB<T> managedArray; | |||
private readonly NativeEntityIDs nativeIDs; | |||
private readonly ManagedEntityIDs managedIDs; | |||
private readonly ExclusiveGroupStruct group; | |||
private RefCollection(EntityCollection<T> coll, T inst = default) | |||
public RefCollection(int count, MB<T> managedArray, ManagedEntityIDs managedIDs, ExclusiveGroupStruct group) | |||
{ | |||
if (inst is IEntityComponent) | |||
{ | |||
DeconstructCollection<T, T>(coll); | |||
} | |||
if (typeof(T).IsAssignableFrom(typeof(IEntityViewComponent))) | |||
{ | |||
(managedArray, managedIDs, count) = coll2; | |||
} | |||
this.count = count; | |||
this.managedArray = managedArray; | |||
this.managedIDs = managedIDs; | |||
this.group = group; | |||
managed = true; | |||
nativeArray = default; | |||
nativeIDs = default; | |||
} | |||
private void DeconstructCollection<TM, TN>(EntityCollection<T> coll) where TM : struct, IEntityViewComponent | |||
where TN : unmanaged, IEntityComponent | |||
public RefCollection(int count, NB<T> nativeArray, NativeEntityIDs nativeIDs, ExclusiveGroupStruct group) | |||
{ | |||
switch (coll) | |||
{ | |||
case EntityCollection<TM> cm: | |||
{ | |||
MB<TM> ma; | |||
(ma, managedIDs, count) = cm; | |||
if (ma is MB<T> mb) | |||
managedArray = mb; | |||
else | |||
throw new InvalidCastException("Expected managed buffer in managed entity collection! Wut"); | |||
break; | |||
} | |||
case EntityCollection<TN> cn: | |||
{ | |||
NB<TN> na; | |||
(na, nativeIDs, count) = cn; | |||
if (na is NB<T> nb) | |||
nativeArray = nb; | |||
else | |||
throw new InvalidCastException("Expected native buffer in native entity collection! Wut"); | |||
break; | |||
} | |||
} | |||
} | |||
public static implicit operator RefCollection<T>(EntityCollection<T> coll) | |||
{ | |||
return new RefCollection<T>(coll); | |||
this.count = count; | |||
this.nativeArray = nativeArray; | |||
this.nativeIDs = nativeIDs; | |||
this.group = group; | |||
managed = false; | |||
} | |||
public Enumerator GetEnumerator() => new(this); | |||
public ref struct Enumerator | |||
{ | |||
private RefCollection<T> collection; | |||
private uint index; | |||
private RefCollection<T> coll; | |||
private int index; | |||
public Enumerator(RefCollection<T> collection) | |||
{ | |||
index = default; | |||
this.collection = collection; | |||
index = -1; | |||
coll = collection; | |||
} | |||
public OptionalRef<T> Current => collection.coll.[index]; | |||
public OptionalRef<T> Current | |||
{ | |||
get | |||
{ | |||
if (coll.count <= index && index >= 0) return default; | |||
if (coll.managed) | |||
return new OptionalRef<T>(coll.managedArray, (uint)index, | |||
new EGID(coll.managedIDs[index], coll.group)); | |||
return new OptionalRef<T>(coll.nativeArray, (uint)index, | |||
new EGID(coll.nativeIDs[index], coll.group)); | |||
} | |||
} | |||
public bool MoveNext() | |||
{ | |||
return true; | |||
return ++index < coll.count; | |||
} | |||
} | |||
private static void Test<TN>(EntityCollection<TN> coll) where TN : unmanaged, IEntityComponent | |||
{ | |||
} | |||
} | |||
} |