Merge branch 'feature-ecs_object_base'

This commit is contained in:
Norbi Peti 2021-05-12 00:51:56 +02:00
commit aa12b848d0
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
27 changed files with 526 additions and 516 deletions

View file

@ -27,7 +27,7 @@ def buildReferencesXml(path):
return "<!--Start Dependencies-->\n <ItemGroup>\n" + "".join(result) + " </ItemGroup>\n<!--End Dependencies-->" return "<!--Start Dependencies-->\n <ItemGroup>\n" + "".join(result) + " </ItemGroup>\n<!--End Dependencies-->"
if __name__ == "__main__": 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 # TODO (maybe?): add params for custom csproj read and write locations
args = parser.parse_args() args = parser.parse_args()
@ -35,8 +35,8 @@ if __name__ == "__main__":
asmXml = buildReferencesXml("../ref/TechbloxPreview_Data/Managed") asmXml = buildReferencesXml("../ref/TechbloxPreview_Data/Managed")
# print(asmXml) # print(asmXml)
with open("../GamecraftModdingAPI/GamecraftModdingAPI.csproj", "r") as xmlFile: with open("../TechbloxModdingAPI/TechbloxModdingAPI.csproj", "r") as xmlFile:
print("Parsing GamecraftModdingAPI.csproj") print("Parsing TechbloxModdingAPI.csproj")
fileStr = xmlFile.read() fileStr = xmlFile.read()
# print(fileStr) # print(fileStr)
depsStart = re.search(r"\<!--\s*Start\s+Dependencies\s*--\>", fileStr) depsStart = re.search(r"\<!--\s*Start\s+Dependencies\s*--\>", fileStr)
@ -45,7 +45,7 @@ if __name__ == "__main__":
print("Unable to find dependency XML comments, aborting!") print("Unable to find dependency XML comments, aborting!")
exit(1) exit(1)
newFileStr = fileStr[:depsStart.start()] + "\n" + asmXml + "\n" + fileStr[depsEnd.end() + 1:] newFileStr = fileStr[:depsStart.start()] + "\n" + asmXml + "\n" + fileStr[depsEnd.end() + 1:]
with open("../GamecraftModdingAPI/GamecraftModdingAPI.csproj", "w") as xmlFile: with open("../TechbloxModdingAPI/TechbloxModdingAPI.csproj", "w") as xmlFile:
print("Writing Assembly references") print("Writing Assembly references")
xmlFile.write(newFileStr) xmlFile.write(newFileStr)
# print(newFileStr) # print(newFileStr)

View file

