Merge branch 'feature-ecs_object_base'
This commit is contained in:
commit
aa12b848d0
27 changed files with 526 additions and 516 deletions
|
@ -27,7 +27,7 @@ def buildReferencesXml(path):
|
|||
return "<!--Start Dependencies-->\n <ItemGroup>\n" + "".join(result) + " </ItemGroup>\n<!--End Dependencies-->"
|
||||
|
||||
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"\<!--\s*Start\s+Dependencies\s*--\>", fileStr)
|
||||
|
@ -45,7 +45,7 @@ if __name__ == "__main__":
|
|||
print("Unable to find dependency XML comments, aborting!")
|
||||
exit(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")
|
||||
xmlFile.write(newFileStr)
|
||||
# print(newFileStr)
|
||||
|
|
|
@ -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.
|
||||
/// </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 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<T>(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;
|
||||
|
||||
/// <summary>
|
||||
|
@ -256,10 +254,10 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
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);
|
||||
|
@ -271,10 +269,10 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
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);
|
||||
|
@ -287,14 +285,14 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float3 Scale
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (ScalingEntityStruct st) => st.scale);
|
||||
get => BlockEngine.GetBlockInfo<ScalingEntityStruct>(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<ScalingEntityStruct>(this).scale = value;
|
||||
if (!Exists) return; //UpdateCollision needs the block to exist
|
||||
ScalingEngine.UpdateCollision(Id);
|
||||
BlockEngine.UpdateDisplayedBlock(Id);
|
||||
|
@ -307,12 +305,11 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public int UniformScale
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (UniformBlockScaleEntityStruct st) => st.scaleFactor);
|
||||
get => BlockEngine.GetBlockInfo<UniformBlockScaleEntityStruct>(this).scaleFactor;
|
||||
set
|
||||
{
|
||||
if (value < 1) value = 1;
|
||||
BlockEngine.SetBlockInfo(this, (ref UniformBlockScaleEntityStruct st, int val) => st.scaleFactor = val,
|
||||
value);
|
||||
BlockEngine.GetBlockInfo<UniformBlockScaleEntityStruct>(this).scaleFactor = value;
|
||||
Scale = new float3(value, value, value);
|
||||
}
|
||||
}
|
||||
|
@ -322,16 +319,12 @@ namespace TechbloxModdingAPI
|
|||
*/
|
||||
public bool Flipped
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (ScalingEntityStruct st) => st.scale.x < 0);
|
||||
get => BlockEngine.GetBlockInfo<ScalingEntityStruct>(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<ScalingEntityStruct>(this);
|
||||
st.scale.x = math.abs(st.scale.x) * (value ? -1 : 1);
|
||||
BlockEngine.UpdatePrefab(this, (ushort) Type, (byte) Material, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -342,7 +335,8 @@ namespace TechbloxModdingAPI
|
|||
{
|
||||
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
|
||||
{
|
||||
byte index = BlockEngine.GetBlockInfo(this, (ColourParameterEntityStruct st) => st.indexInPalette,
|
||||
byte.MaxValue);
|
||||
return new BlockColor(index);
|
||||
var opt = BlockEngine.GetBlockInfoOptional<ColourParameterEntityStruct>(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<ColourParameterEntityStruct>(this);
|
||||
color.indexInPalette = value.Index;
|
||||
color.hasNetworkChange = true;
|
||||
color.paletteColour = BlockEngine.ConvertBlockColor(color.indexInPalette);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,14 +365,12 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float4 CustomColor
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (ColourParameterEntityStruct st) => st.paletteColour);
|
||||
get => BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(this).paletteColour;
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this, (ref ColourParameterEntityStruct color, float4 val) =>
|
||||
{
|
||||
color.paletteColour = val;
|
||||
color.hasNetworkChange = true;
|
||||
}, value);
|
||||
ref var color = ref BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(this);
|
||||
color.paletteColour = value;
|
||||
color.hasNetworkChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -389,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<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>
|
||||
|
@ -400,13 +397,11 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public string Label
|
||||
{
|
||||
get => BlockEngine.GetBlockInfoViewStruct(this, (TextLabelEntityViewStruct st) => st.textLabelComponent?.text);
|
||||
get => BlockEngine.GetBlockInfoViewComponent<TextLabelEntityViewStruct>(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<TextLabelEntityViewStruct>(this).textLabelComponent;
|
||||
if (comp != null) comp.text = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -424,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<BlockGroupEntityComponent>(this);
|
||||
return blockGroup = bgec.currentBlockGroup == -1 ? null : new BlockGroup(bgec.currentBlockGroup, this);
|
||||
}
|
||||
set
|
||||
{
|
||||
|
@ -437,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<BlockGroupEntityComponent>(this).currentBlockGroup = (int?) value?.Id.entityID ?? -1;
|
||||
value?.AddInternal(this);
|
||||
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>
|
||||
public SimBody GetSimBody()
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this,
|
||||
(GridConnectionsEntityStruct st) => st.machineRigidBodyId != uint.MaxValue
|
||||
? new SimBody(st.machineRigidBodyId, st.clusterId)
|
||||
: null);
|
||||
var st = BlockEngine.GetBlockInfo<GridConnectionsEntityStruct>(this);
|
||||
return st.machineRigidBodyId != uint.MaxValue
|
||||
? new SimBody(st.machineRigidBodyId, st.clusterId)
|
||||
: null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -558,7 +550,7 @@ namespace TechbloxModdingAPI
|
|||
|
||||
//Lets improve that using delegates
|
||||
var block = New<T>(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
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
|
||||
using Gamecraft.Blocks.BlockGroups;
|
||||
using Svelto.ECS;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using TechbloxModdingAPI.Blocks;
|
||||
|
@ -13,10 +14,10 @@ namespace TechbloxModdingAPI
|
|||
/// <summary>
|
||||
/// A group of blocks that can be selected together. The placed version of blueprints. Dispose after usage.
|
||||
/// </summary>
|
||||
public class BlockGroup : ICollection<Block>, IDisposable
|
||||
public class BlockGroup : EcsObjectBase, ICollection<Block>, IDisposable
|
||||
{
|
||||
internal static BlueprintEngine _engine = new BlueprintEngine();
|
||||
public int Id { get; }
|
||||
public override EGID Id { get; }
|
||||
private readonly Block sourceBlock;
|
||||
private readonly List<Block> blocks;
|
||||
private float3 position, rotation;
|
||||
|
@ -26,7 +27,7 @@ namespace TechbloxModdingAPI
|
|||
{
|
||||
if (id == BlockGroupUtility.GROUP_UNASSIGNED)
|
||||
throw new BlockException("Cannot create a block group for blocks without a group!");
|
||||
Id = id;
|
||||
Id = new EGID((uint) id, BlockGroupExclusiveGroups.BlockGroupEntityGroup);
|
||||
sourceBlock = block;
|
||||
blocks = new List<Block>(GetBlocks());
|
||||
Block.Removed += OnBlockRemoved;
|
||||
|
@ -168,7 +169,7 @@ namespace TechbloxModdingAPI
|
|||
internal void AddInternal(Block item)
|
||||
{
|
||||
blocks.Add(item);
|
||||
_engine.AddBlockToGroup(item.Id, Id);
|
||||
_engine.AddBlockToGroup(item.Id, (int) Id.entityID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -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,76 +70,24 @@ namespace TechbloxModdingAPI.Blocks
|
|||
: entitiesDB.QueryEntity<PaletteEntryEntityStruct>(index,
|
||||
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 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
|
||||
{
|
||||
if (entitiesDB.Exists<T>(blockID))
|
||||
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
|
||||
return entitiesDB.QueryEntityOptional<T>(block);
|
||||
}
|
||||
|
||||
public U GetBlockInfo<T, U>(Block block, Func<T, U> getter,
|
||||
U def = default) where T : unmanaged, IEntityComponent
|
||||
public ref T GetBlockInfo<T>(Block block) where T : unmanaged, IEntityComponent
|
||||
{
|
||||
if (entitiesDB.Exists<T>(block.Id))
|
||||
return getter(entitiesDB.QueryEntity<T>(block.Id));
|
||||
return GetBlockInitInfo(block, getter, def);
|
||||
}
|
||||
|
||||
public U GetBlockInfoViewStruct<T, U>(Block block, Func<T, U> getter,
|
||||
U def = default) where T : struct, IEntityViewComponent
|
||||
{
|
||||
if (entitiesDB.Exists<T>(block.Id))
|
||||
return getter(entitiesDB.QueryEntity<T>(block.Id));
|
||||
return GetBlockInitInfo(block, getter, def);
|
||||
return ref entitiesDB.QueryEntityOrDefault<T>(block);
|
||||
}
|
||||
|
||||
private U GetBlockInitInfo<T, U>(Block block, Func<T, U> getter, U def) where T : struct, IEntityComponent
|
||||
internal ref T GetBlockInfo<T>(EcsObjectBase obj) where T : unmanaged, 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;
|
||||
return ref entitiesDB.QueryEntityOrDefault<T>(obj);
|
||||
}
|
||||
|
||||
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
|
||||
public ref T GetBlockInfoViewComponent<T>(Block block) 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);
|
||||
}
|
||||
return ref entitiesDB.QueryEntityOrDefault<T>(block);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
var ret = new FasterList<SimBody>(4);
|
||||
|
|
|
@ -19,10 +19,9 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public float MaxForce
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (DampedSpringReadOnlyStruct dsrs) => dsrs.springFrequency);
|
||||
get => BlockEngine.GetBlockInfo<DampedSpringReadOnlyStruct>(this).springFrequency;
|
||||
|
||||
set => BlockEngine.SetBlockInfo(this,
|
||||
(ref DampedSpringReadOnlyStruct dsrs, float val) => dsrs.springFrequency = val, value);
|
||||
set => BlockEngine.GetBlockInfo<DampedSpringReadOnlyStruct>(this).springFrequency = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -39,10 +38,9 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public float Damping
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (DampedSpringReadOnlyStruct ljf) => ljf.springDamping);
|
||||
get => BlockEngine.GetBlockInfo<DampedSpringReadOnlyStruct>(this).springDamping;
|
||||
|
||||
set => BlockEngine.SetBlockInfo(this,
|
||||
(ref DampedSpringReadOnlyStruct ljf, float val) => ljf.springDamping = val, value);
|
||||
set => BlockEngine.GetBlockInfo<DampedSpringReadOnlyStruct>(this).springDamping = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -50,10 +48,9 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public float MaxExtension
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (DampedSpringReadOnlyStruct ljf) => ljf.maxExtent);
|
||||
get => BlockEngine.GetBlockInfo<DampedSpringReadOnlyStruct>(this).maxExtent;
|
||||
|
||||
set => BlockEngine.SetBlockInfo(this,
|
||||
(ref DampedSpringReadOnlyStruct ljf, float val) => ljf.maxExtent = val, value);
|
||||
set => BlockEngine.GetBlockInfo<DampedSpringReadOnlyStruct>(this).maxExtent = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,12 +28,12 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this, (MotorReadOnlyStruct st) => st.maxVelocity);
|
||||
return BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(this).maxVelocity;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this, (MotorReadOnlyStruct st) => st.maxForce);
|
||||
return BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(this).maxForce;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this, (MotorReadOnlyStruct st) => st.reverse);
|
||||
return BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(this).reverse;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this, (ref MotorReadOnlyStruct st, bool val) => st.reverse = val, value);
|
||||
BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(this).reverse = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<PositionEntityStruct>(blockID))
|
||||
{
|
||||
if (data.Group == null) return float3.zero;
|
||||
var init = new EntityInitializer(blockID, data.Group, data.Reference);
|
||||
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);
|
||||
ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntityOrDefault<PositionEntityStruct>(block);
|
||||
ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntityOrDefault<GridRotationStruct>(block);
|
||||
ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntityOrDefault<LocalTransformEntityStruct>(block);
|
||||
ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntityOrDefault<UECSPhysicsEntityStruct>(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<GridConnectionsEntityStruct>(blockID).isProcessed = false;
|
||||
if (phyStruct.ID != EGID.Empty)
|
||||
{ //It exists
|
||||
FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Translation
|
||||
{
|
||||
Value = posStruct.position
|
||||
});
|
||||
}
|
||||
|
||||
entitiesDB.QueryEntityOrDefault<GridConnectionsEntityStruct>(block).isProcessed = false;
|
||||
return posStruct.position;
|
||||
}
|
||||
|
||||
internal float3 GetPosition(EGID blockID, BlockEngine.BlockInitData data)
|
||||
internal float3 GetPosition(Block block)
|
||||
{
|
||||
if (!entitiesDB.Exists<PositionEntityStruct>(blockID))
|
||||
{
|
||||
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;
|
||||
return entitiesDB.QueryEntityOrDefault<PositionEntityStruct>(block).position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,13 +28,12 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this, (MusicBlockDataEntityStruct st) => st.trackIndx);
|
||||
return BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this).trackIndx;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this,
|
||||
(ref MusicBlockDataEntityStruct msdes, byte val) => msdes.trackIndx = val, value);
|
||||
BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this).trackIndx = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,24 +41,22 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this,
|
||||
(MusicBlockDataEntityStruct msdes) => msdes.fmod2DEventPaths.Get<Guid>(msdes.trackIndx));
|
||||
var msdes = BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this);
|
||||
return msdes.fmod2DEventPaths.Get<Guid>(msdes.trackIndx);
|
||||
}
|
||||
|
||||
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);
|
||||
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<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>()];
|
||||
for (byte i = 0; i < tracks.Length; i++)
|
||||
{
|
||||
tracks[i] = msdes.fmod2DEventPaths.Get<Guid>(i);
|
||||
}
|
||||
return tracks;
|
||||
});
|
||||
tracks[i] = msdes.fmod2DEventPaths.Get<Guid>(i);
|
||||
}
|
||||
return tracks;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,13 +78,12 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this, (MusicBlockDataEntityStruct msdes) => msdes.tweakableVolume);
|
||||
return BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this).tweakableVolume;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this,
|
||||
(ref MusicBlockDataEntityStruct msdes, float val) => msdes.tweakableVolume = val, value);
|
||||
BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(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<MusicBlockDataEntityStruct>(this).channelType;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this,
|
||||
(ref MusicBlockDataEntityStruct msdes, ChannelType val) => msdes.channelType = (byte) val, value);
|
||||
BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this).channelType = (byte) value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,33 +105,31 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this,
|
||||
(MusicBlockDataEntityStruct msdes) => msdes.isPlaying);
|
||||
return BlockEngine.GetBlockInfo<MusicBlockDataEntityStruct>(this).isPlaying;
|
||||
}
|
||||
|
||||
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;
|
||||
if (val)
|
||||
{
|
||||
// start playing
|
||||
EventInstance inst = RuntimeManager.CreateInstance(msdes.fmod2DEventPaths.Get<Guid>(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<Guid>(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,14 +16,11 @@ namespace TechbloxModdingAPI.Blocks
|
|||
|
||||
public char Identifier
|
||||
{
|
||||
get => (char) BlockEngine.GetBlockInfo(this, (ObjectIdEntityStruct st) => st.objectId + 'A');
|
||||
get => (char) (BlockEngine.GetBlockInfo<ObjectIdEntityStruct>(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<ObjectIdEntityStruct>(this).objectId = (byte) (value - 'A');
|
||||
Label = value + ""; //The label isn't updated automatically
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +29,7 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public byte SimID
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (ObjectIdEntityStruct st) => st.simObjectId);
|
||||
get => BlockEngine.GetBlockInfo<ObjectIdEntityStruct>(this).simObjectId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -26,12 +26,11 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public float MaximumExtension
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (PistonReadOnlyStruct st) => st.maxDeviation);
|
||||
get => BlockEngine.GetBlockInfo<PistonReadOnlyStruct>(this).maxDeviation;
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this, (ref PistonReadOnlyStruct st, float val) => st.maxDeviation = val,
|
||||
value);
|
||||
BlockEngine.GetBlockInfo<PistonReadOnlyStruct>(this).maxDeviation = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,11 +39,11 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public float MaximumForce
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (PistonReadOnlyStruct st) => st.pistonVelocity);
|
||||
get => BlockEngine.GetBlockInfo<PistonReadOnlyStruct>(this).pistonVelocity;
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this, (ref PistonReadOnlyStruct st, float val) => st.pistonVelocity = val, value);
|
||||
BlockEngine.GetBlockInfo<PistonReadOnlyStruct>(this).pistonVelocity = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<RotationEntityStruct>(blockID))
|
||||
{
|
||||
if (data.Group == null) return float3.zero;
|
||||
var init = new EntityInitializer(blockID, data.Group, data.Reference);
|
||||
init.GetOrCreate<RotationEntityStruct>().rotation = Quaternion.Euler(vector);
|
||||
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
|
||||
ref RotationEntityStruct rotStruct = ref this.entitiesDB.QueryEntityOrDefault<RotationEntityStruct>(block);
|
||||
ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntityOrDefault<GridRotationStruct>(block);
|
||||
ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntityOrDefault<LocalTransformEntityStruct>(block);
|
||||
ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntityOrDefault<UECSPhysicsEntityStruct>(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<GridConnectionsEntityStruct>(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<GridConnectionsEntityStruct>(block).isProcessed = false;
|
||||
return ((Quaternion)rotStruct.rotation).eulerAngles;
|
||||
|
||||
}
|
||||
|
||||
internal float3 GetRotation(EGID blockID, BlockEngine.BlockInitData data)
|
||||
internal float3 GetRotation(Block block)
|
||||
{
|
||||
if (!entitiesDB.Exists<RotationEntityStruct>(blockID))
|
||||
{
|
||||
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);
|
||||
ref RotationEntityStruct rotStruct = ref entitiesDB.QueryEntityOrDefault<RotationEntityStruct>(block);
|
||||
return ((Quaternion) rotStruct.rotation).eulerAngles;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,11 +26,11 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public float MinimumAngle
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (ServoReadOnlyStruct st) => st.minDeviation);
|
||||
get => BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(this).minDeviation;
|
||||
|
||||
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>
|
||||
public float MaximumAngle
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (ServoReadOnlyStruct st) => st.maxDeviation);
|
||||
get => BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(this).maxDeviation;
|
||||
|
||||
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>
|
||||
public float MaximumForce
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (ServoReadOnlyStruct st) => st.servoVelocity);
|
||||
get => BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(this).servoVelocity;
|
||||
|
||||
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>
|
||||
public bool Reverse
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (ServoReadOnlyStruct st) => st.reverse);
|
||||
get => BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(this).reverse;
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this, (ref ServoReadOnlyStruct st, bool val) => st.reverse = val, value);
|
||||
BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(this).reverse = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,13 +22,12 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.tweakableVolume);
|
||||
return BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).tweakableVolume;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this,
|
||||
(ref SoundSfxBlockDataEntityStruct obj, float val) => obj.tweakableVolume = val, value);
|
||||
BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).tweakableVolume = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,13 +35,12 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.tweakablePitch);
|
||||
return BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).tweakablePitch;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this,
|
||||
(ref SoundSfxBlockDataEntityStruct obj, float val) => obj.tweakablePitch = val, value);
|
||||
BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).tweakablePitch = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,13 +48,12 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.is3D);
|
||||
return BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).is3D;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this,
|
||||
(ref SoundSfxBlockDataEntityStruct obj, bool val) => obj.is3D = val, value);
|
||||
BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).is3D = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,13 +61,12 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => (ChannelType)obj.channelType);
|
||||
return (ChannelType) BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).channelType;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this,
|
||||
(ref SoundSfxBlockDataEntityStruct obj, ChannelType val) => obj.tweakableVolume = (byte) val, value);
|
||||
BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).channelType = (byte) value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,13 +74,12 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.soundEffectIndex);
|
||||
return BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).soundEffectIndex;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this,
|
||||
(ref SoundSfxBlockDataEntityStruct obj, byte val) => obj.soundEffectIndex = val, value);
|
||||
BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).soundEffectIndex = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,35 +88,36 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this,
|
||||
(SoundSfxBlockDataEntityStruct obj) => obj.is3D ? obj.fmod3DEventPaths.Get<Guid>(obj.soundEffectIndex) : obj.fmod2DEventPaths.Get<Guid>(obj.soundEffectIndex));
|
||||
var obj = BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this);
|
||||
return obj.is3D
|
||||
? obj.fmod3DEventPaths.Get<Guid>(obj.soundEffectIndex)
|
||||
: obj.fmod2DEventPaths.Get<Guid>(obj.soundEffectIndex);
|
||||
}
|
||||
|
||||
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);
|
||||
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<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);
|
||||
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<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>()];
|
||||
for (byte i = 0; i < tracks.Length; i++)
|
||||
{
|
||||
tracks[i] = obj.fmod2DEventPaths.Get<Guid>(i);
|
||||
}
|
||||
return tracks;
|
||||
});
|
||||
tracks[i] = obj.fmod2DEventPaths.Get<Guid>(i);
|
||||
}
|
||||
|
||||
return tracks;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Guid[] Tracks3D
|
||||
{
|
||||
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>()];
|
||||
for (byte i = 0; i < tracks.Length; i++)
|
||||
{
|
||||
tracks[i] = obj.fmod2DEventPaths.Get<Guid>(i);
|
||||
}
|
||||
return tracks;
|
||||
});
|
||||
tracks[i] = obj.fmod2DEventPaths.Get<Guid>(i);
|
||||
}
|
||||
|
||||
return tracks;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,13 +156,12 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.isLoopedBlock);
|
||||
return BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).isLoopedBlock;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this,
|
||||
(ref SoundSfxBlockDataEntityStruct obj, bool val) => obj.isLoopedBlock = val, value);
|
||||
BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).isLoopedBlock = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,33 +169,33 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo(this,
|
||||
(SoundSfxBlockDataEntityStruct obj) => obj.isPlaying);
|
||||
return BlockEngine.GetBlockInfo<SoundSfxBlockDataEntityStruct>(this).isPlaying;
|
||||
}
|
||||
|
||||
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;
|
||||
if (val)
|
||||
{
|
||||
// start playing
|
||||
EventInstance inst = RuntimeManager.CreateInstance(obj.is3D ? obj.fmod3DEventPaths.Get<Guid>(obj.soundEffectIndex) : obj.fmod2DEventPaths.Get<Guid>(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<Guid>(obj.soundEffectIndex)
|
||||
: obj.fmod2DEventPaths.Get<Guid>(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<BlockPortsStruct>(block, block.Id, out bool exists);
|
||||
if (!exists)
|
||||
var bps = entitiesDB.QueryEntityOptional<BlockPortsStruct>(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<BlockPortsStruct>(block, block.Id, out exists);
|
||||
return new EGID(ports.firstInputID + portUsage, NamedExclusiveGroup<InputPortsGroup>.Group);
|
||||
var ports = entitiesDB.QueryEntityOptional<BlockPortsStruct>(block);
|
||||
exists = ports;
|
||||
return new EGID(ports.Get().firstInputID + portUsage, NamedExclusiveGroup<InputPortsGroup>.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<BlockPortsStruct>(block, block.Id, out exists);
|
||||
return new EGID(ports.firstOutputID + portUsage, NamedExclusiveGroup<OutputPortsGroup>.Group);
|
||||
var ports = entitiesDB.QueryEntityOptional<BlockPortsStruct>(block);
|
||||
exists = ports;
|
||||
return new EGID(ports.Get().firstOutputID + portUsage, NamedExclusiveGroup<OutputPortsGroup>.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<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)
|
||||
{
|
||||
ExclusiveGroup group = input
|
||||
|
|
|
@ -67,7 +67,7 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public uint InputCount
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (BlockPortsStruct st) => st.inputCount);
|
||||
get => BlockEngine.GetBlockInfo<BlockPortsStruct>(this).inputCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -75,7 +75,7 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public uint OutputCount
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (BlockPortsStruct st) => st.outputCount);
|
||||
get => BlockEngine.GetBlockInfo<BlockPortsStruct>(this).outputCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -109,7 +109,6 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// <returns>The localized port name.</returns>
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -28,11 +28,11 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public uint Lives
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (SpawnPointStatsEntityStruct st) => st.lives);
|
||||
get => BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(this).lives;
|
||||
|
||||
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>
|
||||
public bool Damageable
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (SpawnPointStatsEntityStruct st) => st.canTakeDamage);
|
||||
get => BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(this).canTakeDamage;
|
||||
|
||||
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>
|
||||
public bool GameOverEnabled
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (SpawnPointStatsEntityStruct st) => st.gameOverScreen);
|
||||
get => BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(this).gameOverScreen;
|
||||
|
||||
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>
|
||||
public byte Team
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (SpawnPointIdsEntityStruct st) => st.teamId);
|
||||
get => BlockEngine.GetBlockInfo<SpawnPointIdsEntityStruct>(this).teamId;
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this, (ref SpawnPointIdsEntityStruct st, byte val) => st.teamId = val, value);
|
||||
BlockEngine.GetBlockInfo<SpawnPointIdsEntityStruct>(this).teamId = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,17 +26,15 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// The text block's current text.
|
||||
/// </summary>
|
||||
public string Text
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (TextBlockDataStruct st) => st.textCurrent);
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<TextBlockDataStruct>(this).textCurrent;
|
||||
|
||||
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<TextBlockDataStruct>(this);
|
||||
tbds.textCurrent.Set(value);
|
||||
tbds.textStored.Set(value, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,13 +43,12 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public string TextBlockId
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (TextBlockDataStruct st) => st.textBlockID);
|
||||
get => BlockEngine.GetBlockInfo<TextBlockDataStruct>(this).textBlockID;
|
||||
|
||||
set
|
||||
{
|
||||
if (value == null) value = "";
|
||||
BlockEngine.SetBlockInfo(this, (ref TextBlockDataStruct tbds, string val) =>
|
||||
tbds.textBlockID.Set(val), value);
|
||||
BlockEngine.GetBlockInfo<TextBlockDataStruct>(this).textBlockID.Set(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,12 +28,11 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public float Start
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (TimerBlockDataStruct st) => st.startTime);
|
||||
get => BlockEngine.GetBlockInfo<TimerBlockDataStruct>(this).startTime;
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this, (ref TimerBlockDataStruct tbds, float val) => tbds.startTime = val,
|
||||
value);
|
||||
BlockEngine.GetBlockInfo<TimerBlockDataStruct>(this).startTime = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,12 +41,11 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public float End
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (TimerBlockDataStruct st) => st.endTime);
|
||||
get => BlockEngine.GetBlockInfo<TimerBlockDataStruct>(this).endTime;
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this, (ref TimerBlockDataStruct tbds, float val) => tbds.endTime = val,
|
||||
value);
|
||||
BlockEngine.GetBlockInfo<TimerBlockDataStruct>(this).endTime = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,12 +54,11 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public bool DisplayMilliseconds
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (TimerBlockDataStruct st) => st.outputFormatHasMS);
|
||||
get => BlockEngine.GetBlockInfo<TimerBlockDataStruct>(this).outputFormatHasMS;
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this, (ref TimerBlockDataStruct tbds, bool val) => tbds.outputFormatHasMS = val,
|
||||
value);
|
||||
BlockEngine.GetBlockInfo<TimerBlockDataStruct>(this).outputFormatHasMS = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,12 +67,11 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// </summary>
|
||||
public int CurrentTime
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo(this, (TimerBlockLabelCacheEntityStruct st) => st.timeLastRenderFrameMS);
|
||||
get => BlockEngine.GetBlockInfo<TimerBlockLabelCacheEntityStruct>(this).timeLastRenderFrameMS;
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.SetBlockInfo(this, (ref TimerBlockLabelCacheEntityStruct tbds, int val) => tbds.timeLastRenderFrameMS = val,
|
||||
value);
|
||||
BlockEngine.GetBlockInfo<TimerBlockLabelCacheEntityStruct>(this).timeLastRenderFrameMS = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
/// </summary>
|
||||
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<HealthEntityComponent>(Id).initialHealth;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).initialHealth = value;
|
||||
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).initialHealth;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).initialHealth = value;
|
||||
}
|
||||
|
||||
public float CurrentHealth
|
||||
{
|
||||
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).currentHealth;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).currentHealth = value;
|
||||
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).currentHealth;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).currentHealth = value;
|
||||
}
|
||||
|
||||
public float HealthMultiplier
|
||||
{
|
||||
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier = value;
|
||||
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).healthMultiplier;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).healthMultiplier = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Holds information needed to construct a component initializer
|
||||
/// </summary>
|
||||
internal struct BlockInitData
|
||||
protected internal struct EcsInitData
|
||||
{
|
||||
public FasterDictionary<RefWrapperType, ITypeSafeDictionary> Group;
|
||||
public EntityReference Reference;
|
||||
private FasterDictionary<RefWrapperType, ITypeSafeDictionary> 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<RefWrapperType, ITypeSafeDictionary> GetInitGroup(
|
||||
private delegate FasterDictionary<RefWrapperType, ITypeSafeDictionary> GetInitGroupFunc(
|
||||
EntityInitializer initializer);
|
||||
|
||||
/// <summary>
|
||||
/// Accesses the group field of the initializer
|
||||
/// </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
|
||||
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");
|
||||
if (invokeMethod == null)
|
|
@ -1,4 +1,5 @@
|
|||
using RobocraftX.Physics;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.EntityStructs;
|
||||
using Techblox.FlyCam;
|
||||
using TechbloxModdingAPI.Players;
|
||||
|
@ -8,13 +9,13 @@ using UnityEngine;
|
|||
|
||||
namespace TechbloxModdingAPI
|
||||
{
|
||||
public class FlyCam
|
||||
public class FlyCam : EcsObjectBase
|
||||
{
|
||||
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>
|
||||
/// The local player's camera.
|
||||
|
@ -26,11 +27,11 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float3 Position
|
||||
{
|
||||
get => Engine.GetComponent<PositionEntityStruct>(Id).Get().position;
|
||||
get => Engine.GetComponent<PositionEntityStruct>(this).position;
|
||||
set
|
||||
{
|
||||
Engine.GetComponent<PositionEntityStruct>(Id).Get().position = value;
|
||||
Engine.GetComponent<RigidBodyEntityStruct>(Id).Get().position = value;
|
||||
Engine.GetComponent<PositionEntityStruct>(this).position = value;
|
||||
Engine.GetComponent<RigidBodyEntityStruct>(this).position = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,11 +40,11 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float3 Rotation
|
||||
{
|
||||
get => ((Quaternion) Engine.GetComponent<RotationEntityStruct>(Id).Get().rotation).eulerAngles;
|
||||
get => ((Quaternion) Engine.GetComponent<RotationEntityStruct>(this).rotation).eulerAngles;
|
||||
set
|
||||
{
|
||||
Engine.GetComponent<RotationEntityStruct>(Id).Get().rotation = Quaternion.Euler(value);
|
||||
Engine.GetComponent<RigidBodyEntityStruct>(Id).Get().rotation = Quaternion.Euler(value);
|
||||
Engine.GetComponent<RotationEntityStruct>(this).rotation = Quaternion.Euler(value);
|
||||
Engine.GetComponent<RigidBodyEntityStruct>(this).rotation = Quaternion.Euler(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,8 +53,8 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float3 MovementDirection
|
||||
{
|
||||
get => Engine.GetComponent<FlyCamMovementComponent>(Id).Get().movementDirection;
|
||||
set => Engine.GetComponent<FlyCamMovementComponent>(Id).Get().movementDirection = value;
|
||||
get => Engine.GetComponent<FlyCamMovementComponent>(this).movementDirection;
|
||||
set => Engine.GetComponent<FlyCamMovementComponent>(this).movementDirection = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -61,8 +62,8 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public bool Sprinting
|
||||
{
|
||||
get => Engine.GetComponent<FlyCamMovementComponent>(Id).Get().sprinting;
|
||||
set => Engine.GetComponent<FlyCamMovementComponent>(Id).Get().sprinting = value;
|
||||
get => Engine.GetComponent<FlyCamMovementComponent>(this).sprinting;
|
||||
set => Engine.GetComponent<FlyCamMovementComponent>(this).sprinting = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -70,8 +71,8 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float Speed
|
||||
{
|
||||
get => Engine.GetComponent<FlyCamMovementSettingsComponent>(Id).Get().speed;
|
||||
set => Engine.GetComponent<FlyCamMovementSettingsComponent>(Id).Get().speed = value;
|
||||
get => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).speed;
|
||||
set => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).speed = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -79,8 +80,8 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float SpeedSprintMultiplier
|
||||
{
|
||||
get => Engine.GetComponent<FlyCamMovementSettingsComponent>(Id).Get().speedSprintMultiplier;
|
||||
set => Engine.GetComponent<FlyCamMovementSettingsComponent>(Id).Get().speedSprintMultiplier = value;
|
||||
get => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).speedSprintMultiplier;
|
||||
set => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).speedSprintMultiplier = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -88,8 +89,8 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float Acceleration
|
||||
{
|
||||
get => Engine.GetComponent<FlyCamMovementSettingsComponent>(Id).Get().acceleration;
|
||||
set => Engine.GetComponent<FlyCamMovementSettingsComponent>(Id).Get().acceleration = value;
|
||||
get => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).acceleration;
|
||||
set => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).acceleration = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -97,8 +98,8 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float3 Velocity
|
||||
{
|
||||
get => Engine.GetComponent<RigidBodyEntityStruct>(Id).Get().velocity;
|
||||
set => Engine.GetComponent<RigidBodyEntityStruct>(Id).Get().velocity = value;
|
||||
get => Engine.GetComponent<RigidBodyEntityStruct>(this).velocity;
|
||||
set => Engine.GetComponent<RigidBodyEntityStruct>(this).velocity = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -106,8 +107,8 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float3 AngularVelocity
|
||||
{
|
||||
get => Engine.GetComponent<RigidBodyEntityStruct>(Id).Get().angularVelocity;
|
||||
set => Engine.GetComponent<RigidBodyEntityStruct>(Id).Get().angularVelocity = value;
|
||||
get => Engine.GetComponent<RigidBodyEntityStruct>(this).angularVelocity;
|
||||
set => Engine.GetComponent<RigidBodyEntityStruct>(this).angularVelocity = value;
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using Svelto.ECS;
|
||||
using Techblox.FlyCam;
|
||||
using TechbloxModdingAPI.Engines;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Players
|
||||
{
|
||||
|
@ -18,11 +19,9 @@ namespace TechbloxModdingAPI.Players
|
|||
public string Name => "TechbloxModdingAPIFlyCamEngine";
|
||||
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 new OptionalRef<T>(array, index);
|
||||
return new OptionalRef<T>();
|
||||
return ref entitiesDB.QueryEntityOrDefault<T>(cam);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,9 +12,9 @@ namespace TechbloxModdingAPI
|
|||
/// <summary>
|
||||
/// A rigid body (like a chunk of connected blocks) during simulation.
|
||||
/// </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>
|
||||
/// 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<HealthEntityComponent>(Id).initialHealth;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).initialHealth = value;
|
||||
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).initialHealth;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).initialHealth = value;
|
||||
}
|
||||
|
||||
public float CurrentHealth
|
||||
{
|
||||
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).currentHealth;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).currentHealth = value;
|
||||
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).currentHealth;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).currentHealth = value;
|
||||
}
|
||||
|
||||
public float HealthMultiplier
|
||||
{
|
||||
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier = value;
|
||||
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).healthMultiplier;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).healthMultiplier = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the body can be moved or static.
|
||||
/// </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>
|
||||
/// 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<RigidBodyEntityStruct>(Id);
|
||||
return ref Block.BlockEngine.GetBlockInfo<RigidBodyEntityStruct>(this);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
|
|
@ -487,9 +487,9 @@
|
|||
<HintPath>..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.Inventory.dll</HintPath>
|
||||
<HintPath>..\..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.Inventory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.GUI.RemoveBlock">
|
||||
<HintPath>..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.RemoveBlock.dll</HintPath>
|
||||
<HintPath>..\..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.RemoveBlock.dll</HintPath>
|
||||
<Reference Include="RobocraftX.GUI.PauseMenu">
|
||||
<HintPath>..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.PauseMenu.dll</HintPath>
|
||||
<HintPath>..\..\ref\TechbloxPreview_Data\Managed\RobocraftX.GUI.PauseMenu.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.GUI.ScaleGhost">
|
||||
<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>
|
||||
</Reference>
|
||||
<Reference Include="Techblox.MouseCursor">
|
||||
<HintPath>..\ref\TechbloxPreview_Data\Managed\Techblox.MouseCursor.dll</HintPath>
|
||||
<HintPath>..\..\ref\TechbloxPreview_Data\Managed\Techblox.MouseCursor.dll</HintPath>
|
||||
<Reference Include="Techblox.Pointer">
|
||||
<HintPath>..\ref\TechbloxPreview_Data\Managed\Techblox.Pointer.dll</HintPath>
|
||||
<HintPath>..\..\ref\TechbloxPreview_Data\Managed\Techblox.Pointer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Techblox.SwitchAnimation">
|
||||
<HintPath>..\ref\TechbloxPreview_Data\Managed\Techblox.SwitchAnimation.dll</HintPath>
|
||||
|
|
55
TechbloxModdingAPI/Utility/ManagedApiExtensions.cs
Normal file
55
TechbloxModdingAPI/Utility/ManagedApiExtensions.cs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
53
TechbloxModdingAPI/Utility/NativeApiExtensions.cs
Normal file
53
TechbloxModdingAPI/Utility/NativeApiExtensions.cs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,60 +1,93 @@
|
|||
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 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 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)
|
||||
{
|
||||
exists = true;
|
||||
state = State.Native;
|
||||
this.array = array;
|
||||
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;
|
||||
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)
|
||||
return ref array[index];
|
||||
return ref CompRefCache<T>._default;
|
||||
if (state == State.Empty) return ref CompRefCache.Default;
|
||||
if ((state & State.Initializer) != State.Empty) return ref initializer.GetOrCreate<T>();
|
||||
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 bool(OptionalRef<T> opt) => opt.exists;
|
||||
|
||||
/*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>();*/
|
||||
public static implicit operator bool(OptionalRef<T> opt) => opt.state != State.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of a struct T that can be referenced.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The struct type to cache</typeparam>
|
||||
private struct CompRefCache<T> where T : unmanaged
|
||||
internal struct CompRefCache
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue