From ddaa933e7d820b2965bcb8b039798c81c832a4c9 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 7 Feb 2022 00:25:01 +0100 Subject: [PATCH] Add option to delay entity change publish and remove reflection stuff Neither of them work actually Added some delay between tests --- TechbloxModdingAPI/Blocks/BlockTests.cs | 2 +- .../Blocks/Engines/BlockEngine.cs | 21 +++++----- TechbloxModdingAPI/TechbloxModdingAPI.csproj | 2 +- TechbloxModdingAPI/Tests/TestRoot.cs | 2 +- .../Utility/NativeApiExtensions.cs | 40 +++++++++++++++++++ 5 files changed, 55 insertions(+), 12 deletions(-) diff --git a/TechbloxModdingAPI/Blocks/BlockTests.cs b/TechbloxModdingAPI/Blocks/BlockTests.cs index e58387e..34903cb 100644 --- a/TechbloxModdingAPI/Blocks/BlockTests.cs +++ b/TechbloxModdingAPI/Blocks/BlockTests.cs @@ -82,7 +82,7 @@ namespace TechbloxModdingAPI.Blocks yield break; for (var index = 0; index < blocks.Length; index++) { - if (index % 50 == 0) yield return Yield.It; //The material or flipped status can only be changed 130 times per submission + if (index % 50 == 0) yield return new WaitForSecondsEnumerator(0.2f).Continue(); //The material or flipped status can only be changed 130 times per submission var block = blocks[index]; if (!block.Exists) continue; foreach (var property in block.GetType().GetProperties()) diff --git a/TechbloxModdingAPI/Blocks/Engines/BlockEngine.cs b/TechbloxModdingAPI/Blocks/Engines/BlockEngine.cs index f150e27..1cfe0eb 100644 --- a/TechbloxModdingAPI/Blocks/Engines/BlockEngine.cs +++ b/TechbloxModdingAPI/Blocks/Engines/BlockEngine.cs @@ -99,16 +99,19 @@ namespace TechbloxModdingAPI.Blocks.Engines internal object GetBlockInfo(Block block, Type type, string name) { - var str = AccessTools.Method(typeof(BlockEngine), "GetBlockInfo", generics: new[] { type }) - .Invoke(this, new object[] { block }); - return AccessTools.Field(str.GetType(), name).GetValue(str); + /*var opt = AccessTools.Method(typeof(BlockEngine), "GetBlockInfoOptional", generics: new[] { type }) + .Invoke(this, new object[] { block }); - TODO: Cannot call method with by-ref return value + var str = AccessTools.Method(opt.GetType(), "Get").Invoke(opt, Array.Empty()); + return AccessTools.Field(str.GetType(), name).GetValue(str);*/ + return AccessTools.Field(type, name).GetValue(Activator.CreateInstance(type)); } internal void SetBlockInfo(Block block, Type type, string name, object value) { - var str = AccessTools.Method(typeof(BlockEngine), "GetBlockInfo", generics: new[] { type }) + /*var opt = AccessTools.Method(typeof(BlockEngine), "GetBlockInfoOptional", generics: new[] { type }) .Invoke(this, new object[] { block }); - AccessTools.Field(str.GetType(), name).SetValue(str, value); + var str = AccessTools.Method(opt.GetType(), "Get").Invoke(opt, Array.Empty()); + AccessTools.Field(str.GetType(), name).SetValue(str, value);*/ } public void UpdateDisplayedBlock(EGID id) @@ -120,7 +123,7 @@ namespace TechbloxModdingAPI.Blocks.Engines var skew = entitiesDB.QueryEntity(id); entitiesDB.QueryEntity(id).matrix = math.mul(float4x4.TRS(pos.position, rot.rotation, scale.scale), skew.skewMatrix); - entitiesDB.PublishEntityChange(id); // Signal a prefab change so it updates the render buffers + entitiesDB.PublishEntityChangeDelayed(id); // Signal a prefab change so it updates the render buffers } internal void UpdatePrefab(Block block, byte material, bool flipped) @@ -141,15 +144,15 @@ namespace TechbloxModdingAPI.Blocks.Engines entitiesDB.QueryEntityOrDefault(block).prefabID = prefabId; if (block.Exists) { - entitiesDB.PublishEntityChange(block.Id); - entitiesDB.PublishEntityChange(block.Id); + entitiesDB.PublishEntityChangeDelayed(block.Id); + entitiesDB.PublishEntityChangeDelayed(block.Id); ref BuildingActionComponent local = ref entitiesDB.QueryEntity(BuildingDroneUtility .GetLocalBuildingDrone(entitiesDB).ToEGID(entitiesDB)); local.buildAction = BuildAction.ChangeMaterial; local.targetPosition = block.Position; - this.entitiesDB.PublishEntityChange(local.ID); + this.entitiesDB.PublishEntityChangeDelayed(local.ID); } //Phyiscs prefab: prefabAssetID, set on block creation from the CubeListData } diff --git a/TechbloxModdingAPI/TechbloxModdingAPI.csproj b/TechbloxModdingAPI/TechbloxModdingAPI.csproj index c26813f..7692f80 100644 --- a/TechbloxModdingAPI/TechbloxModdingAPI.csproj +++ b/TechbloxModdingAPI/TechbloxModdingAPI.csproj @@ -8,7 +8,7 @@ https://git.exmods.org/modtainers/GamecraftModdingAPI en-CA true - 8 + 9 diff --git a/TechbloxModdingAPI/Tests/TestRoot.cs b/TechbloxModdingAPI/Tests/TestRoot.cs index 648d029..5306adc 100644 --- a/TechbloxModdingAPI/Tests/TestRoot.cs +++ b/TechbloxModdingAPI/Tests/TestRoot.cs @@ -205,7 +205,7 @@ namespace TechbloxModdingAPI.Tests } while (cont); } - yield return Yield.It; + yield return new WaitForSecondsEnumerator(1f).Continue(); } } diff --git a/TechbloxModdingAPI/Utility/NativeApiExtensions.cs b/TechbloxModdingAPI/Utility/NativeApiExtensions.cs index ff5ca45..90b0262 100644 --- a/TechbloxModdingAPI/Utility/NativeApiExtensions.cs +++ b/TechbloxModdingAPI/Utility/NativeApiExtensions.cs @@ -1,4 +1,9 @@ +using System; +using System.Collections.Generic; using Svelto.ECS; +using Svelto.Tasks; +using Svelto.Tasks.Lean; +using TechbloxModdingAPI.Tasks; namespace TechbloxModdingAPI.Utility { @@ -58,5 +63,40 @@ namespace TechbloxModdingAPI.Utility if (init.Has()) return ref init.Get();*/ return ref opt.Get(); //Default value } + + private static readonly Dictionary Changes)> ChangesToPublish = new(); + + /// + /// Publishes an entity change, ignoring duplicate publishes and delaying changes as necessary. + /// It will only publish in the next frame. + /// + /// The entities DB to publish to + /// The ECS object that got changed + /// Limits how many changes to publish - should be no more than the consumers' capacity that process this component + /// The component that changed + public static void PublishEntityChangeDelayed(this EntitiesDB entitiesDB, EGID id, int limit = 80) + where T : unmanaged, IEntityComponent + { //TODO: Doesn't seem to help + if(!ChangesToPublish.ContainsKey(typeof(T))) + ChangesToPublish.Add(typeof(T), (0, new HashSet())); + var changes = ChangesToPublish[typeof(T)].Changes; + if (changes.Contains(id)) return; + changes.Add(id); + PublishChanges(entitiesDB, id, limit).RunOn(Scheduler.leanRunner); + } + + private static IEnumerator PublishChanges(EntitiesDB entitiesDB, EGID id, int limit) + where T : unmanaged, IEntityComponent + { + yield return Yield.It; + while (ChangesToPublish[typeof(T)].PublishedCount >= limit) + yield return Yield.It; + entitiesDB.PublishEntityChange(id); + var (count, changes) = ChangesToPublish[typeof(T)]; + changes.Remove(id); + ChangesToPublish[typeof(T)] = (count + 1, changes); + yield return Yield.It; + ChangesToPublish[typeof(T)] = (0, changes); + } } } \ No newline at end of file