@ -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. /// 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. /// For specific block type operations, use the specialised block classes in the TechbloxModdingAPI.Blocks namespace.
/// </summary> /// </summary>
public class Block : IEquatable<Block>, IEquatable<EGID> public class Block : EcsObjectBase, IEquatable<Block>, IEquatable<EGID>
{ {
protected static readonly PlacementEngine PlacementEngine = new PlacementEngine(); protected static readonly PlacementEngine PlacementEngine = new PlacementEngine();
protected static readonly MovementEngine MovementEngine = new MovementEngine(); protected static readonly MovementEngine MovementEngine = new MovementEngine();
@ -78,8 +78,7 @@ namespace TechbloxModdingAPI
var initializer = PlacementEngine.PlaceBlock(block, position, player, autoWire); var initializer = PlacementEngine.PlaceBlock(block, position, player, autoWire);
var egid = initializer.EGID; var egid = initializer.EGID;
var bl = New<T>(egid.entityID, egid.groupID); var bl = New<T>(egid.entityID, egid.groupID);
bl.InitData.Group = BlockEngine.InitGroup(initializer); bl.InitData = initializer;
bl.InitData.Reference = initializer.reference;
Placed += bl.OnPlacedInit; Placed += bl.OnPlacedInit;
return bl; return bl;
} }
@ -241,13 +240,12 @@ namespace TechbloxModdingAPI
throw new BlockException("Blocks can only be placed in build mode."); throw new BlockException("Blocks can only be placed in build mode.");
var initializer = PlacementEngine.PlaceBlock(type, position, player, autoWire); var initializer = PlacementEngine.PlaceBlock(type, position, player, autoWire);
Id = initializer.EGID; Id = initializer.EGID;
InitData.Group = BlockEngine.InitGroup(initializer); InitData = initializer;
Placed += OnPlacedInit; Placed += OnPlacedInit;
} }
public EGID Id { get; } public override EGID Id { get; }
internal BlockEngine.BlockInitData InitData;
private EGID copiedFrom; private EGID copiedFrom;
/// <summary> /// <summary>
@ -256,10 +254,10 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public float3 Position public float3 Position
{ {
get => MovementEngine.GetPosition(Id, InitData); get => MovementEngine.GetPosition(this);
set set
{ {
MovementEngine.MoveBlock(Id, InitData, value); MovementEngine.MoveBlock(this, value);
if (blockGroup != null) if (blockGroup != null)
blockGroup.PosAndRotCalculated = false; blockGroup.PosAndRotCalculated = false;
BlockEngine.UpdateDisplayedBlock(Id); BlockEngine.UpdateDisplayedBlock(Id);
@ -271,10 +269,10 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public float3 Rotation public float3 Rotation
{ {
get => RotationEngine.GetRotation(Id, InitData); get => RotationEngine.GetRotation(this);
set set
{ {
RotationEngine.RotateBlock(Id, InitData, value); RotationEngine.RotateBlock(this, value);
if (blockGroup != null) if (blockGroup != null)
blockGroup.PosAndRotCalculated = false; blockGroup.PosAndRotCalculated = false;
BlockEngine.UpdateDisplayedBlock(Id); BlockEngine.UpdateDisplayedBlock(Id);
@ -287,14 +285,14 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public float3 Scale public float3 Scale
{ {
get => BlockEngine.GetBlockInfo(this, (ScalingEntityStruct st) => st.scale); get => BlockEngine.GetBlockInfo<ScalingEntityStruct>(this).scale;
set set
{ {
int uscale = UniformScale; int uscale = UniformScale;
if (value.x < 4e-5) value.x = uscale; if (value.x < 4e-5) value.x = uscale;
if (value.y < 4e-5) value.y = uscale; if (value.y < 4e-5) value.y = uscale;
if (value.z < 4e-5) value.z = uscale; if (value.z < 4e-5) value.z = uscale;
BlockEngine.SetBlockInfo(this, (ref ScalingEntityStruct st, float3 val) => st.scale = val, value); BlockEngine.GetBlockInfo<ScalingEntityStruct>(this).scale = value;
if (!Exists) return; //UpdateCollision needs the block to exist if (!Exists) return; //UpdateCollision needs the block to exist
ScalingEngine.UpdateCollision(Id); ScalingEngine.UpdateCollision(Id);
BlockEngine.UpdateDisplayedBlock(Id); BlockEngine.UpdateDisplayedBlock(Id);
@ -307,12 +305,11 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public int UniformScale public int UniformScale
{ {
get => BlockEngine.GetBlockInfo(this, (UniformBlockScaleEntityStruct st) => st.scaleFactor); get => BlockEngine.GetBlockInfo<UniformBlockScaleEntityStruct>(this).scaleFactor;
set set
{ {
if (value < 1) value = 1; if (value < 1) value = 1;
BlockEngine.SetBlockInfo(this, (ref UniformBlockScaleEntityStruct st, int val) => st.scaleFactor = val, BlockEngine.GetBlockInfo<UniformBlockScaleEntityStruct>(this).scaleFactor = value;
value);
Scale = new float3(value, value, value); Scale = new float3(value, value, value);
} }
} }
@ -322,16 +319,12 @@ namespace TechbloxModdingAPI
*/ */
public bool Flipped public bool Flipped
{ {
get => BlockEngine.GetBlockInfo(this, (ScalingEntityStruct st) => st.scale.x < 0); get => BlockEngine.GetBlockInfo<ScalingEntityStruct>(this).scale.x < 0;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref ScalingEntityStruct st, bool val) => var st = BlockEngine.GetBlockInfo<ScalingEntityStruct>(this);
st.scale.x = math.abs(st.scale.x) * (val ? -1 : 1), value); st.scale.x = math.abs(st.scale.x) * (value ? -1 : 1);
BlockEngine.SetBlockInfo(this, (ref GFXPrefabEntityStructGPUI st, bool val) => BlockEngine.UpdatePrefab(this, (ushort) Type, (byte) Material, value);
{
uint prefabId = PrefabsID.GetOrCreatePrefabID((ushort) Type, (byte) Material, 0, value);
st.prefabID = prefabId;
}, value);
} }
} }
@ -342,7 +335,8 @@ namespace TechbloxModdingAPI
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (DBEntityStruct st) => (BlockIDs) st.DBID, BlockIDs.Invalid); var opt = BlockEngine.GetBlockInfoOptional<DBEntityStruct>(this);
return opt ? (BlockIDs) opt.Get().DBID : BlockIDs.Invalid;
} }
} }
@ -353,18 +347,16 @@ namespace TechbloxModdingAPI
{ {
get get
{ {
byte index = BlockEngine.GetBlockInfo(this, (ColourParameterEntityStruct st) => st.indexInPalette, var opt = BlockEngine.GetBlockInfoOptional<ColourParameterEntityStruct>(this);
byte.MaxValue); return new BlockColor(opt ? opt.Get().indexInPalette : byte.MaxValue);
return new BlockColor(index);
} }
set set
{ {
BlockEngine.SetBlockInfo(this, (ref ColourParameterEntityStruct color, BlockColor val) => //TODO: Check if setting to 255 works
{ //TODO: Check if setting to 255 works var color = BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(this);
color.indexInPalette = val.Index; color.indexInPalette = value.Index;
color.hasNetworkChange = true; color.hasNetworkChange = true;
color.paletteColour = BlockEngine.ConvertBlockColor(color.indexInPalette); color.paletteColour = BlockEngine.ConvertBlockColor(color.indexInPalette);
}, value);
} }
} }
@ -373,14 +365,12 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public float4 CustomColor public float4 CustomColor
{ {
get => BlockEngine.GetBlockInfo(this, (ColourParameterEntityStruct st) => st.paletteColour); get => BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(this).paletteColour;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref ColourParameterEntityStruct color, float4 val) => ref var color = ref BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(this);
{ color.paletteColour = value;
color.paletteColour = val; color.hasNetworkChange = true;
color.hasNetworkChange = true;
}, value);
} }
} }
@ -389,9 +379,16 @@ namespace TechbloxModdingAPI
*/ */
public BlockMaterial Material public BlockMaterial Material
{ {
get => BlockEngine.GetBlockInfo(this, (CubeMaterialStruct cmst) => (BlockMaterial) cmst.materialId, BlockMaterial.Default); get
set => BlockEngine.SetBlockInfo(this, {
(ref CubeMaterialStruct cmst, BlockMaterial val) => cmst.materialId = (byte) val, value); var opt = BlockEngine.GetBlockInfoOptional<CubeMaterialStruct>(this);
return opt ? (BlockMaterial) opt.Get().materialId : BlockMaterial.Default;
}
set
{
BlockEngine.GetBlockInfo<CubeMaterialStruct>(this).materialId = (byte) value;
BlockEngine.UpdatePrefab(this, (ushort) Type, (byte) value, Flipped); //TODO: Test default
}
} }
/// <summary> /// <summary>
@ -400,13 +397,11 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public string Label public string Label
{ {
get => BlockEngine.GetBlockInfoViewStruct(this, (TextLabelEntityViewStruct st) => st.textLabelComponent?.text); get => BlockEngine.GetBlockInfoViewComponent<TextLabelEntityViewStruct>(this).textLabelComponent?.text;
set set
{ {
BlockEngine.SetBlockInfoViewStruct(this, (ref TextLabelEntityViewStruct text, string val) => var comp = BlockEngine.GetBlockInfoViewComponent<TextLabelEntityViewStruct>(this).textLabelComponent;
{ if (comp != null) comp.text = value;
if (text.textLabelComponent != null) text.textLabelComponent.text = val;
}, value);
} }
} }
@ -424,9 +419,8 @@ namespace TechbloxModdingAPI
get get
{ {
if (blockGroup != null) return blockGroup; if (blockGroup != null) return blockGroup;
return blockGroup = BlockEngine.GetBlockInfo(this, var bgec = BlockEngine.GetBlockInfo<BlockGroupEntityComponent>(this);
(BlockGroupEntityComponent bgec) => return blockGroup = bgec.currentBlockGroup == -1 ? null : new BlockGroup(bgec.currentBlockGroup, this);
bgec.currentBlockGroup == -1 ? null : new BlockGroup(bgec.currentBlockGroup, this));
} }
set set
{ {
@ -437,9 +431,7 @@ namespace TechbloxModdingAPI
return; return;
} }
blockGroup?.RemoveInternal(this); blockGroup?.RemoveInternal(this);
BlockEngine.SetBlockInfo(this, BlockEngine.GetBlockInfo<BlockGroupEntityComponent>(this).currentBlockGroup = (int?) value?.Id.entityID ?? -1;
(ref BlockGroupEntityComponent bgec, BlockGroup val) => bgec.currentBlockGroup = val?.Id ?? -1,
value);
value?.AddInternal(this); value?.AddInternal(this);
blockGroup = value; blockGroup = value;
} }
@ -469,10 +461,10 @@ namespace TechbloxModdingAPI
/// <returns>The SimBody of the chunk or null if the block doesn't exist or not in simulation mode.</returns> /// <returns>The SimBody of the chunk or null if the block doesn't exist or not in simulation mode.</returns>
public SimBody GetSimBody() public SimBody GetSimBody()
{ {
return BlockEngine.GetBlockInfo(this, var st = BlockEngine.GetBlockInfo<GridConnectionsEntityStruct>(this);
(GridConnectionsEntityStruct st) => st.machineRigidBodyId != uint.MaxValue return st.machineRigidBodyId != uint.MaxValue
? new SimBody(st.machineRigidBodyId, st.clusterId) ? new SimBody(st.machineRigidBodyId, st.clusterId)
: null); : null;
} }
/// <summary> /// <summary>
@ -558,7 +550,7 @@ namespace TechbloxModdingAPI
//Lets improve that using delegates //Lets improve that using delegates
var block = New<T>(Id.entityID, Id.groupID); var block = New<T>(Id.entityID, Id.groupID);
if (this.InitData.Group != null) if (this.InitData.Valid)
{ {
block.InitData = this.InitData; block.InitData = this.InitData;
Placed += block.OnPlacedInit; //Reset InitData of new object Placed += block.OnPlacedInit; //Reset InitData of new object

View file

@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using Gamecraft.Blocks.BlockGroups; using Gamecraft.Blocks.BlockGroups;
using Svelto.ECS;
using Unity.Mathematics; using Unity.Mathematics;
using UnityEngine; using UnityEngine;
using TechbloxModdingAPI.Blocks; using TechbloxModdingAPI.Blocks;
@ -13,10 +14,10 @@ namespace TechbloxModdingAPI
/// <summary> /// <summary>
/// A group of blocks that can be selected together. The placed version of blueprints. Dispose after usage. /// A group of blocks that can be selected together. The placed version of blueprints. Dispose after usage.
/// </summary> /// </summary>
public class BlockGroup : ICollection<Block>, IDisposable public class BlockGroup : EcsObjectBase, ICollection<Block>, IDisposable
{ {
internal static BlueprintEngine _engine = new BlueprintEngine(); internal static BlueprintEngine _engine = new BlueprintEngine();
public int Id { get; } public override EGID Id { get; }
private readonly Block sourceBlock; private readonly Block sourceBlock;
private readonly List<Block> blocks; private readonly List<Block> blocks;
private float3 position, rotation; private float3 position, rotation;
@ -26,7 +27,7 @@ namespace TechbloxModdingAPI
{ {
if (id == BlockGroupUtility.GROUP_UNASSIGNED) if (id == BlockGroupUtility.GROUP_UNASSIGNED)
throw new BlockException("Cannot create a block group for blocks without a group!"); throw new BlockException("Cannot create a block group for blocks without a group!");
Id = id; Id = new EGID((uint) id, BlockGroupExclusiveGroups.BlockGroupEntityGroup);
sourceBlock = block; sourceBlock = block;
blocks = new List<Block>(GetBlocks()); blocks = new List<Block>(GetBlocks());
Block.Removed += OnBlockRemoved; Block.Removed += OnBlockRemoved;
@ -168,7 +169,7 @@ namespace TechbloxModdingAPI
internal void AddInternal(Block item) internal void AddInternal(Block item)
{ {
blocks.Add(item); blocks.Add(item);
_engine.AddBlockToGroup(item.Id, Id); _engine.AddBlockToGroup(item.Id, (int) Id.entityID);
} }
/// <summary> /// <summary>

View file

@ -9,6 +9,7 @@ using RobocraftX.Blocks;
using RobocraftX.Common; using RobocraftX.Common;
using RobocraftX.Physics; using RobocraftX.Physics;
using RobocraftX.Rendering; using RobocraftX.Rendering;
using RobocraftX.Rendering.GPUI;
using Svelto.ECS.EntityStructs; using Svelto.ECS.EntityStructs;
using Svelto.DataStructures; using Svelto.DataStructures;
@ -16,6 +17,7 @@ using Svelto.ECS;
using Svelto.ECS.Hybrid; using Svelto.ECS.Hybrid;
using Unity.Mathematics; using Unity.Mathematics;
using TechbloxModdingAPI.Engines; using TechbloxModdingAPI.Engines;
using TechbloxModdingAPI.Utility;
namespace TechbloxModdingAPI.Blocks namespace TechbloxModdingAPI.Blocks
{ {
@ -68,76 +70,24 @@ namespace TechbloxModdingAPI.Blocks
: entitiesDB.QueryEntity<PaletteEntryEntityStruct>(index, : entitiesDB.QueryEntity<PaletteEntryEntityStruct>(index,
CommonExclusiveGroups.COLOUR_PALETTE_GROUP).Colour; CommonExclusiveGroups.COLOUR_PALETTE_GROUP).Colour;
public ref T GetBlockInfo<T>(EGID blockID) where T : unmanaged, IEntityComponent public OptionalRef<T> GetBlockInfoOptional<T>(Block block) where T : unmanaged, IEntityComponent
{ {
if (entitiesDB.Exists<T>(blockID)) return entitiesDB.QueryEntityOptional<T>(block);
return ref entitiesDB.QueryEntity<T>(blockID);
T[] structHolder = new T[1]; //Create something that can be referenced
return ref structHolder[0]; //Gets a default value automatically
} }
public ref T GetBlockInfoViewStruct<T>(EGID blockID) where T : struct, INeedEGID, IEntityViewComponent public ref T GetBlockInfo<T>(Block block) where T : unmanaged, IEntityComponent
{ {
if (entitiesDB.Exists<T>(blockID)) return ref entitiesDB.QueryEntityOrDefault<T>(block);
return ref entitiesDB.QueryEntity<T>(blockID);
T[] structHolder = new T[1]; //Create something that can be referenced
return ref structHolder[0]; //Gets a default value automatically
} }
public U GetBlockInfo<T, U>(Block block, Func<T, U> getter, internal ref T GetBlockInfo<T>(EcsObjectBase obj) where T : unmanaged, IEntityComponent
U def = default) where T : unmanaged, IEntityComponent
{ {
if (entitiesDB.Exists<T>(block.Id)) return ref entitiesDB.QueryEntityOrDefault<T>(obj);
return getter(entitiesDB.QueryEntity<T>(block.Id));
return GetBlockInitInfo(block, getter, def);
} }
public U GetBlockInfoViewStruct<T, U>(Block block, Func<T, U> getter, public ref T GetBlockInfoViewComponent<T>(Block block) where T : struct, IEntityViewComponent
U def = default) where T : struct, IEntityViewComponent
{ {
if (entitiesDB.Exists<T>(block.Id)) return ref entitiesDB.QueryEntityOrDefault<T>(block);
return getter(entitiesDB.QueryEntity<T>(block.Id));
return GetBlockInitInfo(block, getter, def);
}
private U GetBlockInitInfo<T, U>(Block block, Func<T, U> 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<T>())
return getter(initializer.Get<T>());
return def;
}
public delegate void Setter<T, U>(ref T component, U value) where T : struct, IEntityComponent;
public void SetBlockInfoViewStruct<T, U>(Block block, Setter<T, U> setter, U value) where T : struct, IEntityViewComponent
{
if (entitiesDB.Exists<T>(block.Id))
setter(ref entitiesDB.QueryEntity<T>(block.Id), value);
else
SetBlockInitInfo(block, setter, value);
}
public void SetBlockInfo<T, U>(Block block, Setter<T, U> setter, U value) where T : unmanaged, IEntityComponent
{
if (entitiesDB.Exists<T>(block.Id))
setter(ref entitiesDB.QueryEntity<T>(block.Id), value);
else
SetBlockInitInfo(block, setter, value);
}
private void SetBlockInitInfo<T, U>(Block block, Setter<T, U> 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<T>() ? initializer.Get<T>() : default;
ref T structRef = ref component;
setter(ref structRef, value);
initializer.Init(structRef);
}
} }
public void UpdateDisplayedBlock(EGID id) public void UpdateDisplayedBlock(EGID id)
@ -149,21 +99,18 @@ namespace TechbloxModdingAPI.Blocks
entitiesDB.QueryEntity<RenderingDataStruct>(id).matrix = float4x4.TRS(pos.position, rot.rotation, scale.scale); entitiesDB.QueryEntity<RenderingDataStruct>(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<GFXPrefabEntityStructGPUI>(block).prefabID = pid;
entitiesDB.QueryEntityOrDefault<PhysicsPrefabEntityStruct>(block) = new PhysicsPrefabEntityStruct(pid);
}
public bool BlockExists(EGID blockID) public bool BlockExists(EGID blockID)
{ {
return entitiesDB.Exists<DBEntityStruct>(blockID); return entitiesDB.Exists<DBEntityStruct>(blockID);
} }
public bool GetBlockInfoExists<T>(Block block) where T : struct, IEntityComponent
{
if (entitiesDB.Exists<T>(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<T>();
}
public SimBody[] GetSimBodiesFromID(byte id) public SimBody[] GetSimBodiesFromID(byte id)
{ {
var ret = new FasterList<SimBody>(4); var ret = new FasterList<SimBody>(4);

View file

@ -19,10 +19,9 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public float MaxForce public float MaxForce
{ {
get => BlockEngine.GetBlockInfo(this, (DampedSpringReadOnlyStruct dsrs) => dsrs.springFrequency); get => BlockEngine.GetBlockInfo<DampedSpringReadOnlyStruct>(this).springFrequency;
set => BlockEngine.SetBlockInfo(this, set => BlockEngine.GetBlockInfo<DampedSpringReadOnlyStruct>(this).springFrequency = value;
(ref DampedSpringReadOnlyStruct dsrs, float val) => dsrs.springFrequency = val, value);
} }
/// <summary> /// <summary>
@ -39,10 +38,9 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public float Damping public float Damping
{ {
get => BlockEngine.GetBlockInfo(this, (DampedSpringReadOnlyStruct ljf) => ljf.springDamping); get => BlockEngine.GetBlockInfo<DampedSpringReadOnlyStruct>(this).springDamping;
set => BlockEngine.SetBlockInfo(this, set => BlockEngine.GetBlockInfo<DampedSpringReadOnlyStruct>(this).springDamping = value;
(ref DampedSpringReadOnlyStruct ljf, float val) => ljf.springDamping = val, value);
} }
/// <summary> /// <summary>
@ -50,10 +48,9 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public float MaxExtension public float MaxExtension
{ {
get => BlockEngine.GetBlockInfo(this, (DampedSpringReadOnlyStruct ljf) => ljf.maxExtent); get => BlockEngine.GetBlockInfo<DampedSpringReadOnlyStruct>(this).maxExtent;
set => BlockEngine.SetBlockInfo(this, set => BlockEngine.GetBlockInfo<DampedSpringReadOnlyStruct>(this).maxExtent = value;
(ref DampedSpringReadOnlyStruct ljf, float val) => ljf.maxExtent = val, value);
} }
} }
} }

View file

@ -28,12 +28,12 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (MotorReadOnlyStruct st) => st.maxVelocity); return BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(this).maxVelocity;
} }
set set
{ {
BlockEngine.SetBlockInfo(this, (ref MotorReadOnlyStruct st, float val) => st.maxVelocity = val, value); BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(this).maxVelocity = value;
} }
} }
@ -44,12 +44,12 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (MotorReadOnlyStruct st) => st.maxForce); return BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(this).maxForce;
} }
set set
{ {
BlockEngine.SetBlockInfo(this, (ref MotorReadOnlyStruct st, float val) => st.maxForce = val, value); BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(this).maxForce = value;
} }
} }
@ -60,12 +60,12 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (MotorReadOnlyStruct st) => st.reverse); return BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(this).reverse;
} }
set set
{ {
BlockEngine.SetBlockInfo(this, (ref MotorReadOnlyStruct st, bool val) => st.reverse = val, value); BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(this).reverse = value;
} }
} }
} }

