Fix RefCollection and start using it to query multiple users

- 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 nice
This commit is contained in:
Norbi Peti 2022-09-29 01:26:51 +02:00
parent f70b65e796
commit 5117b69500
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
5 changed files with 64 additions and 73 deletions

View file

@ -281,17 +281,14 @@ namespace TechbloxModdingAPI.Blocks.Engines
for (int startIndex = 0; startIndex < startPorts.Length; startIndex++) for (int startIndex = 0; startIndex < startPorts.Length; startIndex++)
{ {
PortEntityStruct startPES = entitiesDB.QueryEntity<PortEntityStruct>(startPorts[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)) NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group))
{ {
var wire = wireOpt.Get();
} if ((wire.destinationPortUsage == endPES.usage && wire.destinationBlockEGID == endBlock)
for (int w = 0; w < count; w++) && (wire.sourcePortUsage == startPES.usage && wire.sourceBlockEGID == startBlock))
{ {
if ((wires[w].destinationPortUsage == endPES.usage && wires[w].destinationBlockEGID == endBlock) return wireOpt.EGID;
&& (wires[w].sourcePortUsage == startPES.usage && wires[w].sourceBlockEGID == startBlock))
{
return new EGID(ids[w], NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group);
} }
} }
} }

View file

@ -68,9 +68,10 @@ namespace TechbloxModdingAPI.Utility
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <typeparam name="TR"></typeparam> /// <typeparam name="TR"></typeparam>
/// <returns></returns> /// <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);
} }
} }
} }

View file

@ -102,14 +102,19 @@ namespace TechbloxModdingAPI.Utility
ChangesToPublish[typeof(T)] = (0, changes); ChangesToPublish[typeof(T)] = (0, changes);
} }
public static IEnumerable<TR> QueryEntities<T, TR>(this EntitiesDB entitiesDB, ExclusiveGroupStruct group, /// <summary>
ManagedApiExtensions.EntityEnumeratorSelect<T, TR> select) where T : unmanaged, IEntityComponent /// 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); var (buffer, ids, count) = entitiesDB.QueryEntities<T>(group);
for (uint i = 0; i < count; i++) return new RefCollection<T>(count, buffer, ids, group);
{
yield return select(ref coll[i], new EGID(ids[i], group));
}
} }
} }
} }

View file

@ -77,6 +77,11 @@ namespace TechbloxModdingAPI.Utility
set => Get() = value; 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 bool Exists => state != State.Empty;
public T? Nullable() => this ? Get() : default; public T? Nullable() => this ? Get() : default;

View file

@ -6,83 +6,66 @@ using Svelto.ECS.Internal;
namespace TechbloxModdingAPI.Utility 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 readonly bool managed;
private int count; private readonly int count;
private NB<T> nativeArray; private readonly NB<T> nativeArray;
private MB<T> managedArray; private readonly MB<T> managedArray;
private NativeEntityIDs nativeIDs; private readonly NativeEntityIDs nativeIDs;
private ManagedEntityIDs managedIDs; 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) this.count = count;
{ this.managedArray = managedArray;
DeconstructCollection<T, T>(coll); this.managedIDs = managedIDs;
} this.group = group;
if (typeof(T).IsAssignableFrom(typeof(IEntityViewComponent))) managed = true;
{ nativeArray = default;
(managedArray, managedIDs, count) = coll2; nativeIDs = default;
}
} }
private void DeconstructCollection<TM, TN>(EntityCollection<T> coll) where TM : struct, IEntityViewComponent public RefCollection(int count, NB<T> nativeArray, NativeEntityIDs nativeIDs, ExclusiveGroupStruct group)
where TN : unmanaged, IEntityComponent
{ {
switch (coll) this.count = count;
{ this.nativeArray = nativeArray;
case EntityCollection<TM> cm: this.nativeIDs = nativeIDs;
{ this.group = group;
MB<TM> ma; managed = false;
(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);
} }
public Enumerator GetEnumerator() => new(this); public Enumerator GetEnumerator() => new(this);
public ref struct Enumerator public ref struct Enumerator
{ {
private RefCollection<T> collection; private RefCollection<T> coll;
private uint index; private int index;
public Enumerator(RefCollection<T> collection) public Enumerator(RefCollection<T> collection)
{ {
index = default; index = -1;
this.collection = collection; 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() public bool MoveNext()
{ {
return true; return ++index < coll.count;
} }
}
private static void Test<TN>(EntityCollection<TN> coll) where TN : unmanaged, IEntityComponent
{
} }
} }
} }