From 2d99d1d4783171c9751850a00de0cb355697e35b Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 10 May 2021 02:04:59 +0200 Subject: [PATCH 1/7] Generalize optional references and init data Added extension methods to query data from ECS objects Added base class for ECS objects Added support for representing in-construction ECS objects with an OptionalRef --- TechbloxModdingAPI/Block.cs | 10 ++-- TechbloxModdingAPI/Blocks/BlockEngine.cs | 19 ++++--- .../BlockEngineInit.cs => EcsObjectBase.cs} | 30 +++++++---- TechbloxModdingAPI/Utility/ApiExtensions.cs | 53 +++++++++++++++++++ TechbloxModdingAPI/Utility/OptionalRef.cs | 40 ++++++++++---- 5 files changed, 120 insertions(+), 32 deletions(-) rename TechbloxModdingAPI/{Blocks/BlockEngineInit.cs => EcsObjectBase.cs} (58%) create mode 100644 TechbloxModdingAPI/Utility/ApiExtensions.cs diff --git a/TechbloxModdingAPI/Block.cs b/TechbloxModdingAPI/Block.cs index 4729a91..f99ca28 100644 --- a/TechbloxModdingAPI/Block.cs +++ b/TechbloxModdingAPI/Block.cs @@ -20,7 +20,7 @@ namespace TechbloxModdingAPI /// A single (perhaps scaled) block. Properties may return default values if the block is removed and then setting them is ignored. /// For specific block type operations, use the specialised block classes in the TechbloxModdingAPI.Blocks namespace. /// - public class Block : IEquatable, IEquatable + public class Block : EcsObjectBase, IEquatable, IEquatable { protected static readonly PlacementEngine PlacementEngine = new PlacementEngine(); protected static readonly MovementEngine MovementEngine = new MovementEngine(); @@ -78,8 +78,7 @@ namespace TechbloxModdingAPI var initializer = PlacementEngine.PlaceBlock(block, position, player, autoWire); var egid = initializer.EGID; var bl = New(egid.entityID, egid.groupID); - bl.InitData.Group = BlockEngine.InitGroup(initializer); - bl.InitData.Reference = initializer.reference; + bl.InitData = initializer; Placed += bl.OnPlacedInit; return bl; } @@ -241,13 +240,12 @@ namespace TechbloxModdingAPI throw new BlockException("Blocks can only be placed in build mode."); var initializer = PlacementEngine.PlaceBlock(type, position, player, autoWire); Id = initializer.EGID; - InitData.Group = BlockEngine.InitGroup(initializer); + InitData = initializer; Placed += OnPlacedInit; } - public EGID Id { get; } + public override EGID Id { get; } - internal BlockEngine.BlockInitData InitData; private EGID copiedFrom; /// diff --git a/TechbloxModdingAPI/Blocks/BlockEngine.cs b/TechbloxModdingAPI/Blocks/BlockEngine.cs index 404e72a..7bade49 100644 --- a/TechbloxModdingAPI/Blocks/BlockEngine.cs +++ b/TechbloxModdingAPI/Blocks/BlockEngine.cs @@ -9,6 +9,7 @@ using RobocraftX.Blocks; using RobocraftX.Common; using RobocraftX.Physics; using RobocraftX.Rendering; +using RobocraftX.Rendering.GPUI; using Svelto.ECS.EntityStructs; using Svelto.DataStructures; @@ -16,6 +17,7 @@ using Svelto.ECS; using Svelto.ECS.Hybrid; using Unity.Mathematics; using TechbloxModdingAPI.Engines; +using TechbloxModdingAPI.Utility; namespace TechbloxModdingAPI.Blocks { @@ -68,14 +70,13 @@ namespace TechbloxModdingAPI.Blocks : entitiesDB.QueryEntity(index, CommonExclusiveGroups.COLOUR_PALETTE_GROUP).Colour; - public ref T GetBlockInfo(EGID blockID) where T : unmanaged, IEntityComponent + public OptionalRef GetBlockInfo(EGID blockID) where T : unmanaged, IEntityComponent { - if (entitiesDB.Exists(blockID)) - return ref entitiesDB.QueryEntity(blockID); - T[] structHolder = new T[1]; //Create something that can be referenced - return ref structHolder[0]; //Gets a default value automatically + return entitiesDB.TryQueryEntitiesAndIndex(blockID, out uint index, out var array) + ? new OptionalRef(array, index) + : new OptionalRef(); } - + public ref T GetBlockInfoViewStruct(EGID blockID) where T : struct, INeedEGID, IEntityViewComponent { if (entitiesDB.Exists(blockID)) @@ -149,6 +150,12 @@ namespace TechbloxModdingAPI.Blocks entitiesDB.QueryEntity(id).matrix = float4x4.TRS(pos.position, rot.rotation, scale.scale); } + internal void UpdatePrefab(Block block, ushort type, byte material, bool flipped) + { + uint pid = PrefabsID.GetOrCreatePrefabID(type, material, 0, flipped); + entitiesDB.QueryEntityOrDefault() + } + public bool BlockExists(EGID blockID) { return entitiesDB.Exists(blockID); diff --git a/TechbloxModdingAPI/Blocks/BlockEngineInit.cs b/TechbloxModdingAPI/EcsObjectBase.cs similarity index 58% rename from TechbloxModdingAPI/Blocks/BlockEngineInit.cs rename to TechbloxModdingAPI/EcsObjectBase.cs index b9b9eae..c96cf25 100644 --- a/TechbloxModdingAPI/Blocks/BlockEngineInit.cs +++ b/TechbloxModdingAPI/EcsObjectBase.cs @@ -1,33 +1,43 @@ -using System; +using System; using System.Linq.Expressions; - using Svelto.DataStructures; using Svelto.ECS; using Svelto.ECS.Internal; +using TechbloxModdingAPI.Blocks; -namespace TechbloxModdingAPI.Blocks +namespace TechbloxModdingAPI { - public partial class BlockEngine + public abstract class EcsObjectBase { + public abstract EGID Id { get; } //Abstract to support the 'place' Block constructor + + protected internal EcsInitData InitData; + /// /// Holds information needed to construct a component initializer /// - internal struct BlockInitData + protected internal struct EcsInitData { - public FasterDictionary Group; - public EntityReference Reference; + private FasterDictionary group; + private EntityReference reference; + + public static implicit operator EcsInitData(EntityInitializer initializer) => new EcsInitData + {group = GetInitGroup(initializer), reference = initializer.reference}; + + public EntityInitializer Initializer(EGID id) => new EntityInitializer(id, group, reference); + public bool Valid => group != null; } - internal delegate FasterDictionary GetInitGroup( + private delegate FasterDictionary GetInitGroupFunc( EntityInitializer initializer); /// /// Accesses the group field of the initializer /// - internal GetInitGroup InitGroup = CreateAccessor("_group"); + private static GetInitGroupFunc GetInitGroup = CreateAccessor("_group"); //https://stackoverflow.com/questions/55878525/unit-testing-ref-structs-with-private-fields-via-reflection - internal static TDelegate CreateAccessor(string memberName) where TDelegate : Delegate + private static TDelegate CreateAccessor(string memberName) where TDelegate : Delegate { var invokeMethod = typeof(TDelegate).GetMethod("Invoke"); if (invokeMethod == null) diff --git a/TechbloxModdingAPI/Utility/ApiExtensions.cs b/TechbloxModdingAPI/Utility/ApiExtensions.cs new file mode 100644 index 0000000..3da1a67 --- /dev/null +++ b/TechbloxModdingAPI/Utility/ApiExtensions.cs @@ -0,0 +1,53 @@ +using Svelto.ECS; +using TechbloxModdingAPI.Blocks; + +namespace TechbloxModdingAPI.Utility +{ + public static class ApiExtensions + { + /// + /// Attempts to query an entity and returns an optional that contains the result if succeeded. + /// + /// The entities DB + /// The EGID to query + /// The component type to query + /// An optional that contains the result on success or is empty if not found + public static OptionalRef QueryEntityOptional(this EntitiesDB entitiesDB, EGID egid) + where T : unmanaged, IEntityComponent + { + return entitiesDB.TryQueryEntitiesAndIndex(egid, out uint index, out var array) + ? new OptionalRef(array, index) + : new OptionalRef(); + } + + /// + /// Attempts to query an entity and returns the result or a dummy value that can be modified. + /// + /// + /// + /// + /// + public static OptionalRef QueryEntityOptional(this EntitiesDB entitiesDB, EcsObjectBase obj) + where T : unmanaged, IEntityComponent + { + var opt = QueryEntityOptional(entitiesDB, obj.Id); + return opt ? opt : new OptionalRef(obj); + } + + /// + /// Attempts to query an entity and returns the result or a dummy value that can be modified. + /// + /// + /// + /// + /// + public static ref T QueryEntityOrDefault(this EntitiesDB entitiesDB, EcsObjectBase obj) + where T : unmanaged, IEntityComponent + { + var opt = QueryEntityOptional(entitiesDB, obj.Id); + if (opt) return ref opt.Get(); + if (obj.InitData.Valid) return ref obj.InitData.Initializer(obj.Id).GetOrCreate(); + return ref opt.Get(); //Default value + } + } +} \ No newline at end of file diff --git a/TechbloxModdingAPI/Utility/OptionalRef.cs b/TechbloxModdingAPI/Utility/OptionalRef.cs index 7210d22..2323431 100644 --- a/TechbloxModdingAPI/Utility/OptionalRef.cs +++ b/TechbloxModdingAPI/Utility/OptionalRef.cs @@ -9,31 +9,51 @@ using Svelto.ECS; namespace TechbloxModdingAPI { - public struct OptionalRef where T : unmanaged + public ref struct OptionalRef where T : unmanaged, IEntityComponent { private bool exists; private NB array; private uint index; + private EntityInitializer initializer; public OptionalRef(NB array, uint index) { exists = true; this.array = array; this.index = index; + initializer = default; } - - public OptionalRef(ref T value) + + /// + /// Wraps the initializer data, if present. + /// + /// The object with the initializer + public OptionalRef(EcsObjectBase obj) { - exists = true; + if (obj.InitData.Valid) + { + initializer = obj.InitData.Initializer(obj.Id); + exists = true; + } + else + { + initializer = default; + exists = false; + } array = default; index = default; } - public ref T Get(T def = default) + /// + /// Returns the value or a default value if empty. Supports objects that are being initialized. + /// + /// The value or the default value + public ref T Get() { - if (exists) + if (!exists) return ref CompRefCache.Default; + if (initializer.EGID == EGID.Empty) return ref array[index]; - return ref CompRefCache._default; + return ref initializer.GetOrCreate(); } public bool Exists => exists; @@ -51,10 +71,10 @@ namespace TechbloxModdingAPI /// /// Creates an instance of a struct T that can be referenced. /// - /// The struct type to cache - private struct CompRefCache where T : unmanaged + /// The struct type to cache + private struct CompRefCache where TR : unmanaged { - public static T _default; + public static TR Default; } } } \ No newline at end of file From 61184145a914ef360350f4df7263709cee19c5c9 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 10 May 2021 22:45:07 +0200 Subject: [PATCH 2/7] Start using new extension methods, code cleanup Removed all of the different block property getter methods --- TechbloxModdingAPI/Block.cs | 8 +- TechbloxModdingAPI/Blocks/BlockEngine.cs | 83 +-------------------- TechbloxModdingAPI/Blocks/MovementEngine.cs | 44 ++++------- TechbloxModdingAPI/Blocks/RotationEngine.cs | 61 ++++++--------- TechbloxModdingAPI/Blocks/SignalEngine.cs | 38 +++------- 5 files changed, 55 insertions(+), 179 deletions(-) diff --git a/TechbloxModdingAPI/Block.cs b/TechbloxModdingAPI/Block.cs index f99ca28..0e97a03 100644 --- a/TechbloxModdingAPI/Block.cs +++ b/TechbloxModdingAPI/Block.cs @@ -254,10 +254,10 @@ namespace TechbloxModdingAPI /// public float3 Position { - get => MovementEngine.GetPosition(Id, InitData); + get => MovementEngine.GetPosition(this); set { - MovementEngine.MoveBlock(Id, InitData, value); + MovementEngine.MoveBlock(this, value); if (blockGroup != null) blockGroup.PosAndRotCalculated = false; BlockEngine.UpdateDisplayedBlock(Id); @@ -269,10 +269,10 @@ namespace TechbloxModdingAPI /// public float3 Rotation { - get => RotationEngine.GetRotation(Id, InitData); + get => RotationEngine.GetRotation(this); set { - RotationEngine.RotateBlock(Id, InitData, value); + RotationEngine.RotateBlock(this, value); if (blockGroup != null) blockGroup.PosAndRotCalculated = false; BlockEngine.UpdateDisplayedBlock(Id); diff --git a/TechbloxModdingAPI/Blocks/BlockEngine.cs b/TechbloxModdingAPI/Blocks/BlockEngine.cs index 7bade49..935e3a1 100644 --- a/TechbloxModdingAPI/Blocks/BlockEngine.cs +++ b/TechbloxModdingAPI/Blocks/BlockEngine.cs @@ -70,75 +70,9 @@ namespace TechbloxModdingAPI.Blocks : entitiesDB.QueryEntity(index, CommonExclusiveGroups.COLOUR_PALETTE_GROUP).Colour; - public OptionalRef GetBlockInfo(EGID blockID) where T : unmanaged, IEntityComponent + public OptionalRef GetBlockInfo(Block block) where T : unmanaged, IEntityComponent { - return entitiesDB.TryQueryEntitiesAndIndex(blockID, out uint index, out var array) - ? new OptionalRef(array, index) - : new OptionalRef(); - } - - public ref T GetBlockInfoViewStruct(EGID blockID) where T : struct, INeedEGID, IEntityViewComponent - { - if (entitiesDB.Exists(blockID)) - return ref entitiesDB.QueryEntity(blockID); - T[] structHolder = new T[1]; //Create something that can be referenced - return ref structHolder[0]; //Gets a default value automatically - } - - public U GetBlockInfo(Block block, Func getter, - U def = default) where T : unmanaged, IEntityComponent - { - if (entitiesDB.Exists(block.Id)) - return getter(entitiesDB.QueryEntity(block.Id)); - return GetBlockInitInfo(block, getter, def); - } - - public U GetBlockInfoViewStruct(Block block, Func getter, - U def = default) where T : struct, IEntityViewComponent - { - if (entitiesDB.Exists(block.Id)) - return getter(entitiesDB.QueryEntity(block.Id)); - return GetBlockInitInfo(block, getter, def); - } - - private U GetBlockInitInfo(Block block, Func getter, U def) where T : struct, IEntityComponent - { - if (block.InitData.Group == null) return def; - var initializer = new EntityInitializer(block.Id, block.InitData.Group, block.InitData.Reference); - if (initializer.Has()) - return getter(initializer.Get()); - return def; - } - - public delegate void Setter(ref T component, U value) where T : struct, IEntityComponent; - - public void SetBlockInfoViewStruct(Block block, Setter setter, U value) where T : struct, IEntityViewComponent - { - if (entitiesDB.Exists(block.Id)) - setter(ref entitiesDB.QueryEntity(block.Id), value); - else - SetBlockInitInfo(block, setter, value); - } - - public void SetBlockInfo(Block block, Setter setter, U value) where T : unmanaged, IEntityComponent - { - if (entitiesDB.Exists(block.Id)) - setter(ref entitiesDB.QueryEntity(block.Id), value); - else - SetBlockInitInfo(block, setter, value); - } - - private void SetBlockInitInfo(Block block, Setter setter, U value) - where T : struct, IEntityComponent - { - if (block.InitData.Group != null) - { - var initializer = new EntityInitializer(block.Id, block.InitData.Group, block.InitData.Reference); - T component = initializer.Has() ? initializer.Get() : default; - ref T structRef = ref component; - setter(ref structRef, value); - initializer.Init(structRef); - } + return entitiesDB.QueryEntityOptional(block); } public void UpdateDisplayedBlock(EGID id) @@ -153,7 +87,8 @@ namespace TechbloxModdingAPI.Blocks internal void UpdatePrefab(Block block, ushort type, byte material, bool flipped) { uint pid = PrefabsID.GetOrCreatePrefabID(type, material, 0, flipped); - entitiesDB.QueryEntityOrDefault() + entitiesDB.QueryEntityOrDefault(block).prefabID = pid; + entitiesDB.QueryEntityOrDefault(block) = new PhysicsPrefabEntityStruct(pid); } public bool BlockExists(EGID blockID) @@ -161,16 +96,6 @@ namespace TechbloxModdingAPI.Blocks return entitiesDB.Exists(blockID); } - public bool GetBlockInfoExists(Block block) where T : struct, IEntityComponent - { - if (entitiesDB.Exists(block.Id)) - return true; - if (block.InitData.Group == null) - return false; - var init = new EntityInitializer(block.Id, block.InitData.Group, block.InitData.Reference); - return init.Has(); - } - public SimBody[] GetSimBodiesFromID(byte id) { var ret = new FasterList(4); diff --git a/TechbloxModdingAPI/Blocks/MovementEngine.cs b/TechbloxModdingAPI/Blocks/MovementEngine.cs index aeeac20..7ecf934 100644 --- a/TechbloxModdingAPI/Blocks/MovementEngine.cs +++ b/TechbloxModdingAPI/Blocks/MovementEngine.cs @@ -34,21 +34,12 @@ namespace TechbloxModdingAPI.Blocks // implementations for Movement static class - internal float3 MoveBlock(EGID blockID, BlockEngine.BlockInitData data, float3 vector) + internal float3 MoveBlock(Block block, float3 vector) { - if (!entitiesDB.Exists(blockID)) - { - if (data.Group == null) return float3.zero; - var init = new EntityInitializer(blockID, data.Group, data.Reference); - init.GetOrCreate().position = vector; - init.GetOrCreate().position = vector; - init.GetOrCreate().position = vector; - return vector; - } - ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntity(blockID); - ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntity(blockID); - ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntity(blockID); - ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntity(blockID); + ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntityOrDefault(block); + ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntityOrDefault(block); + ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntityOrDefault(block); + ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntityOrDefault(block); // main (persistent) position posStruct.position = vector; // placement grid position @@ -56,24 +47,21 @@ namespace TechbloxModdingAPI.Blocks // rendered position transStruct.position = vector; // collision position - FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Translation - { - Value = posStruct.position - }); - entitiesDB.QueryEntity(blockID).isProcessed = false; + if (phyStruct.ID != EGID.Empty) + { //It exists + FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Translation + { + Value = posStruct.position + }); + } + + entitiesDB.QueryEntityOrDefault(block).isProcessed = false; return posStruct.position; } - internal float3 GetPosition(EGID blockID, BlockEngine.BlockInitData data) + internal float3 GetPosition(Block block) { - if (!entitiesDB.Exists(blockID)) - { - if (data.Group == null) return float3.zero; - var init = new EntityInitializer(blockID, data.Group, data.Reference); - return init.Has() ? init.Get().position : float3.zero; - } - ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntity(blockID); - return posStruct.position; + return entitiesDB.QueryEntityOrDefault(block).position; } } } diff --git a/TechbloxModdingAPI/Blocks/RotationEngine.cs b/TechbloxModdingAPI/Blocks/RotationEngine.cs index cef4691..b1e54e5 100644 --- a/TechbloxModdingAPI/Blocks/RotationEngine.cs +++ b/TechbloxModdingAPI/Blocks/RotationEngine.cs @@ -34,55 +34,38 @@ namespace TechbloxModdingAPI.Blocks // implementations for Rotation static class - internal float3 RotateBlock(EGID blockID, BlockEngine.BlockInitData data, Vector3 vector) + internal float3 RotateBlock(Block block, Vector3 vector) { - if (!entitiesDB.Exists(blockID)) - { - if (data.Group == null) return float3.zero; - var init = new EntityInitializer(blockID, data.Group, data.Reference); - init.GetOrCreate().rotation = Quaternion.Euler(vector); - init.GetOrCreate().rotation = Quaternion.Euler(vector); - init.GetOrCreate().rotation = Quaternion.Euler(vector); - return vector; - } - ref RotationEntityStruct rotStruct = ref this.entitiesDB.QueryEntity(blockID); - ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntity(blockID); - ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntity(blockID); - ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntity(blockID); - // main (persistent) position + ref RotationEntityStruct rotStruct = ref this.entitiesDB.QueryEntityOrDefault(block); + ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntityOrDefault(block); + ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntityOrDefault(block); + ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntityOrDefault(block); + // main (persistent) rotation Quaternion newRotation = rotStruct.rotation; newRotation.eulerAngles = vector; rotStruct.rotation = newRotation; // placement grid rotation - Quaternion newGridRotation = gridStruct.rotation; - newGridRotation.eulerAngles = vector; - gridStruct.rotation = newGridRotation; - // rendered position - Quaternion newTransRotation = rotStruct.rotation; - newTransRotation.eulerAngles = vector; - transStruct.rotation = newTransRotation; - // collision position - FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Unity.Transforms.Rotation - { - Value = rotStruct.rotation - }); - entitiesDB.QueryEntity(blockID).isProcessed = false; + gridStruct.rotation = newRotation; + // rendered rotation + transStruct.rotation = newRotation; + // collision rotation + if (phyStruct.ID != EGID.Empty) + { //It exists + FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, + new Unity.Transforms.Rotation + { + Value = rotStruct.rotation + }); + } + + entitiesDB.QueryEntityOrDefault(block).isProcessed = false; return ((Quaternion)rotStruct.rotation).eulerAngles; } - internal float3 GetRotation(EGID blockID, BlockEngine.BlockInitData data) + internal float3 GetRotation(Block block) { - if (!entitiesDB.Exists(blockID)) - { - if (data.Group == null) return float3.zero; - var init = new EntityInitializer(blockID, data.Group, data.Reference); - return init.Has() - ? (float3) ((Quaternion) init.Get().rotation).eulerAngles - : float3.zero; - } - - ref RotationEntityStruct rotStruct = ref entitiesDB.QueryEntity(blockID); + ref RotationEntityStruct rotStruct = ref entitiesDB.QueryEntityOrDefault(block); return ((Quaternion) rotStruct.rotation).eulerAngles; } } diff --git a/TechbloxModdingAPI/Blocks/SignalEngine.cs b/TechbloxModdingAPI/Blocks/SignalEngine.cs index 6e40af1..f486463 100644 --- a/TechbloxModdingAPI/Blocks/SignalEngine.cs +++ b/TechbloxModdingAPI/Blocks/SignalEngine.cs @@ -3,6 +3,7 @@ using Svelto.ECS; using Svelto.DataStructures; using Gamecraft.Wires; using TechbloxModdingAPI.Engines; +using TechbloxModdingAPI.Utility; namespace TechbloxModdingAPI.Blocks { @@ -87,8 +88,8 @@ namespace TechbloxModdingAPI.Blocks public ref PortEntityStruct GetPortByOffset(Block block, byte portNumber, bool input) { - BlockPortsStruct bps = GetFromDbOrInitData(block, block.Id, out bool exists); - if (!exists) + var bps = entitiesDB.QueryEntityOptional(block); + if (!bps) { throw new BlockException("Block does not exist"); } @@ -208,8 +209,9 @@ namespace TechbloxModdingAPI.Blocks public EGID MatchBlockInputToPort(Block block, byte portUsage, out bool exists) { - BlockPortsStruct ports = GetFromDbOrInitData(block, block.Id, out exists); - return new EGID(ports.firstInputID + portUsage, NamedExclusiveGroup.Group); + var ports = entitiesDB.QueryEntityOptional(block); + exists = ports; + return new EGID(ports.Get().firstInputID + portUsage, NamedExclusiveGroup.Group); } public EGID MatchBlockInputToPort(EGID block, byte portUsage, out bool exists) @@ -226,8 +228,9 @@ namespace TechbloxModdingAPI.Blocks public EGID MatchBlockOutputToPort(Block block, byte portUsage, out bool exists) { - BlockPortsStruct ports = GetFromDbOrInitData(block, block.Id, out exists); - return new EGID(ports.firstOutputID + portUsage, NamedExclusiveGroup.Group); + var ports = entitiesDB.QueryEntityOptional(block); + exists = ports; + return new EGID(ports.Get().firstOutputID + portUsage, NamedExclusiveGroup.Group); } public EGID MatchBlockOutputToPort(EGID block, byte portUsage, out bool exists) @@ -385,29 +388,6 @@ namespace TechbloxModdingAPI.Blocks return results.ToArray(); } - private ref T GetFromDbOrInitData(Block block, EGID id, out bool exists) where T : unmanaged, IEntityComponent - { - T[] defRef = new T[1]; - if (entitiesDB.Exists(id)) - { - exists = true; - return ref entitiesDB.QueryEntity(id); - } - if (block == null || block.InitData.Group == null) - { - exists = false; - return ref defRef[0]; - } - EntityInitializer initializer = new EntityInitializer(block.Id, block.InitData.Group, block.InitData.Reference); - if (initializer.Has()) - { - exists = true; - return ref initializer.Get(); - } - exists = false; - return ref defRef[0]; - } - private EntityCollection GetSignalStruct(uint signalID, out uint index, bool input = true) { ExclusiveGroup group = input From d238c97906eb56dbd3aa0561bdfa2f3d6363289d Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 10 May 2021 23:08:15 +0200 Subject: [PATCH 3/7] Remove block info getters and setters Regex is great GetBlockInfo\(this, \((\w+) (\w+)\) ?=> ?\2(.+)\); GetBlockInfo<$1>(this)$3; SetBlockInfo\(this, \(ref (\w+) (\w+), \w+ (\w+)\) ?=> \2(.*) = \3,\s*value\); GetBlockInfo<$1>(this)$4 = value; --- TechbloxModdingAPI/Block.cs | 13 ++++++------ TechbloxModdingAPI/Blocks/BlockEngine.cs | 7 ++++++- TechbloxModdingAPI/Blocks/DampedSpring.cs | 6 +++--- TechbloxModdingAPI/Blocks/Motor.cs | 12 +++++------ TechbloxModdingAPI/Blocks/MusicBlock.cs | 4 ++-- TechbloxModdingAPI/Blocks/ObjectIdentifier.cs | 4 ++-- TechbloxModdingAPI/Blocks/Piston.cs | 9 ++++----- TechbloxModdingAPI/Blocks/Servo.cs | 16 +++++++-------- TechbloxModdingAPI/Blocks/SfxBlock.cs | 10 +++++----- TechbloxModdingAPI/Blocks/SignalingBlock.cs | 4 ++-- TechbloxModdingAPI/Blocks/SpawnPoint.cs | 16 +++++++-------- TechbloxModdingAPI/Blocks/TextBlock.cs | 6 +++--- TechbloxModdingAPI/Blocks/Timer.cs | 20 ++++++++----------- 13 files changed, 63 insertions(+), 64 deletions(-) diff --git a/TechbloxModdingAPI/Block.cs b/TechbloxModdingAPI/Block.cs index 0e97a03..b2d400d 100644 --- a/TechbloxModdingAPI/Block.cs +++ b/TechbloxModdingAPI/Block.cs @@ -285,14 +285,14 @@ namespace TechbloxModdingAPI /// public float3 Scale { - get => BlockEngine.GetBlockInfo(this, (ScalingEntityStruct st) => st.scale); + get => BlockEngine.GetBlockInfo(this).scale; set { int uscale = UniformScale; if (value.x < 4e-5) value.x = uscale; if (value.y < 4e-5) value.y = uscale; if (value.z < 4e-5) value.z = uscale; - BlockEngine.SetBlockInfo(this, (ref ScalingEntityStruct st, float3 val) => st.scale = val, value); + BlockEngine.GetBlockInfo(this).scale = value; if (!Exists) return; //UpdateCollision needs the block to exist ScalingEngine.UpdateCollision(Id); BlockEngine.UpdateDisplayedBlock(Id); @@ -305,12 +305,11 @@ namespace TechbloxModdingAPI /// public int UniformScale { - get => BlockEngine.GetBlockInfo(this, (UniformBlockScaleEntityStruct st) => st.scaleFactor); + get => BlockEngine.GetBlockInfo(this).scaleFactor; set { if (value < 1) value = 1; - BlockEngine.SetBlockInfo(this, (ref UniformBlockScaleEntityStruct st, int val) => st.scaleFactor = val, - value); + BlockEngine.GetBlockInfo(this).scaleFactor = value; Scale = new float3(value, value, value); } } @@ -320,7 +319,7 @@ namespace TechbloxModdingAPI */ public bool Flipped { - get => BlockEngine.GetBlockInfo(this, (ScalingEntityStruct st) => st.scale.x < 0); + get => BlockEngine.GetBlockInfo(this).scale.x < 0; set { BlockEngine.SetBlockInfo(this, (ref ScalingEntityStruct st, bool val) => @@ -371,7 +370,7 @@ namespace TechbloxModdingAPI /// public float4 CustomColor { - get => BlockEngine.GetBlockInfo(this, (ColourParameterEntityStruct st) => st.paletteColour); + get => BlockEngine.GetBlockInfo(this).paletteColour; set { BlockEngine.SetBlockInfo(this, (ref ColourParameterEntityStruct color, float4 val) => diff --git a/TechbloxModdingAPI/Blocks/BlockEngine.cs b/TechbloxModdingAPI/Blocks/BlockEngine.cs index 935e3a1..80e14f3 100644 --- a/TechbloxModdingAPI/Blocks/BlockEngine.cs +++ b/TechbloxModdingAPI/Blocks/BlockEngine.cs @@ -70,11 +70,16 @@ namespace TechbloxModdingAPI.Blocks : entitiesDB.QueryEntity(index, CommonExclusiveGroups.COLOUR_PALETTE_GROUP).Colour; - public OptionalRef GetBlockInfo(Block block) where T : unmanaged, IEntityComponent + public OptionalRef GetBlockInfoOptional(Block block) where T : unmanaged, IEntityComponent { return entitiesDB.QueryEntityOptional(block); } + public ref T GetBlockInfo(Block block) where T : unmanaged, IEntityComponent + { + return ref entitiesDB.QueryEntityOrDefault(block); + } + public void UpdateDisplayedBlock(EGID id) { if (!BlockExists(id)) return; diff --git a/TechbloxModdingAPI/Blocks/DampedSpring.cs b/TechbloxModdingAPI/Blocks/DampedSpring.cs index 34c7543..3c92f72 100644 --- a/TechbloxModdingAPI/Blocks/DampedSpring.cs +++ b/TechbloxModdingAPI/Blocks/DampedSpring.cs @@ -19,7 +19,7 @@ namespace TechbloxModdingAPI.Blocks /// public float MaxForce { - get => BlockEngine.GetBlockInfo(this, (DampedSpringReadOnlyStruct dsrs) => dsrs.springFrequency); + get => BlockEngine.GetBlockInfo(this).springFrequency; set => BlockEngine.SetBlockInfo(this, (ref DampedSpringReadOnlyStruct dsrs, float val) => dsrs.springFrequency = val, value); @@ -39,7 +39,7 @@ namespace TechbloxModdingAPI.Blocks /// public float Damping { - get => BlockEngine.GetBlockInfo(this, (DampedSpringReadOnlyStruct ljf) => ljf.springDamping); + get => BlockEngine.GetBlockInfo(this).springDamping; set => BlockEngine.SetBlockInfo(this, (ref DampedSpringReadOnlyStruct ljf, float val) => ljf.springDamping = val, value); @@ -50,7 +50,7 @@ namespace TechbloxModdingAPI.Blocks /// public float MaxExtension { - get => BlockEngine.GetBlockInfo(this, (DampedSpringReadOnlyStruct ljf) => ljf.maxExtent); + get => BlockEngine.GetBlockInfo(this).maxExtent; set => BlockEngine.SetBlockInfo(this, (ref DampedSpringReadOnlyStruct ljf, float val) => ljf.maxExtent = val, value); diff --git a/TechbloxModdingAPI/Blocks/Motor.cs b/TechbloxModdingAPI/Blocks/Motor.cs index 6b1e500..46ed9e4 100644 --- a/TechbloxModdingAPI/Blocks/Motor.cs +++ b/TechbloxModdingAPI/Blocks/Motor.cs @@ -28,12 +28,12 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (MotorReadOnlyStruct st) => st.maxVelocity); + return BlockEngine.GetBlockInfo(this).maxVelocity; } set { - BlockEngine.SetBlockInfo(this, (ref MotorReadOnlyStruct st, float val) => st.maxVelocity = val, value); + BlockEngine.GetBlockInfo(this).maxVelocity = value; } } @@ -44,12 +44,12 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (MotorReadOnlyStruct st) => st.maxForce); + return BlockEngine.GetBlockInfo(this).maxForce; } set { - BlockEngine.SetBlockInfo(this, (ref MotorReadOnlyStruct st, float val) => st.maxForce = val, value); + BlockEngine.GetBlockInfo(this).maxForce = value; } } @@ -60,12 +60,12 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (MotorReadOnlyStruct st) => st.reverse); + return BlockEngine.GetBlockInfo(this).reverse; } set { - BlockEngine.SetBlockInfo(this, (ref MotorReadOnlyStruct st, bool val) => st.reverse = val, value); + BlockEngine.GetBlockInfo(this).reverse = value; } } } diff --git a/TechbloxModdingAPI/Blocks/MusicBlock.cs b/TechbloxModdingAPI/Blocks/MusicBlock.cs index 30ca5ab..ea4aeca 100644 --- a/TechbloxModdingAPI/Blocks/MusicBlock.cs +++ b/TechbloxModdingAPI/Blocks/MusicBlock.cs @@ -28,7 +28,7 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (MusicBlockDataEntityStruct st) => st.trackIndx); + return BlockEngine.GetBlockInfo(this).trackIndx; } set @@ -83,7 +83,7 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (MusicBlockDataEntityStruct msdes) => msdes.tweakableVolume); + return BlockEngine.GetBlockInfo(this).tweakableVolume; } set diff --git a/TechbloxModdingAPI/Blocks/ObjectIdentifier.cs b/TechbloxModdingAPI/Blocks/ObjectIdentifier.cs index 67e250e..fe2d657 100644 --- a/TechbloxModdingAPI/Blocks/ObjectIdentifier.cs +++ b/TechbloxModdingAPI/Blocks/ObjectIdentifier.cs @@ -16,7 +16,7 @@ namespace TechbloxModdingAPI.Blocks public char Identifier { - get => (char) BlockEngine.GetBlockInfo(this, (ObjectIdEntityStruct st) => st.objectId + 'A'); + get => (char) BlockEngine.GetBlockInfo(this).objectId + 'A'; set { BlockEngine.SetBlockInfo(this, (ref ObjectIdEntityStruct st, char val) => @@ -32,7 +32,7 @@ namespace TechbloxModdingAPI.Blocks /// public byte SimID { - get => BlockEngine.GetBlockInfo(this, (ObjectIdEntityStruct st) => st.simObjectId); + get => BlockEngine.GetBlockInfo(this).simObjectId; } /// diff --git a/TechbloxModdingAPI/Blocks/Piston.cs b/TechbloxModdingAPI/Blocks/Piston.cs index b5953ee..9c1b98a 100644 --- a/TechbloxModdingAPI/Blocks/Piston.cs +++ b/TechbloxModdingAPI/Blocks/Piston.cs @@ -26,12 +26,11 @@ namespace TechbloxModdingAPI.Blocks /// public float MaximumExtension { - get => BlockEngine.GetBlockInfo(this, (PistonReadOnlyStruct st) => st.maxDeviation); + get => BlockEngine.GetBlockInfo(this).maxDeviation; set { - BlockEngine.SetBlockInfo(this, (ref PistonReadOnlyStruct st, float val) => st.maxDeviation = val, - value); + BlockEngine.GetBlockInfo(this).maxDeviation = value; } } @@ -40,11 +39,11 @@ namespace TechbloxModdingAPI.Blocks /// public float MaximumForce { - get => BlockEngine.GetBlockInfo(this, (PistonReadOnlyStruct st) => st.pistonVelocity); + get => BlockEngine.GetBlockInfo(this).pistonVelocity; set { - BlockEngine.SetBlockInfo(this, (ref PistonReadOnlyStruct st, float val) => st.pistonVelocity = val, value); + BlockEngine.GetBlockInfo(this).pistonVelocity = value; } } } diff --git a/TechbloxModdingAPI/Blocks/Servo.cs b/TechbloxModdingAPI/Blocks/Servo.cs index 12232de..cdbd87b 100644 --- a/TechbloxModdingAPI/Blocks/Servo.cs +++ b/TechbloxModdingAPI/Blocks/Servo.cs @@ -26,11 +26,11 @@ namespace TechbloxModdingAPI.Blocks /// public float MinimumAngle { - get => BlockEngine.GetBlockInfo(this, (ServoReadOnlyStruct st) => st.minDeviation); + get => BlockEngine.GetBlockInfo(this).minDeviation; set { - BlockEngine.SetBlockInfo(this, (ref ServoReadOnlyStruct st, float val) => st.minDeviation = val, value); + BlockEngine.GetBlockInfo(this).minDeviation = value; } } @@ -39,11 +39,11 @@ namespace TechbloxModdingAPI.Blocks /// public float MaximumAngle { - get => BlockEngine.GetBlockInfo(this, (ServoReadOnlyStruct st) => st.maxDeviation); + get => BlockEngine.GetBlockInfo(this).maxDeviation; set { - BlockEngine.SetBlockInfo(this, (ref ServoReadOnlyStruct st, float val) => st.maxDeviation = val, value); + BlockEngine.GetBlockInfo(this).maxDeviation = value; } } @@ -52,11 +52,11 @@ namespace TechbloxModdingAPI.Blocks /// public float MaximumForce { - get => BlockEngine.GetBlockInfo(this, (ServoReadOnlyStruct st) => st.servoVelocity); + get => BlockEngine.GetBlockInfo(this).servoVelocity; set { - BlockEngine.SetBlockInfo(this, (ref ServoReadOnlyStruct st, float val) => st.servoVelocity = val, value); + BlockEngine.GetBlockInfo(this).servoVelocity = value; } } @@ -65,11 +65,11 @@ namespace TechbloxModdingAPI.Blocks /// public bool Reverse { - get => BlockEngine.GetBlockInfo(this, (ServoReadOnlyStruct st) => st.reverse); + get => BlockEngine.GetBlockInfo(this).reverse; set { - BlockEngine.SetBlockInfo(this, (ref ServoReadOnlyStruct st, bool val) => st.reverse = val, value); + BlockEngine.GetBlockInfo(this).reverse = value; } } } diff --git a/TechbloxModdingAPI/Blocks/SfxBlock.cs b/TechbloxModdingAPI/Blocks/SfxBlock.cs index c72d37a..45453fb 100644 --- a/TechbloxModdingAPI/Blocks/SfxBlock.cs +++ b/TechbloxModdingAPI/Blocks/SfxBlock.cs @@ -22,7 +22,7 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.tweakableVolume); + return BlockEngine.GetBlockInfo(this).tweakableVolume; } set @@ -36,7 +36,7 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.tweakablePitch); + return BlockEngine.GetBlockInfo(this).tweakablePitch; } set @@ -50,7 +50,7 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.is3D); + return BlockEngine.GetBlockInfo(this).is3D; } set @@ -78,7 +78,7 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.soundEffectIndex); + return BlockEngine.GetBlockInfo(this).soundEffectIndex; } set @@ -162,7 +162,7 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.isLoopedBlock); + return BlockEngine.GetBlockInfo(this).isLoopedBlock; } set diff --git a/TechbloxModdingAPI/Blocks/SignalingBlock.cs b/TechbloxModdingAPI/Blocks/SignalingBlock.cs index b18521a..293e00d 100644 --- a/TechbloxModdingAPI/Blocks/SignalingBlock.cs +++ b/TechbloxModdingAPI/Blocks/SignalingBlock.cs @@ -67,7 +67,7 @@ namespace TechbloxModdingAPI.Blocks /// public uint InputCount { - get => BlockEngine.GetBlockInfo(this, (BlockPortsStruct st) => st.inputCount); + get => BlockEngine.GetBlockInfo(this).inputCount; } /// @@ -75,7 +75,7 @@ namespace TechbloxModdingAPI.Blocks /// public uint OutputCount { - get => BlockEngine.GetBlockInfo(this, (BlockPortsStruct st) => st.outputCount); + get => BlockEngine.GetBlockInfo(this).outputCount; } /// diff --git a/TechbloxModdingAPI/Blocks/SpawnPoint.cs b/TechbloxModdingAPI/Blocks/SpawnPoint.cs index ac6c014..0c5c75a 100644 --- a/TechbloxModdingAPI/Blocks/SpawnPoint.cs +++ b/TechbloxModdingAPI/Blocks/SpawnPoint.cs @@ -28,11 +28,11 @@ namespace TechbloxModdingAPI.Blocks /// public uint Lives { - get => BlockEngine.GetBlockInfo(this, (SpawnPointStatsEntityStruct st) => st.lives); + get => BlockEngine.GetBlockInfo(this).lives; set { - BlockEngine.SetBlockInfo(this, (ref SpawnPointStatsEntityStruct st, uint val) => st.lives = val, value); + BlockEngine.GetBlockInfo(this).lives = value; } } @@ -41,11 +41,11 @@ namespace TechbloxModdingAPI.Blocks /// public bool Damageable { - get => BlockEngine.GetBlockInfo(this, (SpawnPointStatsEntityStruct st) => st.canTakeDamage); + get => BlockEngine.GetBlockInfo(this).canTakeDamage; set { - BlockEngine.SetBlockInfo(this, (ref SpawnPointStatsEntityStruct st, bool val) => st.canTakeDamage = val, value); + BlockEngine.GetBlockInfo(this).canTakeDamage = value; } } @@ -54,11 +54,11 @@ namespace TechbloxModdingAPI.Blocks /// public bool GameOverEnabled { - get => BlockEngine.GetBlockInfo(this, (SpawnPointStatsEntityStruct st) => st.gameOverScreen); + get => BlockEngine.GetBlockInfo(this).gameOverScreen; set { - BlockEngine.SetBlockInfo(this, (ref SpawnPointStatsEntityStruct st, bool val) => st.gameOverScreen = val, value); + BlockEngine.GetBlockInfo(this).gameOverScreen = value; } } @@ -67,11 +67,11 @@ namespace TechbloxModdingAPI.Blocks /// public byte Team { - get => BlockEngine.GetBlockInfo(this, (SpawnPointIdsEntityStruct st) => st.teamId); + get => BlockEngine.GetBlockInfo(this).teamId; set { - BlockEngine.SetBlockInfo(this, (ref SpawnPointIdsEntityStruct st, byte val) => st.teamId = val, value); + BlockEngine.GetBlockInfo(this).teamId = value; } } } diff --git a/TechbloxModdingAPI/Blocks/TextBlock.cs b/TechbloxModdingAPI/Blocks/TextBlock.cs index 0e33b75..c3ee1b0 100644 --- a/TechbloxModdingAPI/Blocks/TextBlock.cs +++ b/TechbloxModdingAPI/Blocks/TextBlock.cs @@ -26,8 +26,8 @@ namespace TechbloxModdingAPI.Blocks /// The text block's current text. /// public string Text - { - get => BlockEngine.GetBlockInfo(this, (TextBlockDataStruct st) => st.textCurrent); + { + get => BlockEngine.GetBlockInfo(this).textCurrent; set { @@ -45,7 +45,7 @@ namespace TechbloxModdingAPI.Blocks /// public string TextBlockId { - get => BlockEngine.GetBlockInfo(this, (TextBlockDataStruct st) => st.textBlockID); + get => BlockEngine.GetBlockInfo(this).textBlockID; set { diff --git a/TechbloxModdingAPI/Blocks/Timer.cs b/TechbloxModdingAPI/Blocks/Timer.cs index 6337864..9803258 100644 --- a/TechbloxModdingAPI/Blocks/Timer.cs +++ b/TechbloxModdingAPI/Blocks/Timer.cs @@ -28,12 +28,11 @@ namespace TechbloxModdingAPI.Blocks /// public float Start { - get => BlockEngine.GetBlockInfo(this, (TimerBlockDataStruct st) => st.startTime); + get => BlockEngine.GetBlockInfo(this).startTime; set { - BlockEngine.SetBlockInfo(this, (ref TimerBlockDataStruct tbds, float val) => tbds.startTime = val, - value); + BlockEngine.GetBlockInfo(this).startTime = value; } } @@ -42,12 +41,11 @@ namespace TechbloxModdingAPI.Blocks /// public float End { - get => BlockEngine.GetBlockInfo(this, (TimerBlockDataStruct st) => st.endTime); + get => BlockEngine.GetBlockInfo(this).endTime; set { - BlockEngine.SetBlockInfo(this, (ref TimerBlockDataStruct tbds, float val) => tbds.endTime = val, - value); + BlockEngine.GetBlockInfo(this).endTime = value; } } @@ -56,12 +54,11 @@ namespace TechbloxModdingAPI.Blocks /// public bool DisplayMilliseconds { - get => BlockEngine.GetBlockInfo(this, (TimerBlockDataStruct st) => st.outputFormatHasMS); + get => BlockEngine.GetBlockInfo(this).outputFormatHasMS; set { - BlockEngine.SetBlockInfo(this, (ref TimerBlockDataStruct tbds, bool val) => tbds.outputFormatHasMS = val, - value); + BlockEngine.GetBlockInfo(this).outputFormatHasMS = value; } } @@ -70,12 +67,11 @@ namespace TechbloxModdingAPI.Blocks /// public int CurrentTime { - get => BlockEngine.GetBlockInfo(this, (TimerBlockLabelCacheEntityStruct st) => st.timeLastRenderFrameMS); + get => BlockEngine.GetBlockInfo(this).timeLastRenderFrameMS; set { - BlockEngine.SetBlockInfo(this, (ref TimerBlockLabelCacheEntityStruct tbds, int val) => tbds.timeLastRenderFrameMS = val, - value); + BlockEngine.GetBlockInfo(this).timeLastRenderFrameMS = value; } } } From 858a5c9b5c4c8494b562548194ac4bf5bff3aa75 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Tue, 11 May 2021 00:56:46 +0200 Subject: [PATCH 4/7] Fix remaining errors, add support for managed entity DB --- TechbloxModdingAPI/Block.cs | 77 +++++----- TechbloxModdingAPI/Blocks/BlockEngine.cs | 10 ++ TechbloxModdingAPI/Blocks/DampedSpring.cs | 9 +- TechbloxModdingAPI/Blocks/MusicBlock.cs | 88 +++++------ TechbloxModdingAPI/Blocks/ObjectIdentifier.cs | 9 +- TechbloxModdingAPI/Blocks/SfxBlock.cs | 137 +++++++++--------- TechbloxModdingAPI/Blocks/SignalingBlock.cs | 1 - TechbloxModdingAPI/Blocks/TextBlock.cs | 11 +- TechbloxModdingAPI/Cluster.cs | 16 +- TechbloxModdingAPI/Players/FlyCamEngine.cs | 1 + TechbloxModdingAPI/SimBody.cs | 20 +-- .../Utility/ManagedApiExtensions.cs | 55 +++++++ ...piExtensions.cs => NativeApiExtensions.cs} | 5 +- TechbloxModdingAPI/Utility/OptionalRef.cs | 76 ++++++---- 14 files changed, 282 insertions(+), 233 deletions(-) create mode 100644 TechbloxModdingAPI/Utility/ManagedApiExtensions.cs rename TechbloxModdingAPI/Utility/{ApiExtensions.cs => NativeApiExtensions.cs} (92%) diff --git a/TechbloxModdingAPI/Block.cs b/TechbloxModdingAPI/Block.cs index b2d400d..5181723 100644 --- a/TechbloxModdingAPI/Block.cs +++ b/TechbloxModdingAPI/Block.cs @@ -322,13 +322,9 @@ namespace TechbloxModdingAPI get => BlockEngine.GetBlockInfo(this).scale.x < 0; set { - BlockEngine.SetBlockInfo(this, (ref ScalingEntityStruct st, bool val) => - st.scale.x = math.abs(st.scale.x) * (val ? -1 : 1), value); - BlockEngine.SetBlockInfo(this, (ref GFXPrefabEntityStructGPUI st, bool val) => - { - uint prefabId = PrefabsID.GetOrCreatePrefabID((ushort) Type, (byte) Material, 0, value); - st.prefabID = prefabId; - }, value); + var st = BlockEngine.GetBlockInfo(this); + st.scale.x = math.abs(st.scale.x) * (value ? -1 : 1); + BlockEngine.UpdatePrefab(this, (ushort) Type, (byte) Material, value); } } @@ -339,7 +335,8 @@ namespace TechbloxModdingAPI { get { - return BlockEngine.GetBlockInfo(this, (DBEntityStruct st) => (BlockIDs) st.DBID, BlockIDs.Invalid); + var opt = BlockEngine.GetBlockInfoOptional(this); + return opt ? (BlockIDs) opt.Get().DBID : BlockIDs.Invalid; } } @@ -350,18 +347,16 @@ namespace TechbloxModdingAPI { get { - byte index = BlockEngine.GetBlockInfo(this, (ColourParameterEntityStruct st) => st.indexInPalette, - byte.MaxValue); - return new BlockColor(index); + var opt = BlockEngine.GetBlockInfoOptional(this); + return new BlockColor(opt ? opt.Get().indexInPalette : byte.MaxValue); } set { - BlockEngine.SetBlockInfo(this, (ref ColourParameterEntityStruct color, BlockColor val) => - { //TODO: Check if setting to 255 works - color.indexInPalette = val.Index; - color.hasNetworkChange = true; - color.paletteColour = BlockEngine.ConvertBlockColor(color.indexInPalette); - }, value); + //TODO: Check if setting to 255 works + var color = BlockEngine.GetBlockInfo(this); + color.indexInPalette = value.Index; + color.hasNetworkChange = true; + color.paletteColour = BlockEngine.ConvertBlockColor(color.indexInPalette); } } @@ -373,11 +368,9 @@ namespace TechbloxModdingAPI get => BlockEngine.GetBlockInfo(this).paletteColour; set { - BlockEngine.SetBlockInfo(this, (ref ColourParameterEntityStruct color, float4 val) => - { - color.paletteColour = val; - color.hasNetworkChange = true; - }, value); + ref var color = ref BlockEngine.GetBlockInfo(this); + color.paletteColour = value; + color.hasNetworkChange = true; } } @@ -386,9 +379,16 @@ namespace TechbloxModdingAPI */ public BlockMaterial Material { - get => BlockEngine.GetBlockInfo(this, (CubeMaterialStruct cmst) => (BlockMaterial) cmst.materialId, BlockMaterial.Default); - set => BlockEngine.SetBlockInfo(this, - (ref CubeMaterialStruct cmst, BlockMaterial val) => cmst.materialId = (byte) val, value); + get + { + var opt = BlockEngine.GetBlockInfoOptional(this); + return opt ? (BlockMaterial) opt.Get().materialId : BlockMaterial.Default; + } + set + { + BlockEngine.GetBlockInfo(this).materialId = (byte) value; + BlockEngine.UpdatePrefab(this, (ushort) Type, (byte) value, Flipped); //TODO: Test default + } } /// @@ -397,13 +397,11 @@ namespace TechbloxModdingAPI /// public string Label { - get => BlockEngine.GetBlockInfoViewStruct(this, (TextLabelEntityViewStruct st) => st.textLabelComponent?.text); + get => BlockEngine.GetBlockInfoViewComponent(this).textLabelComponent?.text; set { - BlockEngine.SetBlockInfoViewStruct(this, (ref TextLabelEntityViewStruct text, string val) => - { - if (text.textLabelComponent != null) text.textLabelComponent.text = val; - }, value); + var comp = BlockEngine.GetBlockInfoViewComponent(this).textLabelComponent; + if (comp != null) comp.text = value; } } @@ -421,9 +419,8 @@ namespace TechbloxModdingAPI get { if (blockGroup != null) return blockGroup; - return blockGroup = BlockEngine.GetBlockInfo(this, - (BlockGroupEntityComponent bgec) => - bgec.currentBlockGroup == -1 ? null : new BlockGroup(bgec.currentBlockGroup, this)); + var bgec = BlockEngine.GetBlockInfo(this); + return blockGroup = bgec.currentBlockGroup == -1 ? null : new BlockGroup(bgec.currentBlockGroup, this); } set { @@ -434,9 +431,7 @@ namespace TechbloxModdingAPI return; } blockGroup?.RemoveInternal(this); - BlockEngine.SetBlockInfo(this, - (ref BlockGroupEntityComponent bgec, BlockGroup val) => bgec.currentBlockGroup = val?.Id ?? -1, - value); + BlockEngine.GetBlockInfo(this).currentBlockGroup = value?.Id ?? -1; value?.AddInternal(this); blockGroup = value; } @@ -466,10 +461,10 @@ namespace TechbloxModdingAPI /// The SimBody of the chunk or null if the block doesn't exist or not in simulation mode. public SimBody GetSimBody() { - return BlockEngine.GetBlockInfo(this, - (GridConnectionsEntityStruct st) => st.machineRigidBodyId != uint.MaxValue - ? new SimBody(st.machineRigidBodyId, st.clusterId) - : null); + var st = BlockEngine.GetBlockInfo(this); + return st.machineRigidBodyId != uint.MaxValue + ? new SimBody(st.machineRigidBodyId, st.clusterId) + : null; } /// @@ -555,7 +550,7 @@ namespace TechbloxModdingAPI //Lets improve that using delegates var block = New(Id.entityID, Id.groupID); - if (this.InitData.Group != null) + if (this.InitData.Valid) { block.InitData = this.InitData; Placed += block.OnPlacedInit; //Reset InitData of new object diff --git a/TechbloxModdingAPI/Blocks/BlockEngine.cs b/TechbloxModdingAPI/Blocks/BlockEngine.cs index 80e14f3..c23ee8d 100644 --- a/TechbloxModdingAPI/Blocks/BlockEngine.cs +++ b/TechbloxModdingAPI/Blocks/BlockEngine.cs @@ -80,6 +80,16 @@ namespace TechbloxModdingAPI.Blocks return ref entitiesDB.QueryEntityOrDefault(block); } + internal ref T GetBlockInfo(EcsObjectBase obj) where T : unmanaged, IEntityComponent + { + return ref entitiesDB.QueryEntityOrDefault(obj); + } + + public ref T GetBlockInfoViewComponent(Block block) where T : struct, IEntityViewComponent + { + return ref entitiesDB.QueryEntityOrDefault(block); + } + public void UpdateDisplayedBlock(EGID id) { if (!BlockExists(id)) return; diff --git a/TechbloxModdingAPI/Blocks/DampedSpring.cs b/TechbloxModdingAPI/Blocks/DampedSpring.cs index 3c92f72..4623d6d 100644 --- a/TechbloxModdingAPI/Blocks/DampedSpring.cs +++ b/TechbloxModdingAPI/Blocks/DampedSpring.cs @@ -21,8 +21,7 @@ namespace TechbloxModdingAPI.Blocks { get => BlockEngine.GetBlockInfo(this).springFrequency; - set => BlockEngine.SetBlockInfo(this, - (ref DampedSpringReadOnlyStruct dsrs, float val) => dsrs.springFrequency = val, value); + set => BlockEngine.GetBlockInfo(this).springFrequency = value; } /// @@ -41,8 +40,7 @@ namespace TechbloxModdingAPI.Blocks { get => BlockEngine.GetBlockInfo(this).springDamping; - set => BlockEngine.SetBlockInfo(this, - (ref DampedSpringReadOnlyStruct ljf, float val) => ljf.springDamping = val, value); + set => BlockEngine.GetBlockInfo(this).springDamping = value; } /// @@ -52,8 +50,7 @@ namespace TechbloxModdingAPI.Blocks { get => BlockEngine.GetBlockInfo(this).maxExtent; - set => BlockEngine.SetBlockInfo(this, - (ref DampedSpringReadOnlyStruct ljf, float val) => ljf.maxExtent = val, value); + set => BlockEngine.GetBlockInfo(this).maxExtent = value; } } } \ No newline at end of file diff --git a/TechbloxModdingAPI/Blocks/MusicBlock.cs b/TechbloxModdingAPI/Blocks/MusicBlock.cs index ea4aeca..51e96ee 100644 --- a/TechbloxModdingAPI/Blocks/MusicBlock.cs +++ b/TechbloxModdingAPI/Blocks/MusicBlock.cs @@ -33,8 +33,7 @@ namespace TechbloxModdingAPI.Blocks set { - BlockEngine.SetBlockInfo(this, - (ref MusicBlockDataEntityStruct msdes, byte val) => msdes.trackIndx = val, value); + BlockEngine.GetBlockInfo(this).trackIndx = value; } } @@ -42,24 +41,22 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, - (MusicBlockDataEntityStruct msdes) => msdes.fmod2DEventPaths.Get(msdes.trackIndx)); + var msdes = BlockEngine.GetBlockInfo(this); + return msdes.fmod2DEventPaths.Get(msdes.trackIndx); } set { - BlockEngine.SetBlockInfo(this, (ref MusicBlockDataEntityStruct msdes, Guid val) => + ref var msdes = ref BlockEngine.GetBlockInfo(this); + for (byte i = 0; i < msdes.fmod2DEventPaths.Count(); i++) { - for (byte i = 0; i < msdes.fmod2DEventPaths.Count(); i++) + Guid track = msdes.fmod2DEventPaths.Get(i); + if (track == value) { - Guid track = msdes.fmod2DEventPaths.Get(i); - if (track == val) - { - msdes.trackIndx = i; - break; - } + msdes.trackIndx = i; + break; } - }, value); + } } } @@ -67,15 +64,13 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (MusicBlockDataEntityStruct msdes) => + var msdes = BlockEngine.GetBlockInfo(this); + Guid[] tracks = new Guid[msdes.fmod2DEventPaths.Count()]; + for (byte i = 0; i < tracks.Length; i++) { - Guid[] tracks = new Guid[msdes.fmod2DEventPaths.Count()]; - for (byte i = 0; i < tracks.Length; i++) - { - tracks[i] = msdes.fmod2DEventPaths.Get(i); - } - return tracks; - }); + tracks[i] = msdes.fmod2DEventPaths.Get(i); + } + return tracks; } } @@ -88,8 +83,7 @@ namespace TechbloxModdingAPI.Blocks set { - BlockEngine.SetBlockInfo(this, - (ref MusicBlockDataEntityStruct msdes, float val) => msdes.tweakableVolume = val, value); + BlockEngine.GetBlockInfo(this).tweakableVolume = value; } } @@ -98,14 +92,12 @@ namespace TechbloxModdingAPI.Blocks get { //Assert.Log("Block exists: " + Exists); - return BlockEngine.GetBlockInfo(this, - (MusicBlockDataEntityStruct msdes) => (ChannelType) msdes.channelType); + return (ChannelType) BlockEngine.GetBlockInfo(this).channelType; } set { - BlockEngine.SetBlockInfo(this, - (ref MusicBlockDataEntityStruct msdes, ChannelType val) => msdes.channelType = (byte) val, value); + BlockEngine.GetBlockInfo(this).channelType = (byte) value; } } @@ -113,33 +105,31 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, - (MusicBlockDataEntityStruct msdes) => msdes.isPlaying); + return BlockEngine.GetBlockInfo(this).isPlaying; } set { - BlockEngine.SetBlockInfo(this, (ref MusicBlockDataEntityStruct msdes, bool val) => + ref var msdes = ref BlockEngine.GetBlockInfo(this); + if (msdes.isPlaying == value) return; + if (value) { - if (msdes.isPlaying == val) return; - if (val) - { - // start playing - EventInstance inst = RuntimeManager.CreateInstance(msdes.fmod2DEventPaths.Get(msdes.trackIndx)); - inst.setVolume(msdes.tweakableVolume / 100f); - inst.start(); - msdes.eventHandle = inst.handle; - } - else - { - // stop playing - EventInstance inst = default(EventInstance); - inst.handle = msdes.eventHandle; - inst.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); - inst.release(); - } - msdes.isPlaying = val; - }, value); + // start playing + EventInstance inst = RuntimeManager.CreateInstance(msdes.fmod2DEventPaths.Get(msdes.trackIndx)); + inst.setVolume(msdes.tweakableVolume / 100f); + inst.start(); + msdes.eventHandle = inst.handle; + } + else + { + // stop playing + EventInstance inst = default(EventInstance); + inst.handle = msdes.eventHandle; + inst.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); + inst.release(); + } + + msdes.isPlaying = value; } } } diff --git a/TechbloxModdingAPI/Blocks/ObjectIdentifier.cs b/TechbloxModdingAPI/Blocks/ObjectIdentifier.cs index fe2d657..046054b 100644 --- a/TechbloxModdingAPI/Blocks/ObjectIdentifier.cs +++ b/TechbloxModdingAPI/Blocks/ObjectIdentifier.cs @@ -16,14 +16,11 @@ namespace TechbloxModdingAPI.Blocks public char Identifier { - get => (char) BlockEngine.GetBlockInfo(this).objectId + 'A'; + get => (char) (BlockEngine.GetBlockInfo(this).objectId + 'A'); set { - BlockEngine.SetBlockInfo(this, (ref ObjectIdEntityStruct st, char val) => - { - st.objectId = (byte) (val - 'A'); - Label = val + ""; //The label isn't updated automatically - }, value); + BlockEngine.GetBlockInfo(this).objectId = (byte) (value - 'A'); + Label = value + ""; //The label isn't updated automatically } } diff --git a/TechbloxModdingAPI/Blocks/SfxBlock.cs b/TechbloxModdingAPI/Blocks/SfxBlock.cs index 45453fb..6b6ab36 100644 --- a/TechbloxModdingAPI/Blocks/SfxBlock.cs +++ b/TechbloxModdingAPI/Blocks/SfxBlock.cs @@ -27,8 +27,7 @@ namespace TechbloxModdingAPI.Blocks set { - BlockEngine.SetBlockInfo(this, - (ref SoundSfxBlockDataEntityStruct obj, float val) => obj.tweakableVolume = val, value); + BlockEngine.GetBlockInfo(this).tweakableVolume = value; } } @@ -41,8 +40,7 @@ namespace TechbloxModdingAPI.Blocks set { - BlockEngine.SetBlockInfo(this, - (ref SoundSfxBlockDataEntityStruct obj, float val) => obj.tweakablePitch = val, value); + BlockEngine.GetBlockInfo(this).tweakablePitch = value; } } @@ -55,8 +53,7 @@ namespace TechbloxModdingAPI.Blocks set { - BlockEngine.SetBlockInfo(this, - (ref SoundSfxBlockDataEntityStruct obj, bool val) => obj.is3D = val, value); + BlockEngine.GetBlockInfo(this).is3D = value; } } @@ -64,13 +61,12 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => (ChannelType)obj.channelType); + return (ChannelType) BlockEngine.GetBlockInfo(this).channelType; } set { - BlockEngine.SetBlockInfo(this, - (ref SoundSfxBlockDataEntityStruct obj, ChannelType val) => obj.tweakableVolume = (byte) val, value); + BlockEngine.GetBlockInfo(this).channelType = (byte) value; } } @@ -83,8 +79,7 @@ namespace TechbloxModdingAPI.Blocks set { - BlockEngine.SetBlockInfo(this, - (ref SoundSfxBlockDataEntityStruct obj, byte val) => obj.soundEffectIndex = val, value); + BlockEngine.GetBlockInfo(this).soundEffectIndex = value; } } @@ -93,35 +88,36 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, - (SoundSfxBlockDataEntityStruct obj) => obj.is3D ? obj.fmod3DEventPaths.Get(obj.soundEffectIndex) : obj.fmod2DEventPaths.Get(obj.soundEffectIndex)); + var obj = BlockEngine.GetBlockInfo(this); + return obj.is3D + ? obj.fmod3DEventPaths.Get(obj.soundEffectIndex) + : obj.fmod2DEventPaths.Get(obj.soundEffectIndex); } set { - BlockEngine.SetBlockInfo(this, (ref SoundSfxBlockDataEntityStruct obj, Guid val) => + var obj = BlockEngine.GetBlockInfo(this); + for (byte i = 0; i < obj.fmod2DEventPaths.Count(); i++) { - for (byte i = 0; i < obj.fmod2DEventPaths.Count(); i++) + Guid track = obj.fmod2DEventPaths.Get(i); + if (track == value) { - Guid track = obj.fmod2DEventPaths.Get(i); - if (track == val) - { - obj.soundEffectIndex = i; - obj.is3D = false; - return; - } + obj.soundEffectIndex = i; + obj.is3D = false; + return; } - for (byte i = 0; i < obj.fmod3DEventPaths.Count(); i++) + } + + for (byte i = 0; i < obj.fmod3DEventPaths.Count(); i++) + { + Guid track = obj.fmod3DEventPaths.Get(i); + if (track == value) { - Guid track = obj.fmod3DEventPaths.Get(i); - if (track == val) - { - obj.soundEffectIndex = i; - obj.is3D = true; - return; - } + obj.soundEffectIndex = i; + obj.is3D = true; + return; } - }, value); + } } } @@ -130,31 +126,29 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => + var obj = BlockEngine.GetBlockInfo(this); + Guid[] tracks = new Guid[obj.fmod2DEventPaths.Count()]; + for (byte i = 0; i < tracks.Length; i++) { - Guid[] tracks = new Guid[obj.fmod2DEventPaths.Count()]; - for (byte i = 0; i < tracks.Length; i++) - { - tracks[i] = obj.fmod2DEventPaths.Get(i); - } - return tracks; - }); + tracks[i] = obj.fmod2DEventPaths.Get(i); + } + + return tracks; } } - + public Guid[] Tracks3D { get { - return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => + var obj = BlockEngine.GetBlockInfo(this); + Guid[] tracks = new Guid[obj.fmod3DEventPaths.Count()]; + for (byte i = 0; i < tracks.Length; i++) { - Guid[] tracks = new Guid[obj.fmod3DEventPaths.Count()]; - for (byte i = 0; i < tracks.Length; i++) - { - tracks[i] = obj.fmod2DEventPaths.Get(i); - } - return tracks; - }); + tracks[i] = obj.fmod2DEventPaths.Get(i); + } + + return tracks; } } @@ -167,8 +161,7 @@ namespace TechbloxModdingAPI.Blocks set { - BlockEngine.SetBlockInfo(this, - (ref SoundSfxBlockDataEntityStruct obj, bool val) => obj.isLoopedBlock = val, value); + BlockEngine.GetBlockInfo(this).isLoopedBlock = value; } } @@ -176,33 +169,33 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, - (SoundSfxBlockDataEntityStruct obj) => obj.isPlaying); + return BlockEngine.GetBlockInfo(this).isPlaying; } set { - BlockEngine.SetBlockInfo(this, (ref SoundSfxBlockDataEntityStruct obj, bool val) => + var obj = BlockEngine.GetBlockInfo(this); + if (obj.isPlaying == value) return; + if (value) { - if (obj.isPlaying == val) return; - if (val) - { - // start playing - EventInstance inst = RuntimeManager.CreateInstance(obj.is3D ? obj.fmod3DEventPaths.Get(obj.soundEffectIndex) : obj.fmod2DEventPaths.Get(obj.soundEffectIndex)); - inst.setVolume(obj.tweakableVolume / 100f); - inst.start(); - obj.eventHandle = inst.handle; - } - else - { - // stop playing - EventInstance inst = default(EventInstance); - inst.handle = obj.eventHandle; - inst.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); - inst.release(); - } - obj.isPlaying = val; - }, value); + // start playing + EventInstance inst = RuntimeManager.CreateInstance(obj.is3D + ? obj.fmod3DEventPaths.Get(obj.soundEffectIndex) + : obj.fmod2DEventPaths.Get(obj.soundEffectIndex)); + inst.setVolume(obj.tweakableVolume / 100f); + inst.start(); + obj.eventHandle = inst.handle; + } + else + { + // stop playing + EventInstance inst = default(EventInstance); + inst.handle = obj.eventHandle; + inst.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); + inst.release(); + } + + obj.isPlaying = value; } } } diff --git a/TechbloxModdingAPI/Blocks/SignalingBlock.cs b/TechbloxModdingAPI/Blocks/SignalingBlock.cs index 293e00d..45b5aa6 100644 --- a/TechbloxModdingAPI/Blocks/SignalingBlock.cs +++ b/TechbloxModdingAPI/Blocks/SignalingBlock.cs @@ -109,7 +109,6 @@ namespace TechbloxModdingAPI.Blocks /// The localized port name. public string PortName(byte port, bool input) { - BlockPortsStruct bps = BlockEngine.GetBlockInfo(this, (BlockPortsStruct a) => a); PortEntityStruct pes = SignalEngine.GetPortByOffset(this, port, input); return pes.portNameLocalised; } diff --git a/TechbloxModdingAPI/Blocks/TextBlock.cs b/TechbloxModdingAPI/Blocks/TextBlock.cs index c3ee1b0..99c753a 100644 --- a/TechbloxModdingAPI/Blocks/TextBlock.cs +++ b/TechbloxModdingAPI/Blocks/TextBlock.cs @@ -32,11 +32,9 @@ namespace TechbloxModdingAPI.Blocks set { if (value == null) value = ""; - BlockEngine.SetBlockInfo(this, (ref TextBlockDataStruct tbds, string val) => - { - tbds.textCurrent.Set(val); - tbds.textStored.Set(val, true); - }, value); + var tbds = BlockEngine.GetBlockInfo(this); + tbds.textCurrent.Set(value); + tbds.textStored.Set(value, true); } } @@ -50,8 +48,7 @@ namespace TechbloxModdingAPI.Blocks set { if (value == null) value = ""; - BlockEngine.SetBlockInfo(this, (ref TextBlockDataStruct tbds, string val) => - tbds.textBlockID.Set(val), value); + BlockEngine.GetBlockInfo(this).textBlockID.Set(value); } } } diff --git a/TechbloxModdingAPI/Cluster.cs b/TechbloxModdingAPI/Cluster.cs index 11b995c..2544194 100644 --- a/TechbloxModdingAPI/Cluster.cs +++ b/TechbloxModdingAPI/Cluster.cs @@ -8,9 +8,9 @@ namespace TechbloxModdingAPI /// Represnts a cluster of blocks in time running mode, meaning blocks that are connected either directly or via joints. /// Only exists if a cluster destruction manager is present. Static blocks like grass and dirt aren't part of a cluster. /// - public class Cluster + public class Cluster : EcsObjectBase { - public EGID Id { get; } + public override EGID Id { get; } public Cluster(EGID id) { @@ -23,20 +23,20 @@ namespace TechbloxModdingAPI public float InitialHealth { - get => Block.BlockEngine.GetBlockInfo(Id).initialHealth; - set => Block.BlockEngine.GetBlockInfo(Id).initialHealth = value; + get => Block.BlockEngine.GetBlockInfo(this).initialHealth; + set => Block.BlockEngine.GetBlockInfo(this).initialHealth = value; } public float CurrentHealth { - get => Block.BlockEngine.GetBlockInfo(Id).currentHealth; - set => Block.BlockEngine.GetBlockInfo(Id).currentHealth = value; + get => Block.BlockEngine.GetBlockInfo(this).currentHealth; + set => Block.BlockEngine.GetBlockInfo(this).currentHealth = value; } public float HealthMultiplier { - get => Block.BlockEngine.GetBlockInfo(Id).healthMultiplier; - set => Block.BlockEngine.GetBlockInfo(Id).healthMultiplier = value; + get => Block.BlockEngine.GetBlockInfo(this).healthMultiplier; + set => Block.BlockEngine.GetBlockInfo(this).healthMultiplier = value; } /// diff --git a/TechbloxModdingAPI/Players/FlyCamEngine.cs b/TechbloxModdingAPI/Players/FlyCamEngine.cs index 0b98071..cd52363 100644 --- a/TechbloxModdingAPI/Players/FlyCamEngine.cs +++ b/TechbloxModdingAPI/Players/FlyCamEngine.cs @@ -1,6 +1,7 @@ using Svelto.ECS; using Techblox.FlyCam; using TechbloxModdingAPI.Engines; +using TechbloxModdingAPI.Utility; namespace TechbloxModdingAPI.Players { diff --git a/TechbloxModdingAPI/SimBody.cs b/TechbloxModdingAPI/SimBody.cs index dd7429e..55c6a9e 100644 --- a/TechbloxModdingAPI/SimBody.cs +++ b/TechbloxModdingAPI/SimBody.cs @@ -12,9 +12,9 @@ namespace TechbloxModdingAPI /// /// A rigid body (like a chunk of connected blocks) during simulation. /// - public class SimBody : IEquatable, IEquatable + public class SimBody : EcsObjectBase, IEquatable, IEquatable { - public EGID Id { get; } + public override EGID Id { get; } /// /// The cluster this chunk belongs to, or null if no cluster destruction manager present or the chunk doesn't exist. @@ -92,26 +92,26 @@ namespace TechbloxModdingAPI public float InitialHealth { - get => Block.BlockEngine.GetBlockInfo(Id).initialHealth; - set => Block.BlockEngine.GetBlockInfo(Id).initialHealth = value; + get => Block.BlockEngine.GetBlockInfo(this).initialHealth; + set => Block.BlockEngine.GetBlockInfo(this).initialHealth = value; } public float CurrentHealth { - get => Block.BlockEngine.GetBlockInfo(Id).currentHealth; - set => Block.BlockEngine.GetBlockInfo(Id).currentHealth = value; + get => Block.BlockEngine.GetBlockInfo(this).currentHealth; + set => Block.BlockEngine.GetBlockInfo(this).currentHealth = value; } public float HealthMultiplier { - get => Block.BlockEngine.GetBlockInfo(Id).healthMultiplier; - set => Block.BlockEngine.GetBlockInfo(Id).healthMultiplier = value; + get => Block.BlockEngine.GetBlockInfo(this).healthMultiplier; + set => Block.BlockEngine.GetBlockInfo(this).healthMultiplier = value; } /// /// Whether the body can be moved or static. /// - public bool Static => Block.BlockEngine.GetBlockInfo(Id).isStatic; //Setting it doesn't have any effect + public bool Static => Block.BlockEngine.GetBlockInfo(this).isStatic; //Setting it doesn't have any effect /// /// The rigid bodies connected to this one via functional joints (broken ones don't count). @@ -132,7 +132,7 @@ namespace TechbloxModdingAPI private ref RigidBodyEntityStruct GetStruct() { - return ref Block.BlockEngine.GetBlockInfo(Id); + return ref Block.BlockEngine.GetBlockInfo(this); } public override string ToString() diff --git a/TechbloxModdingAPI/Utility/ManagedApiExtensions.cs b/TechbloxModdingAPI/Utility/ManagedApiExtensions.cs new file mode 100644 index 0000000..2616ab7 --- /dev/null +++ b/TechbloxModdingAPI/Utility/ManagedApiExtensions.cs @@ -0,0 +1,55 @@ +using Svelto.ECS; +using Svelto.ECS.Hybrid; +using TechbloxModdingAPI.Blocks; + +namespace TechbloxModdingAPI.Utility +{ + public static class ManagedApiExtensions + { + /// + /// Attempts to query an entity and returns an optional that contains the result if succeeded. + /// This overload does not take initializer data into account. + /// + /// The entities DB + /// The EGID to query + /// The component type to query + /// An optional that contains the result on success or is empty if not found + public static OptionalRef QueryEntityOptional(this EntitiesDB entitiesDB, EGID egid) + where T : struct, IEntityViewComponent + { + return entitiesDB.TryQueryEntitiesAndIndex(egid, out uint index, out var array) + ? new OptionalRef(array, index) + : new OptionalRef(); + } + + /// + /// Attempts to query an entity and returns the result or a dummy value that can be modified. + /// + /// + /// + /// + /// + public static OptionalRef QueryEntityOptional(this EntitiesDB entitiesDB, EcsObjectBase obj) + where T : struct, IEntityViewComponent + { + var opt = QueryEntityOptional(entitiesDB, obj.Id); + return opt ? opt : new OptionalRef(obj, true); + } + + /// + /// Attempts to query an entity and returns the result or a dummy value that can be modified. + /// + /// + /// + /// + /// + public static ref T QueryEntityOrDefault(this EntitiesDB entitiesDB, EcsObjectBase obj) + where T : struct, IEntityViewComponent + { + var opt = QueryEntityOptional(entitiesDB, obj.Id); + if (opt) return ref opt.Get(); + if (obj.InitData.Valid) return ref obj.InitData.Initializer(obj.Id).GetOrCreate(); + return ref opt.Get(); //Default value + } + } +} \ No newline at end of file diff --git a/TechbloxModdingAPI/Utility/ApiExtensions.cs b/TechbloxModdingAPI/Utility/NativeApiExtensions.cs similarity index 92% rename from TechbloxModdingAPI/Utility/ApiExtensions.cs rename to TechbloxModdingAPI/Utility/NativeApiExtensions.cs index 3da1a67..701e42f 100644 --- a/TechbloxModdingAPI/Utility/ApiExtensions.cs +++ b/TechbloxModdingAPI/Utility/NativeApiExtensions.cs @@ -3,10 +3,11 @@ using TechbloxModdingAPI.Blocks; namespace TechbloxModdingAPI.Utility { - public static class ApiExtensions + public static class NativeApiExtensions { /// /// Attempts to query an entity and returns an optional that contains the result if succeeded. + /// This overload does not take initializer data into account. /// /// The entities DB /// The EGID to query @@ -31,7 +32,7 @@ namespace TechbloxModdingAPI.Utility where T : unmanaged, IEntityComponent { var opt = QueryEntityOptional(entitiesDB, obj.Id); - return opt ? opt : new OptionalRef(obj); + return opt ? opt : new OptionalRef(obj, true); } /// diff --git a/TechbloxModdingAPI/Utility/OptionalRef.cs b/TechbloxModdingAPI/Utility/OptionalRef.cs index 2323431..c5cfb83 100644 --- a/TechbloxModdingAPI/Utility/OptionalRef.cs +++ b/TechbloxModdingAPI/Utility/OptionalRef.cs @@ -1,44 +1,53 @@ using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using TechbloxModdingAPI.Blocks; +using System.Runtime.InteropServices; using Svelto.DataStructures; using Svelto.ECS; -namespace TechbloxModdingAPI +namespace TechbloxModdingAPI.Utility { - public ref struct OptionalRef where T : unmanaged, IEntityComponent + [StructLayout(LayoutKind.Explicit)] //Make the array and managedArray fields take up the same space + public ref struct OptionalRef where T : struct, IEntityComponent { - private bool exists; - private NB array; - private uint index; - private EntityInitializer initializer; + [FieldOffset(0)] private readonly State state; + [FieldOffset(1)] private readonly uint index; + [FieldOffset(5)] private NB array; + [FieldOffset(5)] private MB managedArray; + [FieldOffset(1)] private readonly EntityInitializer initializer; + //The possible fields are: (index && (array || managedArray)) || initializer public OptionalRef(NB array, uint index) { - exists = true; + state = State.Native; this.array = array; this.index = index; initializer = default; } - + + public OptionalRef(MB array, uint index) + { + state = State.Managed; + managedArray = array; + this.index = index; + initializer = default; + this.array = default; + } + /// /// Wraps the initializer data, if present. /// /// The object with the initializer - public OptionalRef(EcsObjectBase obj) + /// Whether the struct is unmanaged + public OptionalRef(EcsObjectBase obj, bool unmanaged) { if (obj.InitData.Valid) { initializer = obj.InitData.Initializer(obj.Id); - exists = true; + state = (unmanaged ? State.Native : State.Managed) | State.Initializer; } else { initializer = default; - exists = false; + state = State.Empty; } array = default; index = default; @@ -50,31 +59,36 @@ namespace TechbloxModdingAPI /// The value or the default value public ref T Get() { - if (!exists) return ref CompRefCache.Default; - if (initializer.EGID == EGID.Empty) - return ref array[index]; - return ref initializer.GetOrCreate(); + if (state == State.Empty) return ref CompRefCache.Default; + if ((state & State.Initializer) != State.Empty) return ref initializer.GetOrCreate(); + if ((state & State.Native) != State.Empty) return ref array[index]; + return ref managedArray[index]; } - public bool Exists => exists; + public bool Exists => state != State.Empty; public static implicit operator T(OptionalRef opt) => opt.Get(); - public static implicit operator bool(OptionalRef opt) => opt.exists; - - /*public delegate ref TR Mapper(ref T component) where TR : unmanaged; - public unsafe delegate TR* PMapper(T* component) where TR : unmanaged; - - public unsafe OptionalRef Map(PMapper mapper) where TR : unmanaged => - exists ? new OptionalRef(ref *mapper(pointer)) : new OptionalRef();*/ + public static implicit operator bool(OptionalRef opt) => opt.state != State.Empty; /// /// Creates an instance of a struct T that can be referenced. /// - /// The struct type to cache - private struct CompRefCache where TR : unmanaged + internal struct CompRefCache { - public static TR Default; + public static T Default; + } + + /// + /// A byte that holds state in its bits. + /// + [Flags] + private enum State : byte + { + Empty, + Native, + Managed, + Initializer = 4 } } } \ No newline at end of file From 3eef859095a289b29bd5ce61faec2302926efdc2 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Tue, 11 May 2021 22:56:36 +0200 Subject: [PATCH 5/7] Update gen_csproj script and references --- Automation/gen_csproj.py | 8 ++++---- TechbloxModdingAPI/TechbloxModdingAPI.csproj | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Automation/gen_csproj.py b/Automation/gen_csproj.py index af00dd1..515bcda 100755 --- a/Automation/gen_csproj.py +++ b/Automation/gen_csproj.py @@ -27,7 +27,7 @@ def buildReferencesXml(path): return "\n \n" + "".join(result) + " \n" if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Generate GamecraftModdingAPI.csproj") + parser = argparse.ArgumentParser(description="Generate TechbloxModdingAPI.csproj") # TODO (maybe?): add params for custom csproj read and write locations args = parser.parse_args() @@ -35,8 +35,8 @@ if __name__ == "__main__": asmXml = buildReferencesXml("../ref/TechbloxPreview_Data/Managed") # print(asmXml) - with open("../GamecraftModdingAPI/GamecraftModdingAPI.csproj", "r") as xmlFile: - print("Parsing GamecraftModdingAPI.csproj") + with open("../TechbloxModdingAPI/TechbloxModdingAPI.csproj", "r") as xmlFile: + print("Parsing TechbloxModdingAPI.csproj") fileStr = xmlFile.read() # print(fileStr) depsStart = re.search(r"\