View file

@ -34,21 +34,12 @@ namespace TechbloxModdingAPI.Blocks
// implementations for Movement static class // 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<PositionEntityStruct>(blockID)) ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntityOrDefault<PositionEntityStruct>(block);
{ ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntityOrDefault<GridRotationStruct>(block);
if (data.Group == null) return float3.zero; ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntityOrDefault<LocalTransformEntityStruct>(block);
var init = new EntityInitializer(blockID, data.Group, data.Reference); ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntityOrDefault<UECSPhysicsEntityStruct>(block);
init.GetOrCreate<PositionEntityStruct>().position = vector;
init.GetOrCreate<GridRotationStruct>().position = vector;
init.GetOrCreate<LocalTransformEntityStruct>().position = vector;
return vector;
}
ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntity<PositionEntityStruct>(blockID);
ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntity<GridRotationStruct>(blockID);
ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntity<LocalTransformEntityStruct>(blockID);
ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntity<UECSPhysicsEntityStruct>(blockID);
// main (persistent) position // main (persistent) position
posStruct.position = vector; posStruct.position = vector;
// placement grid position // placement grid position
@ -56,24 +47,21 @@ namespace TechbloxModdingAPI.Blocks
// rendered position // rendered position
transStruct.position = vector; transStruct.position = vector;
// collision position // collision position
FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Translation if (phyStruct.ID != EGID.Empty)
{ { //It exists
Value = posStruct.position FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Translation
}); {
entitiesDB.QueryEntity<GridConnectionsEntityStruct>(blockID).isProcessed = false; Value = posStruct.position
});
}
entitiesDB.QueryEntityOrDefault<GridConnectionsEntityStruct>(block).isProcessed = false;
return posStruct.position; return posStruct.position;
} }
internal float3 GetPosition(EGID blockID, BlockEngine.BlockInitData data) internal float3 GetPosition(Block block)
{ {
if (!entitiesDB.Exists<PositionEntityStruct>(blockID)) return entitiesDB.QueryEntityOrDefault<PositionEntityStruct>(block).position;
{
if (data.Group == null) return float3.zero;
var init = new EntityInitializer(blockID, data.Group, data.Reference);
return init.Has<PositionEntityStruct>() ? init.Get<PositionEntityStruct>().position : float3.zero;
}
ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntity<PositionEntityStruct>(blockID);
return posStruct.position;
} }
} }
} }

View file

