diff --git a/GamecraftModdingAPI/Block.cs b/GamecraftModdingAPI/Block.cs index ff89be3..d7c37dc 100644 --- a/GamecraftModdingAPI/Block.cs +++ b/GamecraftModdingAPI/Block.cs @@ -32,6 +32,11 @@ namespace GamecraftModdingAPI /// Place a new block at the given position. If scaled, position means the center of the block. The default block size is 0.2 in terms of position. /// Place blocks next to each other to connect them. /// The placed block will be a complete block with a placement grid and collision which will be saved along with the game. + /// + /// When placing multiple blocks, do not access properties immediately after creation as this + /// triggers a sync each time which can affect performance and may cause issues with the game. + /// You may either use AsyncUtils.WaitForSubmission() after placing all of the blocks + /// or simply access the block properties which will trigger the synchronization the first time a property is used. /// /// The block's type /// The block's color @@ -60,7 +65,9 @@ namespace GamecraftModdingAPI /// Place blocks next to each other to connect them. /// The placed block will be a complete block with a placement grid and collision which will be saved along with the game. /// - /// This method waits for the block to be constructed in the game. + /// This method waits for the block to be constructed in the game which may take a significant amount of time. + /// Only use this to place a single block. + /// For placing multiple blocks, use PlaceNew() then AsyncUtils.WaitForSubmission() when done with placing blocks. /// /// The block's type /// The block's color @@ -107,11 +114,11 @@ namespace GamecraftModdingAPI Id = id; if (!BlockEngine.BlockExists(Id)) { - Sync(); + /*Sync(); if (!BlockEngine.BlockExists(Id)) { throw new BlockDoesNotExistException($"Block {Id.entityID} must be placed using PlaceNew(...) since it does not exist yet"); - } + }*/ } } @@ -119,17 +126,6 @@ namespace GamecraftModdingAPI { } - /// - /// Synchronize newly created entity components with entities DB. - /// This forces a partial game tick, so it may be slow. - /// This also has the potential to make Gamecraft unstable. - /// Use this sparingly. - /// - protected static void Sync() - { - DeterministicStepCompositionRootPatch.SubmitEntitiesNow(); - } - public EGID Id { get; protected set; } /// @@ -159,6 +155,7 @@ namespace GamecraftModdingAPI /// /// The block's non-uniform scale or zero if the block's invalid. Independent of the uniform scaling. + /// The default scale of 1 means 0.2 in terms of position. /// public float3 Scale { @@ -171,6 +168,7 @@ namespace GamecraftModdingAPI /// /// The block's uniform scale or zero if the block's invalid. Also sets the non-uniform scale. + /// The default scale of 1 means 0.2 in terms of position. /// public int UniformScale { diff --git a/GamecraftModdingAPI/Blocks/BlockEngine.cs b/GamecraftModdingAPI/Blocks/BlockEngine.cs index eb462f9..6b412a7 100644 --- a/GamecraftModdingAPI/Blocks/BlockEngine.cs +++ b/GamecraftModdingAPI/Blocks/BlockEngine.cs @@ -10,6 +10,7 @@ using Svelto.DataStructures; using Svelto.ECS; using GamecraftModdingAPI.Engines; +using GamecraftModdingAPI.Utility; namespace GamecraftModdingAPI.Blocks { @@ -24,6 +25,8 @@ namespace GamecraftModdingAPI.Blocks public bool isRemovable => false; + internal bool Synced = true; + public void Dispose() { } @@ -60,6 +63,11 @@ namespace GamecraftModdingAPI.Blocks /// An editable reference to the struct public ref T GetBlockInfo(EGID blockID) where T : struct, IEntityComponent { + if (!Synced) + { + Sync(); + Synced = true; + } if (entitiesDB.Exists(blockID)) return ref entitiesDB.QueryEntity(blockID); T[] structHolder = new T[1]; //Create something that can be referenced @@ -76,11 +84,15 @@ namespace GamecraftModdingAPI.Blocks /// An editable reference to the struct public ref T GetBlockInfo(EGID blockID, out bool exists) where T : struct, IEntityComponent { + if (!Synced) + { + Sync(); + Synced = true; + } exists = entitiesDB.Exists(blockID); if (exists) return ref entitiesDB.QueryEntity(blockID); T[] structHolder = new T[1]; - //ref T defRef = ref structHolder[0]; return ref structHolder[0]; } @@ -142,6 +154,17 @@ namespace GamecraftModdingAPI.Blocks return list.ToArray(); } + /// + /// Synchronize newly created entity components with entities DB. + /// This forces a partial game tick, so it may be slow. + /// This also has the potential to make Gamecraft unstable. + /// Use this sparingly. + /// + private static void Sync() + { + DeterministicStepCompositionRootPatch.SubmitEntitiesNow(); + } + #if DEBUG public EntitiesDB GetEntitiesDB() { diff --git a/GamecraftModdingAPI/Blocks/PlacementEngine.cs b/GamecraftModdingAPI/Blocks/PlacementEngine.cs index 28642e8..35f0a92 100644 --- a/GamecraftModdingAPI/Blocks/PlacementEngine.cs +++ b/GamecraftModdingAPI/Blocks/PlacementEngine.cs @@ -24,7 +24,7 @@ namespace GamecraftModdingAPI.Blocks /// public class PlacementEngine : IApiEngine { - public bool IsInGame = false; + public bool IsInGame; public void Dispose() { @@ -119,6 +119,7 @@ namespace GamecraftModdingAPI.Blocks ref PickedBlockExtraDataStruct pickedBlock = ref entitiesDB.QueryEntity(playerEGID); pickedBlock.placedBlockEntityID = playerEGID; pickedBlock.placedBlockWasAPickedBlock = false; + Block.BlockEngine.Synced = false; // Block entities will need to be submitted before properties can be used return newBlockID; } @@ -126,7 +127,7 @@ namespace GamecraftModdingAPI.Blocks public bool isRemovable => false; - [HarmonyPatch] + [HarmonyPatch] public class FactoryObtainerPatch { static void Postfix(BlockEntityFactory blockEntityFactory) diff --git a/GamecraftModdingAPI/Utility/AsyncUtils.cs b/GamecraftModdingAPI/Utility/AsyncUtils.cs index fcb5878..c646f8f 100644 --- a/GamecraftModdingAPI/Utility/AsyncUtils.cs +++ b/GamecraftModdingAPI/Utility/AsyncUtils.cs @@ -10,6 +10,7 @@ namespace GamecraftModdingAPI.Utility /// /// Waits for entity submission asynchronously. + /// Use after placing a block or otherwise creating things in the game to access their properties. /// public static async Task WaitForSubmission() {