diff --git a/encompass-cs/ComponentManager.cs b/encompass-cs/ComponentManager.cs index ded956e..8c45186 100644 --- a/encompass-cs/ComponentManager.cs +++ b/encompass-cs/ComponentManager.cs @@ -73,7 +73,14 @@ namespace Encompass return false; } - public bool UpdateComponent(int entityID, TComponent component, int priority) where TComponent : struct, IComponent + internal void AddImmediateComponent(int entityID, TComponent component) where TComponent : struct, IComponent + { + immediateComponentStore.Set(entityID, component); + replayStore.Set(entityID, component); + upToDateComponentStore.Set(entityID, component); + } + + internal bool UpdateComponent(int entityID, TComponent component, int priority) where TComponent : struct, IComponent { var result = upToDateComponentStore.Set(entityID, component, priority); if (result) @@ -83,6 +90,12 @@ namespace Encompass return result; } + internal void AddComponent(int entityID, TComponent component) where TComponent : struct, IComponent + { + upToDateComponentStore.Set(entityID, component); + replayStore.Set(entityID, component); + } + // existing or immediate reads internal IEnumerable<(TComponent, int)> ReadExistingAndImmediateComponentsByType() where TComponent : struct, IComponent diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index b404022..8be53dd 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -173,6 +173,11 @@ namespace Encompass return _newlyCreatedEntities.Contains(entityID); } + internal void ClearNewlyCreatedEntities() + { + _newlyCreatedEntities.Clear(); + } + /// /// Runs once per World update with the calculated delta-time. /// @@ -478,7 +483,16 @@ namespace Encompass throw new IllegalWriteException("AddComponent used on Entity that was not created in this context. Use SetComponent instead."); } - componentManager.AddComponent(entity.ID, component); + if (writeImmediateTypes.Contains(typeof(TComponent))) + { + componentManager.AddImmediateComponent(entity.ID, component); + trackingManager.ImmediateUpdateTracking(entity.ID, typeof(TComponent)); + } + else + { + componentManager.AddComponent(entity.ID, component); + } + trackingManager.RegisterAddition(entity.ID, typeof(TComponent)); if (component is IDrawableComponent drawableComponent) diff --git a/encompass-cs/World.cs b/encompass-cs/World.cs index 677bf8f..fcc3384 100644 --- a/encompass-cs/World.cs +++ b/encompass-cs/World.cs @@ -54,6 +54,8 @@ namespace Encompass { engine.Update(dt); } + + engine.ClearNewlyCreatedEntities(); } messageManager.ClearMessages(); diff --git a/test/EngineTest.cs b/test/EngineTest.cs index de4d956..b415eb8 100644 --- a/test/EngineTest.cs +++ b/test/EngineTest.cs @@ -415,8 +415,8 @@ namespace Tests Assert.Throws(() => world.Update(0.01f)); } - struct EntityMessage : IMessage, IHasEntity - { + struct EntityMessage : IMessage, IHasEntity + { public EntityMessage(Entity entity, int myInt) { Entity = entity; @@ -1240,6 +1240,101 @@ namespace Tests undilatedDeltaTime.Should().Be(0.5); } + class AddComponentWithoutPriorityEngine : Engine + { + public override void Update(double dt) + { + var entity = CreateEntity(); + AddComponent(entity, new MockComponent()); + + var entityB = CreateEntity(); + AddComponent(entityB, new MockComponent()); + } + } + + [Test] + public void AddComponent() + { + var worldBuilder = new WorldBuilder(); + + worldBuilder.AddEngine(new AddComponentWithoutPriorityEngine()); + worldBuilder.AddEngine(new ReadComponentsTestEngine()); + + var world = worldBuilder.Build(); + + world.Update(0.01); + world.Update(0.01); + + resultComponents.Should().HaveCount(2); + + world.Update(0.01); + + resultComponents.Should().HaveCount(4); + } + + [Reads(typeof(MockComponent))] + class AddComponentToPreviouslyExistingEntityEngine : Engine + { + public override void Update(double dt) + { + var (component, entity) = ReadComponentIncludingEntity(); + + AddComponent(entity, new MockComponent()); + } + } + + [Test] + public void AddComponentToPreviouslyExistingEntityTest() + { + var worldBuilder = new WorldBuilder(); + worldBuilder.AddEngine(new AddComponentToPreviouslyExistingEntityEngine()); + + var entity = worldBuilder.CreateEntity(); + worldBuilder.SetComponent(entity, new MockComponent()); + + var world = worldBuilder.Build(); + + Assert.Throws(() => world.Update(0.01)); + } + + [WritesImmediate(typeof(MockComponentB))] + class AddImmediateComponentEngine : Engine + { + public override void Update(double dt) + { + var entity = CreateEntity(); + AddComponent(entity, new MockComponentB(5)); + } + } + + [ReadsImmediate(typeof(MockComponentB))] + class ReadImmediateComponentEngine : Engine + { + public override void Update(double dt) + { + var (component, entity) = ReadComponentIncludingEntity(); + + getComponentResult = component; + } + } + + [Test] + public void AddImmediateComponentTest() + { + getComponentResult = default(MockComponentB); + + var worldBuilder = new WorldBuilder(); + + worldBuilder.AddEngine(new AddImmediateComponentEngine()); + worldBuilder.AddEngine(new ReadImmediateComponentEngine()); + + var world = worldBuilder.Build(); + + world.Update(0.01); + + getComponentResult.Should().Be(new MockComponentB(5)); + } + public class QueryTests { struct MockComponentB : IComponent { }