@ -28,13 +28,12 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (MusicBlockDataEntityStruct st) => st.trackIndx); return BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this).trackIndx;
} }
set set
{ {
BlockEngine.SetBlockInfo(this, BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this).trackIndx = value;
(ref MusicBlockDataEntityStruct msdes, byte val) => msdes.trackIndx = val, value);
} }
} }
@ -42,24 +41,22 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, var msdes = BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this);
(MusicBlockDataEntityStruct msdes) => msdes.fmod2DEventPaths.Get<Guid>(msdes.trackIndx)); return msdes.fmod2DEventPaths.Get<Guid>(msdes.trackIndx);
} }
set set
{ {
BlockEngine.SetBlockInfo(this, (ref MusicBlockDataEntityStruct msdes, Guid val) => ref var msdes = ref BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this);
for (byte i = 0; i < msdes.fmod2DEventPaths.Count<Guid>(); i++)
{ {
for (byte i = 0; i < msdes.fmod2DEventPaths.Count<Guid>(); i++) Guid track = msdes.fmod2DEventPaths.Get<Guid>(i);
if (track == value)
{ {
Guid track = msdes.fmod2DEventPaths.Get<Guid>(i); msdes.trackIndx = i;
if (track == val) break;
{
msdes.trackIndx = i;
break;
}
} }
}, value); }
} }
} }
@ -67,15 +64,13 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (MusicBlockDataEntityStruct msdes) => var msdes = BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this);
Guid[] tracks = new Guid[msdes.fmod2DEventPaths.Count<Guid>()];
for (byte i = 0; i < tracks.Length; i++)
{ {
Guid[] tracks = new Guid[msdes.fmod2DEventPaths.Count<Guid>()]; tracks[i] = msdes.fmod2DEventPaths.Get<Guid>(i);
for (byte i = 0; i < tracks.Length; i++) }
{ return tracks;
tracks[i] = msdes.fmod2DEventPaths.Get<Guid>(i);
}
return tracks;
});
} }
} }
@ -83,13 +78,12 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (MusicBlockDataEntityStruct msdes) => msdes.tweakableVolume); return BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this).tweakableVolume;
} }
set set
{ {
BlockEngine.SetBlockInfo(this, BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this).tweakableVolume = value;
(ref MusicBlockDataEntityStruct msdes, float val) => msdes.tweakableVolume = val, value);
} }
} }
@ -98,14 +92,12 @@ namespace TechbloxModdingAPI.Blocks
get get
{ {
//Assert.Log("Block exists: " + Exists); //Assert.Log("Block exists: " + Exists);
return BlockEngine.GetBlockInfo(this, return (ChannelType) BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this).channelType;
(MusicBlockDataEntityStruct msdes) => (ChannelType) msdes.channelType);
} }
set set
{ {
BlockEngine.SetBlockInfo(this, BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this).channelType = (byte) value;
(ref MusicBlockDataEntityStruct msdes, ChannelType val) => msdes.channelType = (byte) val, value);
} }
} }
@ -113,33 +105,31 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, return BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this).isPlaying;
(MusicBlockDataEntityStruct msdes) => msdes.isPlaying);
} }
set set
{ {
BlockEngine.SetBlockInfo(this, (ref MusicBlockDataEntityStruct msdes, bool val) => ref var msdes = ref BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this);
if (msdes.isPlaying == value) return;
if (value)
{ {
if (msdes.isPlaying == val) return; // start playing
if (val) EventInstance inst = RuntimeManager.CreateInstance(msdes.fmod2DEventPaths.Get<Guid>(msdes.trackIndx));
{ inst.setVolume(msdes.tweakableVolume / 100f);
// start playing inst.start();
EventInstance inst = RuntimeManager.CreateInstance(msdes.fmod2DEventPaths.Get<Guid>(msdes.trackIndx)); msdes.eventHandle = inst.handle;
inst.setVolume(msdes.tweakableVolume / 100f); }
inst.start(); else
msdes.eventHandle = inst.handle; {
} // stop playing
else EventInstance inst = default(EventInstance);
{ inst.handle = msdes.eventHandle;
// stop playing inst.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
EventInstance inst = default(EventInstance); inst.release();
inst.handle = msdes.eventHandle; }
inst.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
inst.release(); msdes.isPlaying = value;
}
msdes.isPlaying = val;
}, value);
} }
} }
} }

View file

@ -16,14 +16,11 @@ namespace TechbloxModdingAPI.Blocks
public char Identifier public char Identifier
{ {
get => (char) BlockEngine.GetBlockInfo(this, (ObjectIdEntityStruct st) => st.objectId + 'A'); get => (char) (BlockEngine.GetBlockInfo<ObjectIdEntityStruct>(this).objectId + 'A');
set set
{ {
BlockEngine.SetBlockInfo(this, (ref ObjectIdEntityStruct st, char val) => BlockEngine.GetBlockInfo<ObjectIdEntityStruct>(this).objectId = (byte) (value - 'A');
{ Label = value + ""; //The label isn't updated automatically
st.objectId = (byte) (val - 'A');
Label = val + ""; //The label isn't updated automatically
}, value);
} }
} }
@ -32,7 +29,7 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public byte SimID public byte SimID
{ {
get => BlockEngine.GetBlockInfo(this, (ObjectIdEntityStruct st) => st.simObjectId); get => BlockEngine.GetBlockInfo<ObjectIdEntityStruct>(this).simObjectId;
} }
/// <summary> /// <summary>

View file

@ -26,12 +26,11 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public float MaximumExtension public float MaximumExtension
{ {
get => BlockEngine.GetBlockInfo(this, (PistonReadOnlyStruct st) => st.maxDeviation); get => BlockEngine.GetBlockInfo<PistonReadOnlyStruct>(this).maxDeviation;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref PistonReadOnlyStruct st, float val) => st.maxDeviation = val, BlockEngine.GetBlockInfo<PistonReadOnlyStruct>(this).maxDeviation = value;
value);
} }
} }
@ -40,11 +39,11 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public float MaximumForce public float MaximumForce
{ {
get => BlockEngine.GetBlockInfo(this, (PistonReadOnlyStruct st) => st.pistonVelocity); get => BlockEngine.GetBlockInfo<PistonReadOnlyStruct>(this).pistonVelocity;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref PistonReadOnlyStruct st, float val) => st.pistonVelocity = val, value); BlockEngine.GetBlockInfo<PistonReadOnlyStruct>(this).pistonVelocity = value;
} }
} }
} }

View file

@ -34,55 +34,38 @@ namespace TechbloxModdingAPI.Blocks
// implementations for Rotation static class // 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<RotationEntityStruct>(blockID)) ref RotationEntityStruct rotStruct = ref this.entitiesDB.QueryEntityOrDefault<RotationEntityStruct>(block);
{ ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntityOrDefault<GridRotationStruct>(block);
if (data.Group == null) return float3.zero; ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntityOrDefault<LocalTransformEntityStruct>(block);
var init = new EntityInitializer(blockID, data.Group, data.Reference); ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntityOrDefault<UECSPhysicsEntityStruct>(block);
init.GetOrCreate<RotationEntityStruct>().rotation = Quaternion.Euler(vector); // main (persistent) rotation
init.GetOrCreate<GridRotationStruct>().rotation = Quaternion.Euler(vector);
init.GetOrCreate<LocalTransformEntityStruct>().rotation = Quaternion.Euler(vector);
return vector;
}
ref RotationEntityStruct rotStruct = ref this.entitiesDB.QueryEntity<RotationEntityStruct>(blockID);
ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntity<GridRotationStruct>(blockID);
ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntity<LocalTransformEntityStruct>(blockID);
ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntity<UECSPhysicsEntityStruct>(blockID);
// main (persistent) position
Quaternion newRotation = rotStruct.rotation; Quaternion newRotation = rotStruct.rotation;
newRotation.eulerAngles = vector; newRotation.eulerAngles = vector;
rotStruct.rotation = newRotation; rotStruct.rotation = newRotation;
// placement grid rotation // placement grid rotation
Quaternion newGridRotation = gridStruct.rotation; gridStruct.rotation = newRotation;
newGridRotation.eulerAngles = vector; // rendered rotation
gridStruct.rotation = newGridRotation; transStruct.rotation = newRotation;
// rendered position // collision rotation
Quaternion newTransRotation = rotStruct.rotation; if (phyStruct.ID != EGID.Empty)
newTransRotation.eulerAngles = vector; { //It exists
transStruct.rotation = newTransRotation; FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity,
// collision position new Unity.Transforms.Rotation
FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Unity.Transforms.Rotation {
{ Value = rotStruct.rotation
Value = rotStruct.rotation });
}); }
entitiesDB.QueryEntity<GridConnectionsEntityStruct>(blockID).isProcessed = false;
entitiesDB.QueryEntityOrDefault<GridConnectionsEntityStruct>(block).isProcessed = false;
return ((Quaternion)rotStruct.rotation).eulerAngles; return ((Quaternion)rotStruct.rotation).eulerAngles;
} }
internal float3 GetRotation(EGID blockID, BlockEngine.BlockInitData data) internal float3 GetRotation(Block block)
{ {
if (!entitiesDB.Exists<RotationEntityStruct>(blockID)) ref RotationEntityStruct rotStruct = ref entitiesDB.QueryEntityOrDefault<RotationEntityStruct>(block);
{
if (data.Group == null) return float3.zero;
var init = new EntityInitializer(blockID, data.Group, data.Reference);
return init.Has<RotationEntityStruct>()
? (float3) ((Quaternion) init.Get<RotationEntityStruct>().rotation).eulerAngles
: float3.zero;
}
ref RotationEntityStruct rotStruct = ref entitiesDB.QueryEntity<RotationEntityStruct>(blockID);
return ((Quaternion) rotStruct.rotation).eulerAngles; return ((Quaternion) rotStruct.rotation).eulerAngles;
} }
} }

View file

