What have I got myself intofeature/tb.update
@@ -22,7 +22,7 @@ namespace TechbloxModdingAPI.Blocks.Engines | |||
{ | |||
private static IEntityFunctions _entityFunctions; | |||
private static MachineGraphConnectionEntityFactory _connectionFactory; | |||
private NativeHashSet<ulong> removedConnections = new(2000, Allocator.Persistent); | |||
private NativeHashSet<ulong> removedConnections; | |||
public bool RemoveBlock(EGID target) | |||
{ | |||
@@ -44,6 +44,7 @@ namespace TechbloxModdingAPI.Blocks.Engines | |||
public void Ready() | |||
{ | |||
removedConnections = new(2000, Allocator.Persistent); | |||
} | |||
public EntitiesDB entitiesDB { get; set; } | |||
@@ -77,7 +78,8 @@ namespace TechbloxModdingAPI.Blocks.Engines | |||
public JobHandle DeterministicStep(in float deltaTime, JobHandle inputDeps) | |||
{ | |||
removedConnections.Clear(); | |||
if (removedConnections.IsCreated) | |||
removedConnections.Clear(); | |||
return default; | |||
} | |||
} |
@@ -226,27 +226,27 @@ namespace TechbloxModdingAPI.Blocks.Engines | |||
uint entityID = (output ? ports.firstOutputID : ports.firstInputID) + i; | |||
if (!mapper.TryGetArrayAndEntityIndex(entityID, out var index, out var array) || | |||
array[index].usage != portUsage) continue; | |||
return new OptionalRef<PortEntityStruct>(array, index); | |||
return new OptionalRef<PortEntityStruct>(array, index, new EGID(entityID, group)); | |||
} | |||
return default; | |||
} | |||
public ref WireEntityStruct MatchPortToWire(PortEntityStruct port, EGID blockID, out bool exists) | |||
public OptionalRef<WireEntityStruct> MatchPortToWire(PortEntityStruct port, EGID blockID, out EGID wireID) | |||
{ | |||
var (wires, count) = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group); | |||
var (wires, ids, count) = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group); | |||
for (uint i = 0; i < count; i++) | |||
{ | |||
if ((wires[i].destinationPortUsage == port.usage && wires[i].destinationBlockEGID == blockID) | |||
|| (wires[i].sourcePortUsage == port.usage && wires[i].sourceBlockEGID == blockID)) | |||
{ | |||
exists = true; | |||
return ref wires[i]; | |||
wireID = new EGID(ids[i], BuildModeWiresGroups.WiresGroup.Group); | |||
return new OptionalRef<WireEntityStruct>(wires, i); | |||
} | |||
} | |||
exists = false; | |||
WireEntityStruct[] defRef = new WireEntityStruct[1]; | |||
return ref defRef[0]; | |||
wireID = default; | |||
return default; | |||
} | |||
public EGID MatchBlocksToWire(EGID startBlock, EGID endBlock, byte startPort = byte.MaxValue, byte endPort = byte.MaxValue) | |||
@@ -275,19 +275,23 @@ namespace TechbloxModdingAPI.Blocks.Engines | |||
endPorts = new EGID[] {new EGID(ports.firstInputID + endPort, NamedExclusiveGroup<BuildModeWiresGroups.InputPortsGroup>.Group) }; | |||
} | |||
var (wires, count) = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group); | |||
for (int endIndex = 0; endIndex < endPorts.Length; endIndex++) | |||
{ | |||
PortEntityStruct endPES = entitiesDB.QueryEntity<PortEntityStruct>(endPorts[endIndex]); | |||
for (int startIndex = 0; startIndex < startPorts.Length; startIndex++) | |||
{ | |||
PortEntityStruct startPES = entitiesDB.QueryEntity<PortEntityStruct>(startPorts[startIndex]); | |||
foreach (var wire 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)) | |||
{ | |||
return wires[w].ID; | |||
return new EGID(ids[w], NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group); | |||
} | |||
} | |||
} | |||
@@ -308,12 +312,12 @@ namespace TechbloxModdingAPI.Blocks.Engines | |||
public EGID[] GetElectricBlocks() | |||
{ | |||
var res = new FasterList<EGID>(); | |||
foreach (var ((coll, count), _) in entitiesDB.QueryEntities<BlockPortsStruct>()) | |||
foreach (var ((coll, ids, count), _) in entitiesDB.QueryEntities<BlockPortsStruct>()) | |||
{ | |||
for (int i = 0; i < count; i++) | |||
{ | |||
ref BlockPortsStruct s = ref coll[i]; | |||
//res.Add(s.ID); - TODO | |||
//res.Add(s.ID); - TODO: Would need to search for the groups for each block | |||
} | |||
} | |||
@@ -46,9 +46,9 @@ namespace TechbloxModdingAPI.Blocks | |||
/// <returns>The connected wire.</returns> | |||
/// <param name="portId">Port identifier.</param> | |||
/// <param name="connected">Whether the port has a wire connected to it.</param> | |||
protected ref WireEntityStruct GetConnectedWire(PortEntityStruct port, out bool connected) | |||
protected OptionalRef<WireEntityStruct> GetConnectedWire(PortEntityStruct port, out EGID egid) | |||
{ | |||
return ref SignalEngine.MatchPortToWire(port, Id, out connected); | |||
return SignalEngine.MatchPortToWire(port, Id, out egid); | |||
} | |||
/// <summary> | |||
@@ -5,6 +5,7 @@ using Svelto.ECS; | |||
using Svelto.ECS.Experimental; | |||
using TechbloxModdingAPI.Blocks.Engines; | |||
using TechbloxModdingAPI.Utility; | |||
namespace TechbloxModdingAPI.Blocks | |||
{ | |||
@@ -45,9 +46,9 @@ namespace TechbloxModdingAPI.Blocks | |||
{ | |||
var port = signalEngine.MatchBlockIOToPort(end, endPort, false); | |||
if (!port) return null; | |||
WireEntityStruct wire = signalEngine.MatchPortToWire(port, end.Id, out var exists); | |||
return exists | |||
? new Wire(wire.sourceBlockEGID, end.Id, wire.sourcePortUsage, endPort, wire.ID, false) | |||
var wire = signalEngine.MatchPortToWire(port, end.Id, out var egid); | |||
return wire | |||
? new Wire(wire.Get().sourceBlockEGID, end.Id, wire.Get().sourcePortUsage, endPort, egid, false) | |||
: null; | |||
} | |||
@@ -62,9 +63,9 @@ namespace TechbloxModdingAPI.Blocks | |||
{ | |||
var port = signalEngine.MatchBlockIOToPort(start, startPort, true); | |||
if (!port) return null; | |||
WireEntityStruct wire = signalEngine.MatchPortToWire(port, start.Id, out var exists); | |||
return exists | |||
? new Wire(start.Id, wire.destinationBlockEGID, startPort, wire.destinationPortUsage, wire.ID, false) | |||
var wire = signalEngine.MatchPortToWire(port, start.Id, out var egid); | |||
return wire | |||
? new Wire(start.Id, wire.Get().destinationBlockEGID, startPort, wire.Get().destinationPortUsage, egid, false) | |||
: null; | |||
} | |||
@@ -1,3 +1,5 @@ | |||
using System.Collections; | |||
using System.Collections.Generic; | |||
using Svelto.ECS; | |||
using Svelto.ECS.Hybrid; | |||
@@ -18,7 +20,7 @@ namespace TechbloxModdingAPI.Utility | |||
{ | |||
return entitiesDB.TryQueryEntitiesAndIndex<T>(egid, out uint index, out var array) | |||
? new OptionalRef<T>(array, index) | |||
: new OptionalRef<T>(); | |||
: new OptionalRef<T>(); | |||
} | |||
/// <summary> | |||
@@ -29,7 +31,8 @@ namespace TechbloxModdingAPI.Utility | |||
/// <param name="group">The group of the entity if the object can have multiple</param> | |||
/// <typeparam name="T">The component to query</typeparam> | |||
/// <returns>A reference to the component or a dummy value</returns> | |||
public static OptionalRef<T> QueryEntityOptional<T>(this EntitiesDB entitiesDB, EcsObjectBase obj, ExclusiveGroupStruct group = default) | |||
public static OptionalRef<T> QueryEntityOptional<T>(this EntitiesDB entitiesDB, EcsObjectBase obj, | |||
ExclusiveGroupStruct group = default) | |||
where T : struct, IEntityViewComponent | |||
{ | |||
EGID id = group == ExclusiveGroupStruct.Invalid ? obj.Id : new EGID(obj.Id.entityID, group); | |||
@@ -45,7 +48,8 @@ namespace TechbloxModdingAPI.Utility | |||
/// <param name="group">The group of the entity if the object can have multiple</param> | |||
/// <typeparam name="T">The component to query</typeparam> | |||
/// <returns>A reference to the component or a dummy value</returns> | |||
public static ref T QueryEntityOrDefault<T>(this EntitiesDB entitiesDB, EcsObjectBase obj, ExclusiveGroupStruct group = default) | |||
public static ref T QueryEntityOrDefault<T>(this EntitiesDB entitiesDB, EcsObjectBase obj, | |||
ExclusiveGroupStruct group = default) | |||
where T : struct, IEntityViewComponent | |||
{ | |||
EGID id = group == ExclusiveGroupStruct.Invalid ? obj.Id : new EGID(obj.Id.entityID, group); | |||
@@ -54,5 +58,19 @@ namespace TechbloxModdingAPI.Utility | |||
if (obj.InitData.Valid) return ref obj.InitData.Initializer(id).GetOrAdd<T>(); | |||
return ref opt.Get(); //Default value | |||
} | |||
/// <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 : struct, IBaseEntityComponent | |||
{ | |||
return entitiesDB.QueryEntities<T>(group); | |||
} | |||
} | |||
} |
@@ -22,7 +22,7 @@ namespace TechbloxModdingAPI.Utility | |||
{ | |||
return entitiesDB.TryQueryEntitiesAndIndex<T>(egid, out uint index, out var array) | |||
? new OptionalRef<T>(array, index) | |||
: new OptionalRef<T>(); | |||
: new OptionalRef<T>(); | |||
} | |||
/// <summary> | |||
@@ -33,7 +33,8 @@ namespace TechbloxModdingAPI.Utility | |||
/// <param name="group">The group of the entity if the object can have multiple</param> | |||
/// <typeparam name="T">The component to query</typeparam> | |||
/// <returns>A reference to the component or a dummy value</returns> | |||
public static OptionalRef<T> QueryEntityOptional<T>(this EntitiesDB entitiesDB, EcsObjectBase obj, ExclusiveGroupStruct group = default) | |||
public static OptionalRef<T> QueryEntityOptional<T>(this EntitiesDB entitiesDB, EcsObjectBase obj, | |||
ExclusiveGroupStruct group = default) | |||
where T : unmanaged, IEntityComponent | |||
{ | |||
EGID id = group == ExclusiveGroupStruct.Invalid ? obj.Id : new EGID(obj.Id.entityID, group); | |||
@@ -49,7 +50,8 @@ namespace TechbloxModdingAPI.Utility | |||
/// <param name="group">The group of the entity if the object can have multiple</param> | |||
/// <typeparam name="T">The component to query</typeparam> | |||
/// <returns>A reference to the component or a dummy value</returns> | |||
public static ref T QueryEntityOrDefault<T>(this EntitiesDB entitiesDB, EcsObjectBase obj, ExclusiveGroupStruct group = default) | |||
public static ref T QueryEntityOrDefault<T>(this EntitiesDB entitiesDB, EcsObjectBase obj, | |||
ExclusiveGroupStruct group = default) | |||
where T : unmanaged, IEntityComponent | |||
{ | |||
EGID id = group == ExclusiveGroupStruct.Invalid ? obj.Id : new EGID(obj.Id.entityID, group); | |||
@@ -76,8 +78,9 @@ namespace TechbloxModdingAPI.Utility | |||
/// <typeparam name="T">The component that changed</typeparam> | |||
public static void PublishEntityChangeDelayed<T>(this EntitiesDB entitiesDB, EGID id, int limit = 80) | |||
where T : unmanaged, IEntityComponent | |||
{ //TODO: Doesn't seem to help | |||
if(!ChangesToPublish.ContainsKey(typeof(T))) | |||
{ | |||
//TODO: Doesn't seem to help | |||
if (!ChangesToPublish.ContainsKey(typeof(T))) | |||
ChangesToPublish.Add(typeof(T), (0, new HashSet<EGID>())); | |||
var changes = ChangesToPublish[typeof(T)].Changes; | |||
if (changes.Contains(id)) return; | |||
@@ -98,5 +101,15 @@ namespace TechbloxModdingAPI.Utility | |||
yield return Yield.It; | |||
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 | |||
{ | |||
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)); | |||
} | |||
} | |||
} | |||
} |
@@ -4,8 +4,9 @@ using Svelto.ECS; | |||
namespace TechbloxModdingAPI.Utility | |||
{ | |||
public ref struct OptionalRef<T> where T : struct, IEntityComponent | |||
public ref struct OptionalRef<T> where T : struct, IBaseEntityComponent | |||
{ | |||
private readonly EGID entityId; | |||
private readonly State state; | |||
private readonly uint index; | |||
private NB<T> array; | |||
@@ -13,19 +14,21 @@ namespace TechbloxModdingAPI.Utility | |||
private readonly EntityInitializer initializer; | |||
//The possible fields are: (index && (array || managedArray)) || initializer | |||
public OptionalRef(NB<T> array, uint index) | |||
public OptionalRef(NB<T> array, uint index, EGID entityId = default) | |||
{ | |||
state = State.Native; | |||
this.array = array; | |||
this.index = index; | |||
this.entityId = entityId; | |||
initializer = default; | |||
} | |||
public OptionalRef(MB<T> array, uint index) | |||
public OptionalRef(MB<T> array, uint index, EGID entityId = default) | |||
{ | |||
state = State.Managed; | |||
managedArray = array; | |||
this.index = index; | |||
this.entityId = entityId; | |||
initializer = default; | |||
this.array = default; | |||
} | |||
@@ -35,8 +38,9 @@ namespace TechbloxModdingAPI.Utility | |||
/// </summary> | |||
/// <param name="obj">The object with the initializer</param> | |||
/// <param name="unmanaged">Whether the struct is unmanaged</param> | |||
public OptionalRef(EcsObjectBase obj, bool unmanaged) | |||
public OptionalRef(EcsObjectBase obj, bool unmanaged, EGID entityId = default) | |||
{ | |||
this.entityId = entityId; | |||
if (obj.InitData.Valid) | |||
{ | |||
initializer = obj.InitData.Initializer(obj.Id); | |||
@@ -80,6 +84,8 @@ namespace TechbloxModdingAPI.Utility | |||
public static implicit operator bool(OptionalRef<T> opt) => opt.state != State.Empty; | |||
public static implicit operator EGID(OptionalRef<T> opt) => opt.entityId; | |||
/// <summary> | |||
/// Creates an instance of a struct T that can be referenced. | |||
/// </summary> | |||
@@ -0,0 +1,88 @@ | |||
using System; | |||
using Svelto.DataStructures; | |||
using Svelto.ECS; | |||
using Svelto.ECS.Hybrid; | |||
using Svelto.ECS.Internal; | |||
namespace TechbloxModdingAPI.Utility | |||
{ | |||
public 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 RefCollection(EntityCollection<T> coll, T inst = default) | |||
{ | |||
if (inst is IEntityComponent) | |||
{ | |||
DeconstructCollection<T, T>(coll); | |||
} | |||
if (typeof(T).IsAssignableFrom(typeof(IEntityViewComponent))) | |||
{ | |||
(managedArray, managedIDs, count) = coll2; | |||
} | |||
} | |||
private void DeconstructCollection<TM, TN>(EntityCollection<T> coll) where TM : struct, IEntityViewComponent | |||
where TN : unmanaged, IEntityComponent | |||
{ | |||
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); | |||
} | |||
public Enumerator GetEnumerator() => new(this); | |||
public ref struct Enumerator | |||
{ | |||
private RefCollection<T> collection; | |||
private uint index; | |||
public Enumerator(RefCollection<T> collection) | |||
{ | |||
index = default; | |||
this.collection = collection; | |||
} | |||
public OptionalRef<T> Current => collection.coll.[index]; | |||
public bool MoveNext() | |||
{ | |||
return true; | |||
} | |||
} | |||
private static void Test<TN>(EntityCollection<TN> coll) where TN : unmanaged, IEntityComponent | |||
{ | |||
} | |||
} | |||
} |