@@ -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 | |||
} | |||
public U GetBlockInfo<T, U>(Block block, Func<T, U> getter, | |||
U def = default) 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 entitiesDB.QueryEntityOptional<T>(block); | |||
} | |||
private U GetBlockInitInfo<T, U>(Block block, Func<T, U> getter, U def) where T : struct, IEntityComponent | |||
public ref T GetBlockInfo<T>(Block block) 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>(block); | |||
} | |||
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 | |||
internal ref T GetBlockInfo<T>(EcsObjectBase obj) where T : unmanaged, IEntityComponent | |||
{ | |||
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); | |||
return ref entitiesDB.QueryEntityOrDefault<T>(obj); | |||
} | |||
private void SetBlockInitInfo<T, U>(Block block, Setter<T, U> setter, U value) | |||
where T : struct, IEntityComponent | |||
public ref T GetBlockInfoViewComponent<T>(Block block) where T : struct, IEntityViewComponent | |||
{ | |||
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> | |||
@@ -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 | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
/// <summary> | |||
/// A byte that holds state in its bits. | |||
/// </summary> | |||
[Flags] | |||
private enum State : byte | |||
{ | |||
public static T _default; | |||
Empty, | |||
Native, | |||
Managed, | |||
Initializer = 4 | |||
} | |||
} | |||
} |