@ -26,11 +26,11 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public float MinimumAngle public float MinimumAngle
{ {
get => BlockEngine.GetBlockInfo(this, (ServoReadOnlyStruct st) => st.minDeviation); get => BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(this).minDeviation;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref ServoReadOnlyStruct st, float val) => st.minDeviation = val, value); BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(this).minDeviation = value;
} }
} }
@ -39,11 +39,11 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public float MaximumAngle public float MaximumAngle
{ {
get => BlockEngine.GetBlockInfo(this, (ServoReadOnlyStruct st) => st.maxDeviation); get => BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(this).maxDeviation;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref ServoReadOnlyStruct st, float val) => st.maxDeviation = val, value); BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(this).maxDeviation = value;
} }
} }
@ -52,11 +52,11 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public float MaximumForce public float MaximumForce
{ {
get => BlockEngine.GetBlockInfo(this, (ServoReadOnlyStruct st) => st.servoVelocity); get => BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(this).servoVelocity;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref ServoReadOnlyStruct st, float val) => st.servoVelocity = val, value); BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(this).servoVelocity = value;
} }
} }
@ -65,11 +65,11 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public bool Reverse public bool Reverse
{ {
get => BlockEngine.GetBlockInfo(this, (ServoReadOnlyStruct st) => st.reverse); get => BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(this).reverse;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref ServoReadOnlyStruct st, bool val) => st.reverse = val, value); BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(this).reverse = value;
} }
} }
} }

View file

@ -22,13 +22,12 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.tweakableVolume); return BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).tweakableVolume;
} }
set set
{ {
BlockEngine.SetBlockInfo(this, BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).tweakableVolume = value;
(ref SoundSfxBlockDataEntityStruct obj, float val) => obj.tweakableVolume = val, value);
} }
} }
@ -36,13 +35,12 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.tweakablePitch); return BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).tweakablePitch;
} }
set set
{ {
BlockEngine.SetBlockInfo(this, BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).tweakablePitch = value;
(ref SoundSfxBlockDataEntityStruct obj, float val) => obj.tweakablePitch = val, value);
} }
} }
@ -50,13 +48,12 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.is3D); return BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).is3D;
} }
set set
{ {
BlockEngine.SetBlockInfo(this, BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).is3D = value;
(ref SoundSfxBlockDataEntityStruct obj, bool val) => obj.is3D = val, value);
} }
} }
@ -64,13 +61,12 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => (ChannelType)obj.channelType); return (ChannelType) BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).channelType;
} }
set set
{ {
BlockEngine.SetBlockInfo(this, BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).channelType = (byte) value;
(ref SoundSfxBlockDataEntityStruct obj, ChannelType val) => obj.tweakableVolume = (byte) val, value);
} }
} }
@ -78,13 +74,12 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.soundEffectIndex); return BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).soundEffectIndex;
} }
set set
{ {
BlockEngine.SetBlockInfo(this, BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).soundEffectIndex = value;
(ref SoundSfxBlockDataEntityStruct obj, byte val) => obj.soundEffectIndex = val, value);
} }
} }
@ -93,35 +88,36 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, var obj = BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this);
(SoundSfxBlockDataEntityStruct obj) => obj.is3D ? obj.fmod3DEventPaths.Get<Guid>(obj.soundEffectIndex) : obj.fmod2DEventPaths.Get<Guid>(obj.soundEffectIndex)); return obj.is3D
? obj.fmod3DEventPaths.Get<Guid>(obj.soundEffectIndex)
: obj.fmod2DEventPaths.Get<Guid>(obj.soundEffectIndex);
} }
set set
{ {
BlockEngine.SetBlockInfo(this, (ref SoundSfxBlockDataEntityStruct obj, Guid val) => var obj = BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this);
for (byte i = 0; i < obj.fmod2DEventPaths.Count<Guid>(); i++)
{ {
for (byte i = 0; i < obj.fmod2DEventPaths.Count<Guid>(); i++) Guid track = obj.fmod2DEventPaths.Get<Guid>(i);
if (track == value)
{ {
Guid track = obj.fmod2DEventPaths.Get<Guid>(i); obj.soundEffectIndex = i;
if (track == val) obj.is3D = false;
{ return;
obj.soundEffectIndex = i;
obj.is3D = false;
return;
}
} }
for (byte i = 0; i < obj.fmod3DEventPaths.Count<Guid>(); i++) }
for (byte i = 0; i < obj.fmod3DEventPaths.Count<Guid>(); i++)
{
Guid track = obj.fmod3DEventPaths.Get<Guid>(i);
if (track == value)
{ {
Guid track = obj.fmod3DEventPaths.Get<Guid>(i); obj.soundEffectIndex = i;
if (track == val) obj.is3D = true;
{ return;
obj.soundEffectIndex = i;
obj.is3D = true;
return;
}
} }
}, value); }
} }
} }
@ -130,15 +126,14 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => var obj = BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this);
Guid[] tracks = new Guid[obj.fmod2DEventPaths.Count<Guid>()];
for (byte i = 0; i < tracks.Length; i++)
{ {
Guid[] tracks = new Guid[obj.fmod2DEventPaths.Count<Guid>()]; tracks[i] = obj.fmod2DEventPaths.Get<Guid>(i);
for (byte i = 0; i < tracks.Length; i++) }
{
tracks[i] = obj.fmod2DEventPaths.Get<Guid>(i); return tracks;
}
return tracks;
});
} }
} }
@ -146,15 +141,14 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => var obj = BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this);
Guid[] tracks = new Guid[obj.fmod3DEventPaths.Count<Guid>()];
for (byte i = 0; i < tracks.Length; i++)
{ {
Guid[] tracks = new Guid[obj.fmod3DEventPaths.Count<Guid>()]; tracks[i] = obj.fmod2DEventPaths.Get<Guid>(i);
for (byte i = 0; i < tracks.Length; i++) }
{
tracks[i] = obj.fmod2DEventPaths.Get<Guid>(i); return tracks;
}
return tracks;
});
} }
} }
@ -162,13 +156,12 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.isLoopedBlock); return BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).isLoopedBlock;
} }
set set
{ {
BlockEngine.SetBlockInfo(this, BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).isLoopedBlock = value;
(ref SoundSfxBlockDataEntityStruct obj, bool val) => obj.isLoopedBlock = val, value);
} }
} }
@ -176,33 +169,33 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo(this, return BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).isPlaying;
(SoundSfxBlockDataEntityStruct obj) => obj.isPlaying);
} }
set set
{ {
BlockEngine.SetBlockInfo(this, (ref SoundSfxBlockDataEntityStruct obj, bool val) => var obj = BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this);
if (obj.isPlaying == value) return;
if (value)
{ {
if (obj.isPlaying == val) return; // start playing
if (val) EventInstance inst = RuntimeManager.CreateInstance(obj.is3D
{ ? obj.fmod3DEventPaths.Get<Guid>(obj.soundEffectIndex)
// start playing : obj.fmod2DEventPaths.Get<Guid>(obj.soundEffectIndex));
EventInstance inst = RuntimeManager.CreateInstance(obj.is3D ? obj.fmod3DEventPaths.Get<Guid>(obj.soundEffectIndex) : obj.fmod2DEventPaths.Get<Guid>(obj.soundEffectIndex)); inst.setVolume(obj.tweakableVolume / 100f);
inst.setVolume(obj.tweakableVolume / 100f); inst.start();
inst.start(); obj.eventHandle = inst.handle;
obj.eventHandle = inst.handle; }
} else
else {
{ // stop playing
// stop playing EventInstance inst = default(EventInstance);
EventInstance inst = default(EventInstance); inst.handle = obj.eventHandle;
inst.handle = obj.eventHandle; inst.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
inst.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); inst.release();
inst.release(); }
}
obj.isPlaying = val; obj.isPlaying = value;
}, value);
} }
} }
} }

View file

