From 591cd980d955bcfc2f5017265b1a901d82005db2 Mon Sep 17 00:00:00 2001 From: thatcosmonaut Date: Wed, 13 Nov 2019 13:15:43 -0800 Subject: [PATCH] runtime type HasComponent --- encompass-cs/ComponentMessageManager.cs | 15 ++++++++++ encompass-cs/Engine.cs | 32 +++++++++++++++++++++ test/ComponentTest.cs | 38 ++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/encompass-cs/ComponentMessageManager.cs b/encompass-cs/ComponentMessageManager.cs index c42716b..3cde86c 100644 --- a/encompass-cs/ComponentMessageManager.cs +++ b/encompass-cs/ComponentMessageManager.cs @@ -268,16 +268,31 @@ namespace Encompass return entityToTypeToComponentID.ContainsKey(entity) && entityToTypeToComponentID[entity].ContainsKey(typeof(TComponent)); } + internal bool HasExistingOrPendingComponent(Entity entity, Type type) + { + return entityToTypeToComponentID.ContainsKey(entity) && entityToTypeToComponentID[entity].ContainsKey(type); + } + internal bool HasExistingComponent(Entity entity) where TComponent : struct, IComponent { return entityToTypeToExistingComponentID.ContainsKey(entity) && entityToTypeToExistingComponentID[entity].ContainsKey(typeof(TComponent)); } + internal bool HasExistingComponent(Entity entity, Type type) + { + return entityToTypeToExistingComponentID.ContainsKey(entity) && entityToTypeToExistingComponentID[entity].ContainsKey(type); + } + internal bool HasPendingComponent(Entity entity) where TComponent : struct, IComponent { return entityToTypeToPendingComponentID.ContainsKey(entity) && entityToTypeToPendingComponentID[entity].ContainsKey(typeof(TComponent)); } + internal bool HasPendingComponent(Entity entity, Type type) + { + return entityToTypeToPendingComponentID.ContainsKey(entity) && entityToTypeToPendingComponentID[entity].ContainsKey(type); + } + internal IComponent GetComponentByID(Guid componentID) { if (componentIDToComponent.ContainsKey(componentID)) diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index 92f01d1..c68184f 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -362,6 +362,38 @@ namespace Encompass } } + /// + /// Returns true if the Entity has a Component of the given Type. + /// + /// + /// Thrown when the Engine does not declare that is Reads the given Component Type. + /// + protected bool HasComponent(Entity entity, Type type) + { + var pending = typeof(PendingComponentMessage<>).MakeGenericType(type); + var existing = typeof(ComponentMessage<>).MakeGenericType(type); + + var pendingRead = receiveTypes.Contains(pending); + var existingRead = receiveTypes.Contains(existing); + + if (pendingRead && existingRead) + { + return componentMessageManager.HasExistingOrPendingComponent(entity, type); + } + else if (existingRead) + { + return componentMessageManager.HasExistingComponent(entity, type); + } + else if (pendingRead) + { + return componentMessageManager.HasPendingComponent(entity, type); + } + else + { + throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", GetType().Name, type.Name); + } + } + /// /// Sets Component data for the specified Component Type on the specified Entity. If Component data for this Type already existed on the Entity, the component data is overwritten. /// diff --git a/test/ComponentTest.cs b/test/ComponentTest.cs index 3cd553b..4ae154a 100644 --- a/test/ComponentTest.cs +++ b/test/ComponentTest.cs @@ -135,7 +135,7 @@ namespace Tests worldBuilder.AddEngine(new ReadMockComponentEngine()); var entity = worldBuilder.CreateEntity(); - worldBuilder.SetComponent(entity, new MockComponent {}); + worldBuilder.SetComponent(entity, new MockComponent { }); var world = worldBuilder.Build(); world.Update(0.01); @@ -312,6 +312,42 @@ namespace Tests world.Update(0.01); } + [Receives(typeof(HasComponentTestMessage))] + [Reads(typeof(MockComponent))] + class HasComponentWithRuntimeTypeEngine : Engine + { + public override void Update(double dt) + { + foreach (var hasComponentTestEngine in ReadMessages()) + { + Assert.IsTrue(HasComponent(hasComponentTestEngine.entity, typeof(MockComponent))); + } + } + } + + [Test] + public void HasComponentWithRuntimeType() + { + var worldBuilder = new WorldBuilder(); + worldBuilder.AddEngine(new HasComponentWithRuntimeTypeEngine()); + + var entity = worldBuilder.CreateEntity(); + + MockComponent mockComponent; + mockComponent.myInt = 3; + mockComponent.myString = "hello"; + + worldBuilder.SetComponent(entity, mockComponent); + + HasComponentTestMessage hasComponentTestMessage; + hasComponentTestMessage.entity = entity; + worldBuilder.SendMessage(hasComponentTestMessage); + + var world = worldBuilder.Build(); + + world.Update(0.01); + } + struct RemoveComponentTestMessage : IMessage { public Entity entity;