From 858a5c9b5c4c8494b562548194ac4bf5bff3aa75 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Tue, 11 May 2021 00:56:46 +0200 Subject: [PATCH] Fix remaining errors, add support for managed entity DB --- TechbloxModdingAPI/Block.cs | 77 +++++----- TechbloxModdingAPI/Blocks/BlockEngine.cs | 10 ++ TechbloxModdingAPI/Blocks/DampedSpring.cs | 9 +- TechbloxModdingAPI/Blocks/MusicBlock.cs | 88 +++++------ TechbloxModdingAPI/Blocks/ObjectIdentifier.cs | 9 +- TechbloxModdingAPI/Blocks/SfxBlock.cs | 137 +++++++++--------- TechbloxModdingAPI/Blocks/SignalingBlock.cs | 1 - TechbloxModdingAPI/Blocks/TextBlock.cs | 11 +- TechbloxModdingAPI/Cluster.cs | 16 +- TechbloxModdingAPI/Players/FlyCamEngine.cs | 1 + TechbloxModdingAPI/SimBody.cs | 20 +-- .../Utility/ManagedApiExtensions.cs | 55 +++++++ ...piExtensions.cs => NativeApiExtensions.cs} | 5 +- TechbloxModdingAPI/Utility/OptionalRef.cs | 76 ++++++---- 14 files changed, 282 insertions(+), 233 deletions(-) create mode 100644 TechbloxModdingAPI/Utility/ManagedApiExtensions.cs rename TechbloxModdingAPI/Utility/{ApiExtensions.cs => NativeApiExtensions.cs} (92%) diff --git a/TechbloxModdingAPI/Block.cs b/TechbloxModdingAPI/Block.cs index b2d400d..5181723 100644 --- a/TechbloxModdingAPI/Block.cs +++ b/TechbloxModdingAPI/Block.cs @@ -322,13 +322,9 @@ namespace TechbloxModdingAPI get => BlockEngine.GetBlockInfo(this).scale.x < 0; set { - BlockEngine.SetBlockInfo(this, (ref ScalingEntityStruct st, bool val) => - st.scale.x = math.abs(st.scale.x) * (val ? -1 : 1), value); - BlockEngine.SetBlockInfo(this, (ref GFXPrefabEntityStructGPUI st, bool val) => - { - uint prefabId = PrefabsID.GetOrCreatePrefabID((ushort) Type, (byte) Material, 0, value); - st.prefabID = prefabId; - }, value); + var st = BlockEngine.GetBlockInfo(this); + st.scale.x = math.abs(st.scale.x) * (value ? -1 : 1); + BlockEngine.UpdatePrefab(this, (ushort) Type, (byte) Material, value); } } @@ -339,7 +335,8 @@ namespace TechbloxModdingAPI { get { - return BlockEngine.GetBlockInfo(this, (DBEntityStruct st) => (BlockIDs) st.DBID, BlockIDs.Invalid); + var opt = BlockEngine.GetBlockInfoOptional(this); + return opt ? (BlockIDs) opt.Get().DBID : BlockIDs.Invalid; } } @@ -350,18 +347,16 @@ namespace TechbloxModdingAPI { get { - byte index = BlockEngine.GetBlockInfo(this, (ColourParameterEntityStruct st) => st.indexInPalette, - byte.MaxValue); - return new BlockColor(index); + var opt = BlockEngine.GetBlockInfoOptional(this); + return new BlockColor(opt ? opt.Get().indexInPalette : byte.MaxValue); } set { - BlockEngine.SetBlockInfo(this, (ref ColourParameterEntityStruct color, BlockColor val) => - { //TODO: Check if setting to 255 works - color.indexInPalette = val.Index; - color.hasNetworkChange = true; - color.paletteColour = BlockEngine.ConvertBlockColor(color.indexInPalette); - }, value); + //TODO: Check if setting to 255 works + var color = BlockEngine.GetBlockInfo(this); + color.indexInPalette = value.Index; + color.hasNetworkChange = true; + color.paletteColour = BlockEngine.ConvertBlockColor(color.indexInPalette); } } @@ -373,11 +368,9 @@ namespace TechbloxModdingAPI get => BlockEngine.GetBlockInfo(this).paletteColour; set { - BlockEngine.SetBlockInfo(this, (ref ColourParameterEntityStruct color, float4 val) => - { - color.paletteColour = val; - color.hasNetworkChange = true; - }, value); + ref var color = ref BlockEngine.GetBlockInfo(this); + color.paletteColour = value; + color.hasNetworkChange = true; } } @@ -386,9 +379,16 @@ namespace TechbloxModdingAPI */ public BlockMaterial Material { - get => BlockEngine.GetBlockInfo(this, (CubeMaterialStruct cmst) => (BlockMaterial) cmst.materialId, BlockMaterial.Default); - set => BlockEngine.SetBlockInfo(this, - (ref CubeMaterialStruct cmst, BlockMaterial val) => cmst.materialId = (byte) val, value); + get + { + var opt = BlockEngine.GetBlockInfoOptional(this); + return opt ? (BlockMaterial) opt.Get().materialId : BlockMaterial.Default; + } + set + { + BlockEngine.GetBlockInfo(this).materialId = (byte) value; + BlockEngine.UpdatePrefab(this, (ushort) Type, (byte) value, Flipped); //TODO: Test default + } } /// @@ -397,13 +397,11 @@ namespace TechbloxModdingAPI /// public string Label { - get => BlockEngine.GetBlockInfoViewStruct(this, (TextLabelEntityViewStruct st) => st.textLabelComponent?.text); + get => BlockEngine.GetBlockInfoViewComponent(this).textLabelComponent?.text; set { - BlockEngine.SetBlockInfoViewStruct(this, (ref TextLabelEntityViewStruct text, string val) => - { - if (text.textLabelComponent != null) text.textLabelComponent.text = val; - }, value); + var comp = BlockEngine.GetBlockInfoViewComponent(this).textLabelComponent; + if (comp != null) comp.text = value; } } @@ -421,9 +419,8 @@ namespace TechbloxModdingAPI get { if (blockGroup != null) return blockGroup; - return blockGroup = BlockEngine.GetBlockInfo(this, - (BlockGroupEntityComponent bgec) => - bgec.currentBlockGroup == -1 ? null : new BlockGroup(bgec.currentBlockGroup, this)); + var bgec = BlockEngine.GetBlockInfo(this); + return blockGroup = bgec.currentBlockGroup == -1 ? null : new BlockGroup(bgec.currentBlockGroup, this); } set { @@ -434,9 +431,7 @@ namespace TechbloxModdingAPI return; } blockGroup?.RemoveInternal(this); - BlockEngine.SetBlockInfo(this, - (ref BlockGroupEntityComponent bgec, BlockGroup val) => bgec.currentBlockGroup = val?.Id ?? -1, - value); + BlockEngine.GetBlockInfo(this).currentBlockGroup = value?.Id ?? -1; value?.AddInternal(this); blockGroup = value; } @@ -466,10 +461,10 @@ namespace TechbloxModdingAPI /// The SimBody of the chunk or null if the block doesn't exist or not in simulation mode. public SimBody GetSimBody() { - return BlockEngine.GetBlockInfo(this, - (GridConnectionsEntityStruct st) => st.machineRigidBodyId != uint.MaxValue - ? new SimBody(st.machineRigidBodyId, st.clusterId) - : null); + var st = BlockEngine.GetBlockInfo(this); + return st.machineRigidBodyId != uint.MaxValue + ? new SimBody(st.machineRigidBodyId, st.clusterId) + : null; } /// @@ -555,7 +550,7 @@ namespace TechbloxModdingAPI //Lets improve that using delegates var block = New(Id.entityID, Id.groupID); - if (this.InitData.Group != null) + if (this.InitData.Valid) { block.InitData = this.InitData; Placed += block.OnPlacedInit; //Reset InitData of new object diff --git a/TechbloxModdingAPI/Blocks/BlockEngine.cs b/TechbloxModdingAPI/Blocks/BlockEngine.cs index 80e14f3..c23ee8d 100644 --- a/TechbloxModdingAPI/Blocks/BlockEngine.cs +++ b/TechbloxModdingAPI/Blocks/BlockEngine.cs @@ -80,6 +80,16 @@ namespace TechbloxModdingAPI.Blocks return ref entitiesDB.QueryEntityOrDefault(block); } + internal ref T GetBlockInfo(EcsObjectBase obj) where T : unmanaged, IEntityComponent + { + return ref entitiesDB.QueryEntityOrDefault(obj); + } + + public ref T GetBlockInfoViewComponent(Block block) where T : struct, IEntityViewComponent + { + return ref entitiesDB.QueryEntityOrDefault(block); + } + public void UpdateDisplayedBlock(EGID id) { if (!BlockExists(id)) return; diff --git a/TechbloxModdingAPI/Blocks/DampedSpring.cs b/TechbloxModdingAPI/Blocks/DampedSpring.cs index 3c92f72..4623d6d 100644 --- a/TechbloxModdingAPI/Blocks/DampedSpring.cs +++ b/TechbloxModdingAPI/Blocks/DampedSpring.cs @@ -21,8 +21,7 @@ namespace TechbloxModdingAPI.Blocks { get => BlockEngine.GetBlockInfo(this).springFrequency; - set => BlockEngine.SetBlockInfo(this, - (ref DampedSpringReadOnlyStruct dsrs, float val) => dsrs.springFrequency = val, value); + set => BlockEngine.GetBlockInfo(this).springFrequency = value; } /// @@ -41,8 +40,7 @@ namespace TechbloxModdingAPI.Blocks { get => BlockEngine.GetBlockInfo(this).springDamping; - set => BlockEngine.SetBlockInfo(this, - (ref DampedSpringReadOnlyStruct ljf, float val) => ljf.springDamping = val, value); + set => BlockEngine.GetBlockInfo(this).springDamping = value; } /// @@ -52,8 +50,7 @@ namespace TechbloxModdingAPI.Blocks { get => BlockEngine.GetBlockInfo(this).maxExtent; - set => BlockEngine.SetBlockInfo(this, - (ref DampedSpringReadOnlyStruct ljf, float val) => ljf.maxExtent = val, value); + set => BlockEngine.GetBlockInfo(this).maxExtent = value; } } } \ No newline at end of file diff --git a/TechbloxModdingAPI/Blocks/MusicBlock.cs b/TechbloxModdingAPI/Blocks/MusicBlock.cs index ea4aeca..51e96ee 100644 --- a/TechbloxModdingAPI/Blocks/MusicBlock.cs +++ b/TechbloxModdingAPI/Blocks/MusicBlock.cs @@ -33,8 +33,7 @@ namespace TechbloxModdingAPI.Blocks set { - BlockEngine.SetBlockInfo(this, - (ref MusicBlockDataEntityStruct msdes, byte val) => msdes.trackIndx = val, value); + BlockEngine.GetBlockInfo(this).trackIndx = value; } } @@ -42,24 +41,22 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, - (MusicBlockDataEntityStruct msdes) => msdes.fmod2DEventPaths.Get(msdes.trackIndx)); + var msdes = BlockEngine.GetBlockInfo(this); + return msdes.fmod2DEventPaths.Get(msdes.trackIndx); } set { - BlockEngine.SetBlockInfo(this, (ref MusicBlockDataEntityStruct msdes, Guid val) => + ref var msdes = ref BlockEngine.GetBlockInfo(this); + for (byte i = 0; i < msdes.fmod2DEventPaths.Count(); i++) { - for (byte i = 0; i < msdes.fmod2DEventPaths.Count(); i++) + Guid track = msdes.fmod2DEventPaths.Get(i); + if (track == value) { - Guid track = msdes.fmod2DEventPaths.Get(i); - if (track == val) - { - msdes.trackIndx = i; - break; - } + msdes.trackIndx = i; + break; } - }, value); + } } } @@ -67,15 +64,13 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (MusicBlockDataEntityStruct msdes) => + var msdes = BlockEngine.GetBlockInfo(this); + Guid[] tracks = new Guid[msdes.fmod2DEventPaths.Count()]; + for (byte i = 0; i < tracks.Length; i++) { - Guid[] tracks = new Guid[msdes.fmod2DEventPaths.Count()]; - for (byte i = 0; i < tracks.Length; i++) - { - tracks[i] = msdes.fmod2DEventPaths.Get(i); - } - return tracks; - }); + tracks[i] = msdes.fmod2DEventPaths.Get(i); + } + return tracks; } } @@ -88,8 +83,7 @@ namespace TechbloxModdingAPI.Blocks set { - BlockEngine.SetBlockInfo(this, - (ref MusicBlockDataEntityStruct msdes, float val) => msdes.tweakableVolume = val, value); + BlockEngine.GetBlockInfo(this).tweakableVolume = value; } } @@ -98,14 +92,12 @@ namespace TechbloxModdingAPI.Blocks get { //Assert.Log("Block exists: " + Exists); - return BlockEngine.GetBlockInfo(this, - (MusicBlockDataEntityStruct msdes) => (ChannelType) msdes.channelType); + return (ChannelType) BlockEngine.GetBlockInfo(this).channelType; } set { - BlockEngine.SetBlockInfo(this, - (ref MusicBlockDataEntityStruct msdes, ChannelType val) => msdes.channelType = (byte) val, value); + BlockEngine.GetBlockInfo(this).channelType = (byte) value; } } @@ -113,33 +105,31 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, - (MusicBlockDataEntityStruct msdes) => msdes.isPlaying); + return BlockEngine.GetBlockInfo(this).isPlaying; } set { - BlockEngine.SetBlockInfo(this, (ref MusicBlockDataEntityStruct msdes, bool val) => + ref var msdes = ref BlockEngine.GetBlockInfo(this); + if (msdes.isPlaying == value) return; + if (value) { - if (msdes.isPlaying == val) return; - if (val) - { - // start playing - EventInstance inst = RuntimeManager.CreateInstance(msdes.fmod2DEventPaths.Get(msdes.trackIndx)); - inst.setVolume(msdes.tweakableVolume / 100f); - inst.start(); - msdes.eventHandle = inst.handle; - } - else - { - // stop playing - EventInstance inst = default(EventInstance); - inst.handle = msdes.eventHandle; - inst.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); - inst.release(); - } - msdes.isPlaying = val; - }, value); + // start playing + EventInstance inst = RuntimeManager.CreateInstance(msdes.fmod2DEventPaths.Get(msdes.trackIndx)); + inst.setVolume(msdes.tweakableVolume / 100f); + inst.start(); + msdes.eventHandle = inst.handle; + } + else + { + // stop playing + EventInstance inst = default(EventInstance); + inst.handle = msdes.eventHandle; + inst.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); + inst.release(); + } + + msdes.isPlaying = value; } } } diff --git a/TechbloxModdingAPI/Blocks/ObjectIdentifier.cs b/TechbloxModdingAPI/Blocks/ObjectIdentifier.cs index fe2d657..046054b 100644 --- a/TechbloxModdingAPI/Blocks/ObjectIdentifier.cs +++ b/TechbloxModdingAPI/Blocks/ObjectIdentifier.cs @@ -16,14 +16,11 @@ namespace TechbloxModdingAPI.Blocks public char Identifier { - get => (char) BlockEngine.GetBlockInfo(this).objectId + 'A'; + get => (char) (BlockEngine.GetBlockInfo(this).objectId + 'A'); set { - BlockEngine.SetBlockInfo(this, (ref ObjectIdEntityStruct st, char val) => - { - st.objectId = (byte) (val - 'A'); - Label = val + ""; //The label isn't updated automatically - }, value); + BlockEngine.GetBlockInfo(this).objectId = (byte) (value - 'A'); + Label = value + ""; //The label isn't updated automatically } } diff --git a/TechbloxModdingAPI/Blocks/SfxBlock.cs b/TechbloxModdingAPI/Blocks/SfxBlock.cs index 45453fb..6b6ab36 100644 --- a/TechbloxModdingAPI/Blocks/SfxBlock.cs +++ b/TechbloxModdingAPI/Blocks/SfxBlock.cs @@ -27,8 +27,7 @@ namespace TechbloxModdingAPI.Blocks set { - BlockEngine.SetBlockInfo(this, - (ref SoundSfxBlockDataEntityStruct obj, float val) => obj.tweakableVolume = val, value); + BlockEngine.GetBlockInfo(this).tweakableVolume = value; } } @@ -41,8 +40,7 @@ namespace TechbloxModdingAPI.Blocks set { - BlockEngine.SetBlockInfo(this, - (ref SoundSfxBlockDataEntityStruct obj, float val) => obj.tweakablePitch = val, value); + BlockEngine.GetBlockInfo(this).tweakablePitch = value; } } @@ -55,8 +53,7 @@ namespace TechbloxModdingAPI.Blocks set { - BlockEngine.SetBlockInfo(this, - (ref SoundSfxBlockDataEntityStruct obj, bool val) => obj.is3D = val, value); + BlockEngine.GetBlockInfo(this).is3D = value; } } @@ -64,13 +61,12 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => (ChannelType)obj.channelType); + return (ChannelType) BlockEngine.GetBlockInfo(this).channelType; } set { - BlockEngine.SetBlockInfo(this, - (ref SoundSfxBlockDataEntityStruct obj, ChannelType val) => obj.tweakableVolume = (byte) val, value); + BlockEngine.GetBlockInfo(this).channelType = (byte) value; } } @@ -83,8 +79,7 @@ namespace TechbloxModdingAPI.Blocks set { - BlockEngine.SetBlockInfo(this, - (ref SoundSfxBlockDataEntityStruct obj, byte val) => obj.soundEffectIndex = val, value); + BlockEngine.GetBlockInfo(this).soundEffectIndex = value; } } @@ -93,35 +88,36 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, - (SoundSfxBlockDataEntityStruct obj) => obj.is3D ? obj.fmod3DEventPaths.Get(obj.soundEffectIndex) : obj.fmod2DEventPaths.Get(obj.soundEffectIndex)); + var obj = BlockEngine.GetBlockInfo(this); + return obj.is3D + ? obj.fmod3DEventPaths.Get(obj.soundEffectIndex) + : obj.fmod2DEventPaths.Get(obj.soundEffectIndex); } set { - BlockEngine.SetBlockInfo(this, (ref SoundSfxBlockDataEntityStruct obj, Guid val) => + var obj = BlockEngine.GetBlockInfo(this); + for (byte i = 0; i < obj.fmod2DEventPaths.Count(); i++) { - for (byte i = 0; i < obj.fmod2DEventPaths.Count(); i++) + Guid track = obj.fmod2DEventPaths.Get(i); + if (track == value) { - Guid track = obj.fmod2DEventPaths.Get(i); - if (track == val) - { - obj.soundEffectIndex = i; - obj.is3D = false; - return; - } + obj.soundEffectIndex = i; + obj.is3D = false; + return; } - for (byte i = 0; i < obj.fmod3DEventPaths.Count(); i++) + } + + for (byte i = 0; i < obj.fmod3DEventPaths.Count(); i++) + { + Guid track = obj.fmod3DEventPaths.Get(i); + if (track == value) { - Guid track = obj.fmod3DEventPaths.Get(i); - if (track == val) - { - obj.soundEffectIndex = i; - obj.is3D = true; - return; - } + obj.soundEffectIndex = i; + obj.is3D = true; + return; } - }, value); + } } } @@ -130,31 +126,29 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => + var obj = BlockEngine.GetBlockInfo(this); + Guid[] tracks = new Guid[obj.fmod2DEventPaths.Count()]; + for (byte i = 0; i < tracks.Length; i++) { - Guid[] tracks = new Guid[obj.fmod2DEventPaths.Count()]; - for (byte i = 0; i < tracks.Length; i++) - { - tracks[i] = obj.fmod2DEventPaths.Get(i); - } - return tracks; - }); + tracks[i] = obj.fmod2DEventPaths.Get(i); + } + + return tracks; } } - + public Guid[] Tracks3D { get { - return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => + var obj = BlockEngine.GetBlockInfo(this); + Guid[] tracks = new Guid[obj.fmod3DEventPaths.Count()]; + for (byte i = 0; i < tracks.Length; i++) { - Guid[] tracks = new Guid[obj.fmod3DEventPaths.Count()]; - for (byte i = 0; i < tracks.Length; i++) - { - tracks[i] = obj.fmod2DEventPaths.Get(i); - } - return tracks; - }); + tracks[i] = obj.fmod2DEventPaths.Get(i); + } + + return tracks; } } @@ -167,8 +161,7 @@ namespace TechbloxModdingAPI.Blocks set { - BlockEngine.SetBlockInfo(this, - (ref SoundSfxBlockDataEntityStruct obj, bool val) => obj.isLoopedBlock = val, value); + BlockEngine.GetBlockInfo(this).isLoopedBlock = value; } } @@ -176,33 +169,33 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this, - (SoundSfxBlockDataEntityStruct obj) => obj.isPlaying); + return BlockEngine.GetBlockInfo(this).isPlaying; } set { - BlockEngine.SetBlockInfo(this, (ref SoundSfxBlockDataEntityStruct obj, bool val) => + var obj = BlockEngine.GetBlockInfo(this); + if (obj.isPlaying == value) return; + if (value) { - if (obj.isPlaying == val) return; - if (val) - { - // start playing - EventInstance inst = RuntimeManager.CreateInstance(obj.is3D ? obj.fmod3DEventPaths.Get(obj.soundEffectIndex) : obj.fmod2DEventPaths.Get(obj.soundEffectIndex)); - inst.setVolume(obj.tweakableVolume / 100f); - inst.start(); - obj.eventHandle = inst.handle; - } - else - { - // stop playing - EventInstance inst = default(EventInstance); - inst.handle = obj.eventHandle; - inst.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); - inst.release(); - } - obj.isPlaying = val; - }, value); + // start playing + EventInstance inst = RuntimeManager.CreateInstance(obj.is3D + ? obj.fmod3DEventPaths.Get(obj.soundEffectIndex) + : obj.fmod2DEventPaths.Get(obj.soundEffectIndex)); + inst.setVolume(obj.tweakableVolume / 100f); + inst.start(); + obj.eventHandle = inst.handle; + } + else + { + // stop playing + EventInstance inst = default(EventInstance); + inst.handle = obj.eventHandle; + inst.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); + inst.release(); + } + + obj.isPlaying = value; } } } diff --git a/TechbloxModdingAPI/Blocks/SignalingBlock.cs b/TechbloxModdingAPI/Blocks/SignalingBlock.cs index 293e00d..45b5aa6 100644 --- a/TechbloxModdingAPI/Blocks/SignalingBlock.cs +++ b/TechbloxModdingAPI/Blocks/SignalingBlock.cs @@ -109,7 +109,6 @@ namespace TechbloxModdingAPI.Blocks /// The localized port name. public string PortName(byte port, bool input) { - BlockPortsStruct bps = BlockEngine.GetBlockInfo(this, (BlockPortsStruct a) => a); PortEntityStruct pes = SignalEngine.GetPortByOffset(this, port, input); return pes.portNameLocalised; } diff --git a/TechbloxModdingAPI/Blocks/TextBlock.cs b/TechbloxModdingAPI/Blocks/TextBlock.cs index c3ee1b0..99c753a 100644 --- a/TechbloxModdingAPI/Blocks/TextBlock.cs +++ b/TechbloxModdingAPI/Blocks/TextBlock.cs @@ -32,11 +32,9 @@ namespace TechbloxModdingAPI.Blocks set { if (value == null) value = ""; - BlockEngine.SetBlockInfo(this, (ref TextBlockDataStruct tbds, string val) => - { - tbds.textCurrent.Set(val); - tbds.textStored.Set(val, true); - }, value); + var tbds = BlockEngine.GetBlockInfo(this); + tbds.textCurrent.Set(value); + tbds.textStored.Set(value, true); } } @@ -50,8 +48,7 @@ namespace TechbloxModdingAPI.Blocks set { if (value == null) value = ""; - BlockEngine.SetBlockInfo(this, (ref TextBlockDataStruct tbds, string val) => - tbds.textBlockID.Set(val), value); + BlockEngine.GetBlockInfo(this).textBlockID.Set(value); } } } diff --git a/TechbloxModdingAPI/Cluster.cs b/TechbloxModdingAPI/Cluster.cs index 11b995c..2544194 100644 --- a/TechbloxModdingAPI/Cluster.cs +++ b/TechbloxModdingAPI/Cluster.cs @@ -8,9 +8,9 @@ namespace TechbloxModdingAPI /// Represnts a cluster of blocks in time running mode, meaning blocks that are connected either directly or via joints. /// Only exists if a cluster destruction manager is present. Static blocks like grass and dirt aren't part of a cluster. /// - public class Cluster + public class Cluster : EcsObjectBase { - public EGID Id { get; } + public override EGID Id { get; } public Cluster(EGID id) { @@ -23,20 +23,20 @@ namespace TechbloxModdingAPI public float InitialHealth { - get => Block.BlockEngine.GetBlockInfo(Id).initialHealth; - set => Block.BlockEngine.GetBlockInfo(Id).initialHealth = value; + get => Block.BlockEngine.GetBlockInfo(this).initialHealth; + set => Block.BlockEngine.GetBlockInfo(this).initialHealth = value; } public float CurrentHealth { - get => Block.BlockEngine.GetBlockInfo(Id).currentHealth; - set => Block.BlockEngine.GetBlockInfo(Id).currentHealth = value; + get => Block.BlockEngine.GetBlockInfo(this).currentHealth; + set => Block.BlockEngine.GetBlockInfo(this).currentHealth = value; } public float HealthMultiplier { - get => Block.BlockEngine.GetBlockInfo(Id).healthMultiplier; - set => Block.BlockEngine.GetBlockInfo(Id).healthMultiplier = value; + get => Block.BlockEngine.GetBlockInfo(this).healthMultiplier; + set => Block.BlockEngine.GetBlockInfo(this).healthMultiplier = value; } /// diff --git a/TechbloxModdingAPI/Players/FlyCamEngine.cs b/TechbloxModdingAPI/Players/FlyCamEngine.cs index 0b98071..cd52363 100644 --- a/TechbloxModdingAPI/Players/FlyCamEngine.cs +++ b/TechbloxModdingAPI/Players/FlyCamEngine.cs @@ -1,6 +1,7 @@ using Svelto.ECS; using Techblox.FlyCam; using TechbloxModdingAPI.Engines; +using TechbloxModdingAPI.Utility; namespace TechbloxModdingAPI.Players { diff --git a/TechbloxModdingAPI/SimBody.cs b/TechbloxModdingAPI/SimBody.cs index dd7429e..55c6a9e 100644 --- a/TechbloxModdingAPI/SimBody.cs +++ b/TechbloxModdingAPI/SimBody.cs @@ -12,9 +12,9 @@ namespace TechbloxModdingAPI /// /// A rigid body (like a chunk of connected blocks) during simulation. /// - public class SimBody : IEquatable, IEquatable + public class SimBody : EcsObjectBase, IEquatable, IEquatable { - public EGID Id { get; } + public override EGID Id { get; } /// /// The cluster this chunk belongs to, or null if no cluster destruction manager present or the chunk doesn't exist. @@ -92,26 +92,26 @@ namespace TechbloxModdingAPI public float InitialHealth { - get => Block.BlockEngine.GetBlockInfo(Id).initialHealth; - set => Block.BlockEngine.GetBlockInfo(Id).initialHealth = value; + get => Block.BlockEngine.GetBlockInfo(this).initialHealth; + set => Block.BlockEngine.GetBlockInfo(this).initialHealth = value; } public float CurrentHealth { - get => Block.BlockEngine.GetBlockInfo(Id).currentHealth; - set => Block.BlockEngine.GetBlockInfo(Id).currentHealth = value; + get => Block.BlockEngine.GetBlockInfo(this).currentHealth; + set => Block.BlockEngine.GetBlockInfo(this).currentHealth = value; } public float HealthMultiplier { - get => Block.BlockEngine.GetBlockInfo(Id).healthMultiplier; - set => Block.BlockEngine.GetBlockInfo(Id).healthMultiplier = value; + get => Block.BlockEngine.GetBlockInfo(this).healthMultiplier; + set => Block.BlockEngine.GetBlockInfo(this).healthMultiplier = value; } /// /// Whether the body can be moved or static. /// - public bool Static => Block.BlockEngine.GetBlockInfo(Id).isStatic; //Setting it doesn't have any effect + public bool Static => Block.BlockEngine.GetBlockInfo(this).isStatic; //Setting it doesn't have any effect /// /// The rigid bodies connected to this one via functional joints (broken ones don't count). @@ -132,7 +132,7 @@ namespace TechbloxModdingAPI private ref RigidBodyEntityStruct GetStruct() { - return ref Block.BlockEngine.GetBlockInfo(Id); + return ref Block.BlockEngine.GetBlockInfo(this); } public override string ToString() diff --git a/TechbloxModdingAPI/Utility/ManagedApiExtensions.cs b/TechbloxModdingAPI/Utility/ManagedApiExtensions.cs new file mode 100644 index 0000000..2616ab7 --- /dev/null +++ b/TechbloxModdingAPI/Utility/ManagedApiExtensions.cs @@ -0,0 +1,55 @@ +using Svelto.ECS; +using Svelto.ECS.Hybrid; +using TechbloxModdingAPI.Blocks; + +namespace TechbloxModdingAPI.Utility +{ + public static class ManagedApiExtensions + { + /// + /// Attempts to query an entity and returns an optional that contains the result if succeeded. + /// This overload does not take initializer data into account. + /// + /// The entities DB + /// The EGID to query + /// The component type to query + /// An optional that contains the result on success or is empty if not found + public static OptionalRef QueryEntityOptional(this EntitiesDB entitiesDB, EGID egid) + where T : struct, IEntityViewComponent + { + return entitiesDB.TryQueryEntitiesAndIndex(egid, out uint index, out var array) + ? new OptionalRef(array, index) + : new OptionalRef(); + } + + /// + /// Attempts to query an entity and returns the result or a dummy value that can be modified. + /// + /// + /// + /// + /// + public static OptionalRef QueryEntityOptional(this EntitiesDB entitiesDB, EcsObjectBase obj) + where T : struct, IEntityViewComponent + { + var opt = QueryEntityOptional(entitiesDB, obj.Id); + return opt ? opt : new OptionalRef(obj, true); + } + + /// + /// Attempts to query an entity and returns the result or a dummy value that can be modified. + /// + /// + /// + /// + /// + public static ref T QueryEntityOrDefault(this EntitiesDB entitiesDB, EcsObjectBase obj) + where T : struct, IEntityViewComponent + { + var opt = QueryEntityOptional(entitiesDB, obj.Id); + if (opt) return ref opt.Get(); + if (obj.InitData.Valid) return ref obj.InitData.Initializer(obj.Id).GetOrCreate(); + return ref opt.Get(); //Default value + } + } +} \ No newline at end of file diff --git a/TechbloxModdingAPI/Utility/ApiExtensions.cs b/TechbloxModdingAPI/Utility/NativeApiExtensions.cs similarity index 92% rename from TechbloxModdingAPI/Utility/ApiExtensions.cs rename to TechbloxModdingAPI/Utility/NativeApiExtensions.cs index 3da1a67..701e42f 100644 --- a/TechbloxModdingAPI/Utility/ApiExtensions.cs +++ b/TechbloxModdingAPI/Utility/NativeApiExtensions.cs @@ -3,10 +3,11 @@ using TechbloxModdingAPI.Blocks; namespace TechbloxModdingAPI.Utility { - public static class ApiExtensions + public static class NativeApiExtensions { /// /// Attempts to query an entity and returns an optional that contains the result if succeeded. + /// This overload does not take initializer data into account. /// /// The entities DB /// The EGID to query @@ -31,7 +32,7 @@ namespace TechbloxModdingAPI.Utility where T : unmanaged, IEntityComponent { var opt = QueryEntityOptional(entitiesDB, obj.Id); - return opt ? opt : new OptionalRef(obj); + return opt ? opt : new OptionalRef(obj, true); } /// diff --git a/TechbloxModdingAPI/Utility/OptionalRef.cs b/TechbloxModdingAPI/Utility/OptionalRef.cs index 2323431..c5cfb83 100644 --- a/TechbloxModdingAPI/Utility/OptionalRef.cs +++ b/TechbloxModdingAPI/Utility/OptionalRef.cs @@ -1,44 +1,53 @@ using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using TechbloxModdingAPI.Blocks; +using System.Runtime.InteropServices; using Svelto.DataStructures; using Svelto.ECS; -namespace TechbloxModdingAPI +namespace TechbloxModdingAPI.Utility { - public ref struct OptionalRef where T : unmanaged, IEntityComponent + [StructLayout(LayoutKind.Explicit)] //Make the array and managedArray fields take up the same space + public ref struct OptionalRef where T : struct, IEntityComponent { - private bool exists; - private NB array; - private uint index; - private EntityInitializer initializer; + [FieldOffset(0)] private readonly State state; + [FieldOffset(1)] private readonly uint index; + [FieldOffset(5)] private NB array; + [FieldOffset(5)] private MB managedArray; + [FieldOffset(1)] private readonly EntityInitializer initializer; + //The possible fields are: (index && (array || managedArray)) || initializer public OptionalRef(NB array, uint index) { - exists = true; + state = State.Native; this.array = array; this.index = index; initializer = default; } - + + public OptionalRef(MB array, uint index) + { + state = State.Managed; + managedArray = array; + this.index = index; + initializer = default; + this.array = default; + } + /// /// Wraps the initializer data, if present. /// /// The object with the initializer - public OptionalRef(EcsObjectBase obj) + /// Whether the struct is unmanaged + public OptionalRef(EcsObjectBase obj, bool unmanaged) { if (obj.InitData.Valid) { initializer = obj.InitData.Initializer(obj.Id); - exists = true; + state = (unmanaged ? State.Native : State.Managed) | State.Initializer; } else { initializer = default; - exists = false; + state = State.Empty; } array = default; index = default; @@ -50,31 +59,36 @@ namespace TechbloxModdingAPI /// The value or the default value public ref T Get() { - if (!exists) return ref CompRefCache.Default; - if (initializer.EGID == EGID.Empty) - return ref array[index]; - return ref initializer.GetOrCreate(); + if (state == State.Empty) return ref CompRefCache.Default; + if ((state & State.Initializer) != State.Empty) return ref initializer.GetOrCreate(); + if ((state & State.Native) != State.Empty) return ref array[index]; + return ref managedArray[index]; } - public bool Exists => exists; + public bool Exists => state != State.Empty; public static implicit operator T(OptionalRef opt) => opt.Get(); - public static implicit operator bool(OptionalRef opt) => opt.exists; - - /*public delegate ref TR Mapper(ref T component) where TR : unmanaged; - public unsafe delegate TR* PMapper(T* component) where TR : unmanaged; - - public unsafe OptionalRef Map(PMapper mapper) where TR : unmanaged => - exists ? new OptionalRef(ref *mapper(pointer)) : new OptionalRef();*/ + public static implicit operator bool(OptionalRef opt) => opt.state != State.Empty; /// /// Creates an instance of a struct T that can be referenced. /// - /// The struct type to cache - private struct CompRefCache where TR : unmanaged + internal struct CompRefCache + { + public static T Default; + } + + /// + /// A byte that holds state in its bits. + /// + [Flags] + private enum State : byte { - public static TR Default; + Empty, + Native, + Managed, + Initializer = 4 } } } \ No newline at end of file