@ -3,6 +3,7 @@ using Svelto.ECS;
using Svelto.DataStructures; using Svelto.DataStructures;
using Gamecraft.Wires; using Gamecraft.Wires;
using TechbloxModdingAPI.Engines; using TechbloxModdingAPI.Engines;
using TechbloxModdingAPI.Utility;
namespace TechbloxModdingAPI.Blocks namespace TechbloxModdingAPI.Blocks
{ {
@ -87,8 +88,8 @@ namespace TechbloxModdingAPI.Blocks
public ref PortEntityStruct GetPortByOffset(Block block, byte portNumber, bool input) public ref PortEntityStruct GetPortByOffset(Block block, byte portNumber, bool input)
{ {
BlockPortsStruct bps = GetFromDbOrInitData<BlockPortsStruct>(block, block.Id, out bool exists); var bps = entitiesDB.QueryEntityOptional<BlockPortsStruct>(block);
if (!exists) if (!bps)
{ {
throw new BlockException("Block does not exist"); throw new BlockException("Block does not exist");
} }
@ -208,8 +209,9 @@ namespace TechbloxModdingAPI.Blocks
public EGID MatchBlockInputToPort(Block block, byte portUsage, out bool exists) public EGID MatchBlockInputToPort(Block block, byte portUsage, out bool exists)
{ {
BlockPortsStruct ports = GetFromDbOrInitData<BlockPortsStruct>(block, block.Id, out exists); var ports = entitiesDB.QueryEntityOptional<BlockPortsStruct>(block);
return new EGID(ports.firstInputID + portUsage, NamedExclusiveGroup<InputPortsGroup>.Group); exists = ports;
return new EGID(ports.Get().firstInputID + portUsage, NamedExclusiveGroup<InputPortsGroup>.Group);
} }
public EGID MatchBlockInputToPort(EGID block, byte portUsage, out bool exists) 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) public EGID MatchBlockOutputToPort(Block block, byte portUsage, out bool exists)
{ {
BlockPortsStruct ports = GetFromDbOrInitData<BlockPortsStruct>(block, block.Id, out exists); var ports = entitiesDB.QueryEntityOptional<BlockPortsStruct>(block);
return new EGID(ports.firstOutputID + portUsage, NamedExclusiveGroup<OutputPortsGroup>.Group); exists = ports;
return new EGID(ports.Get().firstOutputID + portUsage, NamedExclusiveGroup<OutputPortsGroup>.Group);
} }
public EGID MatchBlockOutputToPort(EGID block, byte portUsage, out bool exists) public EGID MatchBlockOutputToPort(EGID block, byte portUsage, out bool exists)
@ -385,29 +388,6 @@ namespace TechbloxModdingAPI.Blocks
return results.ToArray(); return results.ToArray();
} }
private ref T GetFromDbOrInitData<T>(Block block, EGID id, out bool exists) where T : unmanaged, IEntityComponent
{
T[] defRef = new T[1];
if (entitiesDB.Exists<T>(id))
{
exists = true;
return ref entitiesDB.QueryEntity<T>(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<T>())
{
exists = true;
return ref initializer.Get<T>();
}
exists = false;
return ref defRef[0];
}
private EntityCollection<ChannelDataStruct> GetSignalStruct(uint signalID, out uint index, bool input = true) private EntityCollection<ChannelDataStruct> GetSignalStruct(uint signalID, out uint index, bool input = true)
{ {
ExclusiveGroup group = input ExclusiveGroup group = input

View file

@ -67,7 +67,7 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public uint InputCount public uint InputCount
{ {
get => BlockEngine.GetBlockInfo(this, (BlockPortsStruct st) => st.inputCount); get => BlockEngine.GetBlockInfo<BlockPortsStruct>(this).inputCount;
} }
/// <summary> /// <summary>
@ -75,7 +75,7 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public uint OutputCount public uint OutputCount
{ {
get => BlockEngine.GetBlockInfo(this, (BlockPortsStruct st) => st.outputCount); get => BlockEngine.GetBlockInfo<BlockPortsStruct>(this).outputCount;
} }
/// <summary> /// <summary>
@ -109,7 +109,6 @@ namespace TechbloxModdingAPI.Blocks
/// <returns>The localized port name.</returns> /// <returns>The localized port name.</returns>
public string PortName(byte port, bool input) public string PortName(byte port, bool input)
{ {
BlockPortsStruct bps = BlockEngine.GetBlockInfo(this, (BlockPortsStruct a) => a);
PortEntityStruct pes = SignalEngine.GetPortByOffset(this, port, input); PortEntityStruct pes = SignalEngine.GetPortByOffset(this, port, input);
return pes.portNameLocalised; return pes.portNameLocalised;
} }

View file

@ -28,11 +28,11 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public uint Lives public uint Lives
{ {
get => BlockEngine.GetBlockInfo(this, (SpawnPointStatsEntityStruct st) => st.lives); get => BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(this).lives;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref SpawnPointStatsEntityStruct st, uint val) => st.lives = val, value); BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(this).lives = value;
} }
} }
@ -41,11 +41,11 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public bool Damageable public bool Damageable
{ {
get => BlockEngine.GetBlockInfo(this, (SpawnPointStatsEntityStruct st) => st.canTakeDamage); get => BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(this).canTakeDamage;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref SpawnPointStatsEntityStruct st, bool val) => st.canTakeDamage = val, value); BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(this).canTakeDamage = value;
} }
} }
@ -54,11 +54,11 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public bool GameOverEnabled public bool GameOverEnabled
{ {
get => BlockEngine.GetBlockInfo(this, (SpawnPointStatsEntityStruct st) => st.gameOverScreen); get => BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(this).gameOverScreen;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref SpawnPointStatsEntityStruct st, bool val) => st.gameOverScreen = val, value); BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(this).gameOverScreen = value;
} }
} }
@ -67,11 +67,11 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public byte Team public byte Team
{ {
get => BlockEngine.GetBlockInfo(this, (SpawnPointIdsEntityStruct st) => st.teamId); get => BlockEngine.GetBlockInfo<SpawnPointIdsEntityStruct>(this).teamId;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref SpawnPointIdsEntityStruct st, byte val) => st.teamId = val, value); BlockEngine.GetBlockInfo<SpawnPointIdsEntityStruct>(this).teamId = value;
} }
} }
} }

View file

@ -26,17 +26,15 @@ namespace TechbloxModdingAPI.Blocks
/// The text block's current text. /// The text block's current text.
/// </summary> /// </summary>
public string Text public string Text
{ {
get => BlockEngine.GetBlockInfo(this, (TextBlockDataStruct st) => st.textCurrent); get => BlockEngine.GetBlockInfo<TextBlockDataStruct>(this).textCurrent;
set set
{ {
if (value == null) value = ""; if (value == null) value = "";
BlockEngine.SetBlockInfo(this, (ref TextBlockDataStruct tbds, string val) => var tbds = BlockEngine.GetBlockInfo<TextBlockDataStruct>(this);
{ tbds.textCurrent.Set(value);
tbds.textCurrent.Set(val); tbds.textStored.Set(value, true);
tbds.textStored.Set(val, true);
}, value);
} }
} }
@ -45,13 +43,12 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public string TextBlockId public string TextBlockId
{ {
get => BlockEngine.GetBlockInfo(this, (TextBlockDataStruct st) => st.textBlockID); get => BlockEngine.GetBlockInfo<TextBlockDataStruct>(this).textBlockID;
set set
{ {
if (value == null) value = ""; if (value == null) value = "";
BlockEngine.SetBlockInfo(this, (ref TextBlockDataStruct tbds, string val) => BlockEngine.GetBlockInfo<TextBlockDataStruct>(this).textBlockID.Set(value);
tbds.textBlockID.Set(val), value);
} }
} }
} }

View file

@ -28,12 +28,11 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public float Start public float Start
{ {
get => BlockEngine.GetBlockInfo(this, (TimerBlockDataStruct st) => st.startTime); get => BlockEngine.GetBlockInfo<TimerBlockDataStruct>(this).startTime;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref TimerBlockDataStruct tbds, float val) => tbds.startTime = val, BlockEngine.GetBlockInfo<TimerBlockDataStruct>(this).startTime = value;
value);
} }
} }
@ -42,12 +41,11 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public float End public float End
{ {
get => BlockEngine.GetBlockInfo(this, (TimerBlockDataStruct st) => st.endTime); get => BlockEngine.GetBlockInfo<TimerBlockDataStruct>(this).endTime;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref TimerBlockDataStruct tbds, float val) => tbds.endTime = val, BlockEngine.GetBlockInfo<TimerBlockDataStruct>(this).endTime = value;
value);
} }
} }
@ -56,12 +54,11 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public bool DisplayMilliseconds public bool DisplayMilliseconds
{ {
get => BlockEngine.GetBlockInfo(this, (TimerBlockDataStruct st) => st.outputFormatHasMS); get => BlockEngine.GetBlockInfo<TimerBlockDataStruct>(this).outputFormatHasMS;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref TimerBlockDataStruct tbds, bool val) => tbds.outputFormatHasMS = val, BlockEngine.GetBlockInfo<TimerBlockDataStruct>(this).outputFormatHasMS = value;
value);
} }
} }
@ -70,12 +67,11 @@ namespace TechbloxModdingAPI.Blocks
/// </summary> /// </summary>
public int CurrentTime public int CurrentTime
{ {
get => BlockEngine.GetBlockInfo(this, (TimerBlockLabelCacheEntityStruct st) => st.timeLastRenderFrameMS); get => BlockEngine.GetBlockInfo<TimerBlockLabelCacheEntityStruct>(this).timeLastRenderFrameMS;
set set
{ {
BlockEngine.SetBlockInfo(this, (ref TimerBlockLabelCacheEntityStruct tbds, int val) => tbds.timeLastRenderFrameMS = val, BlockEngine.GetBlockInfo<TimerBlockLabelCacheEntityStruct>(this).timeLastRenderFrameMS = value;
value);
} }
} }
} }

View file

@ -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. /// 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. /// Only exists if a cluster destruction manager is present. Static blocks like grass and dirt aren't part of a cluster.
/// </summary> /// </summary>
public class Cluster public class Cluster : EcsObjectBase
{ {
public EGID Id { get; } public override EGID Id { get; }
public Cluster(EGID id) public Cluster(EGID id)
{ {
@ -23,20 +23,20 @@ namespace TechbloxModdingAPI
public float InitialHealth public float InitialHealth
{ {
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).initialHealth; get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).initialHealth;
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).initialHealth = value; set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).initialHealth = value;
} }
public float CurrentHealth public float CurrentHealth
{ {
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).currentHealth; get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).currentHealth;
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).currentHealth = value; set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).currentHealth = value;
} }
public float HealthMultiplier public float HealthMultiplier
{ {
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier; get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).healthMultiplier;
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier = value; set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).healthMultiplier = value;
} }
/// <summary> /// <summary>

View file

