Browse Source

Start updating to Techblox 2022.08.11.09.42 and start work on RefCollection

What have I got myself into
feature/tb.update
NorbiPeti 1 year ago
parent
commit
f70b65e796
Signed by: NorbiPeti <szatmari.norbert.peter@gmail.com> GPG Key ID: DBA4C4549A927E56
8 changed files with 166 additions and 34 deletions
  1. +4
    -2
      TechbloxModdingAPI/Blocks/Engines/RemovalEngine.cs
  2. +16
    -12
      TechbloxModdingAPI/Blocks/Engines/SignalEngine.cs
  3. +2
    -2
      TechbloxModdingAPI/Blocks/SignalingBlock.cs
  4. +7
    -6
      TechbloxModdingAPI/Blocks/Wire.cs
  5. +21
    -3
      TechbloxModdingAPI/Utility/ManagedApiExtensions.cs
  6. +18
    -5
      TechbloxModdingAPI/Utility/NativeApiExtensions.cs
  7. +10
    -4
      TechbloxModdingAPI/Utility/OptionalRef.cs
  8. +88
    -0
      TechbloxModdingAPI/Utility/RefCollection.cs

+ 4
- 2
TechbloxModdingAPI/Blocks/Engines/RemovalEngine.cs View File

@@ -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;
}
}

+ 16
- 12
TechbloxModdingAPI/Blocks/Engines/SignalEngine.cs View File

@@ -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
}
}



+ 2
- 2
TechbloxModdingAPI/Blocks/SignalingBlock.cs View File

@@ -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>


+ 7
- 6
TechbloxModdingAPI/Blocks/Wire.cs View File

@@ -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;
}



+ 21
- 3
TechbloxModdingAPI/Utility/ManagedApiExtensions.cs View File

@@ -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);
}
}
}

+ 18
- 5
TechbloxModdingAPI/Utility/NativeApiExtensions.cs View File

@@ -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));
}
}
}
}

+ 10
- 4
TechbloxModdingAPI/Utility/OptionalRef.cs View File

@@ -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>


+ 88
- 0
TechbloxModdingAPI/Utility/RefCollection.cs View File

@@ -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
{
}
}
}

Loading…
Cancel
Save