@ -1,33 +1,43 @@
using System; using System;
using System.Linq.Expressions; using System.Linq.Expressions;
using Svelto.DataStructures; using Svelto.DataStructures;
using Svelto.ECS; using Svelto.ECS;
using Svelto.ECS.Internal; 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;
/// <summary> /// <summary>
/// Holds information needed to construct a component initializer /// Holds information needed to construct a component initializer
/// </summary> /// </summary>
internal struct BlockInitData protected internal struct EcsInitData
{ {
public FasterDictionary<RefWrapperType, ITypeSafeDictionary> Group; private FasterDictionary<RefWrapperType, ITypeSafeDictionary> group;
public EntityReference Reference; 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<RefWrapperType, ITypeSafeDictionary> GetInitGroup( private delegate FasterDictionary<RefWrapperType, ITypeSafeDictionary> GetInitGroupFunc(
EntityInitializer initializer); EntityInitializer initializer);
/// <summary> /// <summary>
/// Accesses the group field of the initializer /// Accesses the group field of the initializer
/// </summary> /// </summary>
internal GetInitGroup InitGroup = CreateAccessor<GetInitGroup>("_group"); private static GetInitGroupFunc GetInitGroup = CreateAccessor<GetInitGroupFunc>("_group");
//https://stackoverflow.com/questions/55878525/unit-testing-ref-structs-with-private-fields-via-reflection //https://stackoverflow.com/questions/55878525/unit-testing-ref-structs-with-private-fields-via-reflection
internal static TDelegate CreateAccessor<TDelegate>(string memberName) where TDelegate : Delegate private static TDelegate CreateAccessor<TDelegate>(string memberName) where TDelegate : Delegate
{ {
var invokeMethod = typeof(TDelegate).GetMethod("Invoke"); var invokeMethod = typeof(TDelegate).GetMethod("Invoke");
if (invokeMethod == null) if (invokeMethod == null)

View file

@ -1,4 +1,5 @@
using RobocraftX.Physics; using RobocraftX.Physics;
using Svelto.ECS;
using Svelto.ECS.EntityStructs; using Svelto.ECS.EntityStructs;
using Techblox.FlyCam; using Techblox.FlyCam;
using TechbloxModdingAPI.Players; using TechbloxModdingAPI.Players;
@ -8,13 +9,13 @@ using UnityEngine;
namespace TechbloxModdingAPI namespace TechbloxModdingAPI
{ {
public class FlyCam public class FlyCam : EcsObjectBase
{ {
private static FlyCamEngine Engine = new FlyCamEngine(); private static FlyCamEngine Engine = new FlyCamEngine();
public uint Id { get; } public override EGID Id { get; }
public FlyCam(uint id) => Id = id; public FlyCam(uint id) => Id = new EGID(id, Techblox.FlyCam.FlyCam.Group);
/// <summary> /// <summary>
/// The local player's camera. /// The local player's camera.
@ -26,11 +27,11 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public float3 Position public float3 Position
{ {
get => Engine.GetComponent<PositionEntityStruct>(Id).Get().position; get => Engine.GetComponent<PositionEntityStruct>(this).position;
set set
{ {
Engine.GetComponent<PositionEntityStruct>(Id).Get().position = value; Engine.GetComponent<PositionEntityStruct>(this).position = value;
Engine.GetComponent<RigidBodyEntityStruct>(Id).Get().position = value; Engine.GetComponent<RigidBodyEntityStruct>(this).position = value;
} }
} }
@ -39,11 +40,11 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public float3 Rotation public float3 Rotation
{ {
get => ((Quaternion) Engine.GetComponent<RotationEntityStruct>(Id).Get().rotation).eulerAngles; get => ((Quaternion) Engine.GetComponent<RotationEntityStruct>(this).rotation).eulerAngles;
set set
{ {
Engine.GetComponent<RotationEntityStruct>(Id).Get().rotation = Quaternion.Euler(value); Engine.GetComponent<RotationEntityStruct>(this).rotation = Quaternion.Euler(value);
Engine.GetComponent<RigidBodyEntityStruct>(Id).Get().rotation = Quaternion.Euler(value); Engine.GetComponent<RigidBodyEntityStruct>(this).rotation = Quaternion.Euler(value);
} }
} }
@ -52,8 +53,8 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public float3 MovementDirection public float3 MovementDirection
{ {
get => Engine.GetComponent<FlyCamMovementComponent>(Id).Get().movementDirection; get => Engine.GetComponent<FlyCamMovementComponent>(this).movementDirection;
set => Engine.GetComponent<FlyCamMovementComponent>(Id).Get().movementDirection = value; set => Engine.GetComponent<FlyCamMovementComponent>(this).movementDirection = value;
} }
/// <summary> /// <summary>
@ -61,8 +62,8 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public bool Sprinting public bool Sprinting
{ {
get => Engine.GetComponent<FlyCamMovementComponent>(Id).Get().sprinting; get => Engine.GetComponent<FlyCamMovementComponent>(this).sprinting;
set => Engine.GetComponent<FlyCamMovementComponent>(Id).Get().sprinting = value; set => Engine.GetComponent<FlyCamMovementComponent>(this).sprinting = value;
} }
/// <summary> /// <summary>
@ -70,8 +71,8 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public float Speed public float Speed
{ {
get => Engine.GetComponent<FlyCamMovementSettingsComponent>(Id).Get().speed; get => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).speed;
set => Engine.GetComponent<FlyCamMovementSettingsComponent>(Id).Get().speed = value; set => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).speed = value;
} }
/// <summary> /// <summary>
@ -79,8 +80,8 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public float SpeedSprintMultiplier public float SpeedSprintMultiplier
{ {
get => Engine.GetComponent<FlyCamMovementSettingsComponent>(Id).Get().speedSprintMultiplier; get => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).speedSprintMultiplier;
set => Engine.GetComponent<FlyCamMovementSettingsComponent>(Id).Get().speedSprintMultiplier = value; set => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).speedSprintMultiplier = value;
} }
/// <summary> /// <summary>
@ -88,8 +89,8 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public float Acceleration public float Acceleration
{ {
get => Engine.GetComponent<FlyCamMovementSettingsComponent>(Id).Get().acceleration; get => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).acceleration;
set => Engine.GetComponent<FlyCamMovementSettingsComponent>(Id).Get().acceleration = value; set => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).acceleration = value;
} }
/// <summary> /// <summary>
@ -97,8 +98,8 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public float3 Velocity public float3 Velocity
{ {
get => Engine.GetComponent<RigidBodyEntityStruct>(Id).Get().velocity; get => Engine.GetComponent<RigidBodyEntityStruct>(this).velocity;
set => Engine.GetComponent<RigidBodyEntityStruct>(Id).Get().velocity = value; set => Engine.GetComponent<RigidBodyEntityStruct>(this).velocity = value;
} }
/// <summary> /// <summary>
@ -106,8 +107,8 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public float3 AngularVelocity public float3 AngularVelocity
{ {
get => Engine.GetComponent<RigidBodyEntityStruct>(Id).Get().angularVelocity; get => Engine.GetComponent<RigidBodyEntityStruct>(this).angularVelocity;
set => Engine.GetComponent<RigidBodyEntityStruct>(Id).Get().angularVelocity = value; set => Engine.GetComponent<RigidBodyEntityStruct>(this).angularVelocity = value;
} }
public static void Init() public static void Init()

View file

@ -1,6 +1,7 @@
using Svelto.ECS; using Svelto.ECS;
using Techblox.FlyCam; using Techblox.FlyCam;
using TechbloxModdingAPI.Engines; using TechbloxModdingAPI.Engines;
using TechbloxModdingAPI.Utility;
namespace TechbloxModdingAPI.Players namespace TechbloxModdingAPI.Players
{ {
@ -18,11 +19,9 @@ namespace TechbloxModdingAPI.Players
public string Name => "TechbloxModdingAPIFlyCamEngine"; public string Name => "TechbloxModdingAPIFlyCamEngine";
public bool isRemovable => false; public bool isRemovable => false;
public OptionalRef<T> GetComponent<T>(uint id) where T : unmanaged, IEntityComponent public ref T GetComponent<T>(FlyCam cam) where T : unmanaged, IEntityComponent
{ {
if (entitiesDB.TryQueryEntitiesAndIndex<T>(id, Techblox.FlyCam.FlyCam.Group, out uint index, out var array)) return ref entitiesDB.QueryEntityOrDefault<T>(cam);
return new OptionalRef<T>(array, index);
return new OptionalRef<T>();
} }
} }
} }

View file

@ -12,9 +12,9 @@ namespace TechbloxModdingAPI
/// <summary> /// <summary>
/// A rigid body (like a chunk of connected blocks) during simulation. /// A rigid body (like a chunk of connected blocks) during simulation.
/// </summary> /// </summary>
public class SimBody : IEquatable<SimBody>, IEquatable<EGID> public class SimBody : EcsObjectBase, IEquatable<SimBody>, IEquatable<EGID>
{ {
public EGID Id { get; } public override EGID Id { get; }
/// <summary> /// <summary>
/// The cluster this chunk belongs to, or null if no cluster destruction manager present or the chunk doesn't exist. /// 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 public float InitialHealth
{ {
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).initialHealth; get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).initialHealth;
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).initialHealth = value; set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).initialHealth = value;
} }
public float CurrentHealth public float CurrentHealth
{ {
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).currentHealth; get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).currentHealth;
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).currentHealth = value; set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).currentHealth = value;
} }
public float HealthMultiplier public float HealthMultiplier
{ {
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier; get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).healthMultiplier;
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier = value; set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).healthMultiplier = value;
} }
/// <summary> /// <summary>
/// Whether the body can be moved or static. /// Whether the body can be moved or static.
/// </summary> /// </summary>
public bool Static => Block.BlockEngine.GetBlockInfo<MassEntityStruct>(Id).isStatic; //Setting it doesn't have any effect public bool Static => Block.BlockEngine.GetBlockInfo<MassEntityStruct>(this).isStatic; //Setting it doesn't have any effect
/// <summary> /// <summary>
/// The rigid bodies connected to this one via functional joints (broken ones don't count). /// 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() private ref RigidBodyEntityStruct GetStruct()
{ {
return ref Block.BlockEngine.GetBlockInfo<RigidBodyEntityStruct>(Id); return ref Block.BlockEngine.GetBlockInfo<RigidBodyEntityStruct>(this);
} }
public override string ToString() public override string ToString()

View file

@ -487,9 +487,9 @@
<HintPath>..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.Inventory.dll</HintPath> <HintPath>..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.Inventory.dll</HintPath>
<HintPath>..\..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.Inventory.dll</HintPath> <HintPath>..\..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.Inventory.dll</HintPath>
</Reference> </Reference>
<Reference Include="RobocraftX.GUI.RemoveBlock"> <Reference Include="RobocraftX.GUI.PauseMenu">
<HintPath>..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.RemoveBlock.dll</HintPath> <HintPath>..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.PauseMenu.dll</HintPath>
<HintPath>..\..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.RemoveBlock.dll</HintPath> <HintPath>..\..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.PauseMenu.dll</HintPath>
</Reference> </Reference>
<Reference Include="RobocraftX.GUI.ScaleGhost"> <Reference Include="RobocraftX.GUI.ScaleGhost">
<HintPath>..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.ScaleGhost.dll</HintPath> <HintPath>..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.ScaleGhost.dll</HintPath>
@ -655,9 +655,9 @@
<HintPath>..\ref\TechbloxPreview_Data\Managed\Techblox.InputCapture.dll</HintPath> <HintPath>..\ref\TechbloxPreview_Data\Managed\Techblox.InputCapture.dll</HintPath>
<HintPath>..\..\ref\TechbloxPreview_Data\Managed\Techblox.InputCapture.dll</HintPath> <HintPath>..\..\ref\TechbloxPreview_Data\Managed\Techblox.InputCapture.dll</HintPath>
</Reference> </Reference>
<Reference Include="Techblox.MouseCursor"> <Reference Include="Techblox.Pointer">
<HintPath>..\ref\TechbloxPreview_Data\Managed\Techblox.MouseCursor.dll</HintPath> <HintPath>..\ref\TechbloxPreview_Data\Managed\Techblox.Pointer.dll</HintPath>
<HintPath>..\..\ref\TechbloxPreview_Data\Managed\Techblox.MouseCursor.dll</HintPath> <HintPath>..\..\ref\TechbloxPreview_Data\Managed\Techblox.Pointer.dll</HintPath>
</Reference> </Reference>
<Reference Include="Techblox.SwitchAnimation"> <Reference Include="Techblox.SwitchAnimation">
<HintPath>..\ref\TechbloxPreview_Data\Managed\Techblox.SwitchAnimation.dll</HintPath> <HintPath>..\ref\TechbloxPreview_Data\Managed\Techblox.SwitchAnimation.dll</HintPath>

View file

@ -0,0 +1,55 @@
using Svelto.ECS;
using Svelto.ECS.Hybrid;
using TechbloxModdingAPI.Blocks;
namespace TechbloxModdingAPI.Utility
{
public static class ManagedApiExtensions
{
/// <summary>
/// Attempts to query an entity and returns an optional that contains the result if succeeded.
/// <b>This overload does not take initializer data into account.</b>
/// </summary>
/// <param name="entitiesDB">The entities DB</param>
/// <param name="egid">The EGID to query</param>
/// <typeparam name="T">The component type to query</typeparam>
/// <returns>An optional that contains the result on success or is empty if not found</returns>
public static OptionalRef<T> QueryEntityOptional<T>(this EntitiesDB entitiesDB, EGID egid)
where T : struct, IEntityViewComponent
{
return entitiesDB.TryQueryEntitiesAndIndex<T>(egid, out uint index, out var array)
? new OptionalRef<T>(array, index)
: new OptionalRef<T>();
}
/// <summary>
/// Attempts to query an entity and returns the result or a dummy value that can be modified.
/// </summary>
/// <param name="entitiesDB"></param>
/// <param name="obj"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static OptionalRef<T> QueryEntityOptional<T>(this EntitiesDB entitiesDB, EcsObjectBase obj)
where T : struct, IEntityViewComponent
{
var opt = QueryEntityOptional<T>(entitiesDB, obj.Id);
return opt ? opt : new OptionalRef<T>(obj, true);
}
/// <summary>
/// Attempts to query an entity and returns the result or a dummy value that can be modified.
/// </summary>
/// <param name="entitiesDB"></param>
/// <param name="obj"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static ref T QueryEntityOrDefault<T>(this EntitiesDB entitiesDB, EcsObjectBase obj)
where T : struct, IEntityViewComponent
{
var opt = QueryEntityOptional<T>(entitiesDB, obj.Id);
if (opt) return ref opt.Get();
if (obj.InitData.Valid) return ref obj.InitData.Initializer(obj.Id).GetOrCreate<T>();
return ref opt.Get(); //Default value
}
}
}

View file

@ -0,0 +1,53 @@
using Svelto.ECS;
namespace TechbloxModdingAPI.Utility
{
public static class NativeApiExtensions
{
/// <summary>
/// Attempts to query an entity and returns an optional that contains the result if succeeded.
/// <b>This overload does not take initializer data into account.</b>
/// </summary>
/// <param name="entitiesDB">The entities DB</param>
/// <param name="egid">The EGID to query</param>
/// <typeparam name="T">The component type to query</typeparam>
/// <returns>An optional that contains the result on success or is empty if not found</returns>
public static OptionalRef<T> QueryEntityOptional<T>(this EntitiesDB entitiesDB, EGID egid)
where T : unmanaged, IEntityComponent
{
return entitiesDB.TryQueryEntitiesAndIndex<T>(egid, out uint index, out var array)
? new OptionalRef<T>(array, index)
: new OptionalRef<T>();
}
/// <summary>
/// Attempts to query an entity and returns the result or a dummy value that can be modified.
/// </summary>
/// <param name="entitiesDB"></param>
/// <param name="obj"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static OptionalRef<T> QueryEntityOptional<T>(this EntitiesDB entitiesDB, EcsObjectBase obj)
where T : unmanaged, IEntityComponent
{
var opt = QueryEntityOptional<T>(entitiesDB, obj.Id);
return opt ? opt : new OptionalRef<T>(obj, true);
}
/// <summary>
/// Attempts to query an entity and returns the result or a dummy value that can be modified.
/// </summary>
/// <param name="entitiesDB"></param>
/// <param name="obj"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static ref T QueryEntityOrDefault<T>(this EntitiesDB entitiesDB, EcsObjectBase obj)
where T : unmanaged, IEntityComponent
{
var opt = QueryEntityOptional<T>(entitiesDB, obj.Id);
if (opt) return ref opt.Get();
if (obj.InitData.Valid) return ref obj.InitData.Initializer(obj.Id).GetOrCreate<T>();
return ref opt.Get(); //Default value
}
}
}

View file

@ -1,60 +1,93 @@
using System; using System;
using System.Collections; using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using TechbloxModdingAPI.Blocks;
using Svelto.DataStructures; using Svelto.DataStructures;
using Svelto.ECS; using Svelto.ECS;
namespace TechbloxModdingAPI namespace TechbloxModdingAPI.Utility
{ {
public struct OptionalRef<T> where T : unmanaged public ref struct OptionalRef<T> where T : struct, IEntityComponent
{ {
private bool exists; private readonly State state;
private readonly uint index;
private NB<T> array; private NB<T> array;
private uint index; private MB<T> managedArray;
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)
{ {
exists = true; state = State.Native;
this.array = array; this.array = array;
this.index = index; this.index = index;
initializer = default;
} }
public OptionalRef(ref T value) public OptionalRef(MB<T> array, uint index)
{ {
exists = true; state = State.Managed;
managedArray = array;
this.index = index;
initializer = default;
this.array = default;
}
/// <summary>
/// Wraps the initializer data, if present.
/// </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)
{
if (obj.InitData.Valid)
{
initializer = obj.InitData.Initializer(obj.Id);
state = (unmanaged ? State.Native : State.Managed) | State.Initializer;
}
else
{
initializer = default;
state = State.Empty;
}
array = default; array = default;
index = default; index = default;
} }
public ref T Get(T def = default) /// <summary>
/// Returns the value or a default value if empty. Supports objects that are being initialized.
/// </summary>
/// <returns>The value or the default value</returns>
public ref T Get()
{ {
if (exists) if (state == State.Empty) return ref CompRefCache.Default;
return ref array[index]; if ((state & State.Initializer) != State.Empty) return ref initializer.GetOrCreate<T>();
return ref CompRefCache<T>._default; 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<T> opt) => opt.Get(); public static implicit operator T(OptionalRef<T> opt) => opt.Get();
public static implicit operator bool(OptionalRef<T> opt) => opt.exists; public static implicit operator bool(OptionalRef<T> opt) => opt.state != State.Empty;
/*public delegate ref TR Mapper<TR>(ref T component) where TR : unmanaged;
public unsafe delegate TR* PMapper<TR>(T* component) where TR : unmanaged;
public unsafe OptionalRef<TR> Map<TR>(PMapper<TR> mapper) where TR : unmanaged =>
exists ? new OptionalRef<TR>(ref *mapper(pointer)) : new OptionalRef<TR>();*/
/// <summary> /// <summary>
/// Creates an instance of a struct T that can be referenced. /// Creates an instance of a struct T that can be referenced.
/// </summary> /// </summary>
/// <typeparam name="T">The struct type to cache</typeparam> internal struct CompRefCache
private struct CompRefCache<T> where T : unmanaged
{ {
public static T _default; public static T Default;
}
/// <summary>
/// A byte that holds state in its bits.
/// </summary>
[Flags]
private enum State : byte
{
Empty,
Native,
Managed,
Initializer = 4
} }
} }
} }