diff --git a/encompass-cs/Attributes/Sends.cs b/encompass-cs/Attributes/Sends.cs new file mode 100644 index 0000000..b9b5cea --- /dev/null +++ b/encompass-cs/Attributes/Sends.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Encompass.Exceptions; + +namespace Encompass +{ + [AttributeUsage(AttributeTargets.Class)] + public class Sends : Attribute + { + public readonly HashSet sendTypes; + + public Sends(params Type[] sendTypes) + { + foreach (var sendType in sendTypes) + { + var isMessage = sendType.GetInterfaces().Contains(typeof(IMessage)); + if (!isMessage) + { + throw new IllegalWriteTypeException("{0} must be a Message", sendType.Name); + } + } + + this.sendTypes = new HashSet(sendTypes); + } + } +} diff --git a/encompass-cs/Attributes/Updates.cs b/encompass-cs/Attributes/Updates.cs new file mode 100644 index 0000000..b78ccae --- /dev/null +++ b/encompass-cs/Attributes/Updates.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Encompass.Exceptions; + +namespace Encompass +{ + [AttributeUsage(AttributeTargets.Class)] + public class Updates : Attribute + { + public readonly HashSet updateTypes; + + public Updates(params Type[] updateTypes) + { + foreach (var updateType in updateTypes) + { + var isComponent = updateType.GetInterfaces().Contains(typeof(IComponent)); + if (!isComponent) + { + throw new IllegalUpdateTypeException("{0} must be a Component", updateType.Name); + } + } + + this.updateTypes = new HashSet(updateTypes); + } + } +} \ No newline at end of file diff --git a/encompass-cs/Attributes/Writes.cs b/encompass-cs/Attributes/Writes.cs deleted file mode 100644 index 7467e33..0000000 --- a/encompass-cs/Attributes/Writes.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Encompass.Exceptions; - -namespace Encompass -{ - [AttributeUsage(AttributeTargets.Class)] - public class Writes : Attribute - { - public readonly HashSet writeTypes; - - public Writes(params Type[] writeTypes) - { - foreach (var writeType in writeTypes) - { - if (!writeType.GetInterfaces().Contains(typeof(IMessage)) && !writeType.GetInterfaces().Contains(typeof(IComponent))) - { - throw new IllegalWriteTypeException("{0} must be a Message or Component", writeType.Name); - } - } - - if (writeTypes.Any((type) => type.GetInterfaces().Contains(typeof(IMessage))) && writeTypes.Any((type) => type.GetInterfaces().Contains(typeof(IComponent)))) - { - throw new ComponentAndMessageWriteException("An Engine which writes Components cannot also write Messages"); - } - - this.writeTypes = new HashSet(writeTypes); - } - } -} diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index 9501c18..dff9496 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -8,9 +8,10 @@ namespace Encompass { public abstract class Engine { - internal readonly HashSet writeTypes = new HashSet(); + internal readonly HashSet sendTypes = new HashSet(); internal readonly HashSet readTypes = new HashSet(); internal readonly HashSet activateTypes = new HashSet(); + internal readonly HashSet updateTypes = new HashSet(); private EntityManager entityManager; private ComponentManager componentManager; @@ -18,10 +19,10 @@ namespace Encompass protected Engine() { - var writesAttribute = GetType().GetCustomAttribute(false); + var writesAttribute = GetType().GetCustomAttribute(false); if (writesAttribute != null) { - writeTypes = writesAttribute.writeTypes; + sendTypes = writesAttribute.sendTypes; } var readsAttribute = GetType().GetCustomAttribute(false); @@ -35,6 +36,16 @@ namespace Encompass { activateTypes = activatesAttribute.activateTypes; } + + var updatesAttribute = GetType().GetCustomAttribute(false); + if (updatesAttribute != null) + { + updateTypes = updatesAttribute.updateTypes; + if (sendTypes.Any()) + { + throw new IllegalEngineAttributesException("Engine {0} sends Message(s) and updates Component(s)", GetType().Name); + } + } } internal void AssignEntityManager(EntityManager entityManager) @@ -181,7 +192,7 @@ namespace Encompass internal void UpdateComponentInWorld(Guid componentID, TComponent newComponent) where TComponent : struct, IComponent { - if (!writeTypes.Contains(typeof(TComponent))) + if (!updateTypes.Contains(typeof(TComponent))) { throw new IllegalWriteException("Engine {0} tried to write undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name); } @@ -196,7 +207,7 @@ namespace Encompass protected void EmitMessage(TMessage message) where TMessage : struct, IMessage { - if (!writeTypes.Contains(typeof(TMessage))) + if (!sendTypes.Contains(typeof(TMessage))) { throw new IllegalWriteException("Engine {0} tried to write undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name); } diff --git a/encompass-cs/Engines/ComponentMessageEmitter.cs b/encompass-cs/Engines/ComponentMessageEmitter.cs index bbb5cfd..3606652 100644 --- a/encompass-cs/Engines/ComponentMessageEmitter.cs +++ b/encompass-cs/Engines/ComponentMessageEmitter.cs @@ -6,13 +6,13 @@ namespace Encompass.Engines { public ComponentMessageEmitter() : base() { - var writesAttribute = GetType().GetCustomAttribute(false); + var writesAttribute = GetType().GetCustomAttribute(false); if (writesAttribute != null) { - writesAttribute.writeTypes.Add(typeof(ComponentMessage)); + writesAttribute.sendTypes.Add(typeof(ComponentMessage)); } - writeTypes.Add(typeof(ComponentMessage)); + sendTypes.Add(typeof(ComponentMessage)); } public override void Update(double dt) diff --git a/encompass-cs/Exceptions/ComponentAndMessageWriteException.cs b/encompass-cs/Exceptions/IllegalEngineAttributesException.cs similarity index 60% rename from encompass-cs/Exceptions/ComponentAndMessageWriteException.cs rename to encompass-cs/Exceptions/IllegalEngineAttributesException.cs index 31c0abc..d133d19 100644 --- a/encompass-cs/Exceptions/ComponentAndMessageWriteException.cs +++ b/encompass-cs/Exceptions/IllegalEngineAttributesException.cs @@ -3,9 +3,9 @@ using System; namespace Encompass.Exceptions { - public class ComponentAndMessageWriteException : Exception + public class IllegalEngineAttributesException : Exception { - public ComponentAndMessageWriteException( + public IllegalEngineAttributesException( string format, params object[] args ) : base(string.Format(format, args)) { } diff --git a/encompass-cs/Exceptions/UnregisteredComponentReadException.cs b/encompass-cs/Exceptions/IllegalUpdateTypeException.cs similarity index 59% rename from encompass-cs/Exceptions/UnregisteredComponentReadException.cs rename to encompass-cs/Exceptions/IllegalUpdateTypeException.cs index 13891cc..0a63dad 100644 --- a/encompass-cs/Exceptions/UnregisteredComponentReadException.cs +++ b/encompass-cs/Exceptions/IllegalUpdateTypeException.cs @@ -2,9 +2,9 @@ using System; namespace Encompass.Exceptions { - public class UnregisteredComponentReadException : Exception + public class IllegalUpdateTypeException : Exception { - public UnregisteredComponentReadException( + public IllegalUpdateTypeException( string format, params object[] args ) : base(string.Format(format, args)) { } diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index c7ed01a..1063955 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -77,11 +77,11 @@ namespace Encompass foreach (var activateType in engine.activateTypes) { - engine.writeTypes.Add(activateType); + engine.sendTypes.Add(activateType); } var messageReadTypes = engine.readTypes.Where((type) => type.GetInterfaces().Contains(typeof(IMessage))); - var messageSendTypes = engine.writeTypes.Where((type) => type.GetInterfaces().Contains(typeof(IMessage))); + var messageSendTypes = engine.sendTypes; if (messageReadTypes.Intersect(messageSendTypes).Any()) { @@ -144,7 +144,7 @@ namespace Encompass { foreach (var senderEngine in senders) { - foreach (var messageType in senderEngine.writeTypes.Where((type) => type.GetInterfaces().Contains(typeof(IMessage)))) + foreach (var messageType in senderEngine.sendTypes.Where((type) => type.GetInterfaces().Contains(typeof(IMessage)))) { if (typeToReaders.ContainsKey(messageType)) { @@ -181,29 +181,25 @@ namespace Encompass foreach (var engine in engines) { - var writeAttribute = engine.GetType().GetCustomAttribute(false); - if (writeAttribute != null) + foreach (var updateType in engine.updateTypes) { - foreach (var writeType in writeAttribute.writeTypes) + if (updateType.GetInterfaces().Contains(typeof(IComponent))) // if our write type is a component { - if (writeType.GetInterfaces().Contains(typeof(IComponent))) // if our write type is a component + if (mutatedComponentTypes.Contains(updateType)) { - if (mutatedComponentTypes.Contains(writeType)) - { - duplicateMutations.Add(writeType); - } - else - { - mutatedComponentTypes.Add(writeType); - } - - if (!componentToEngines.ContainsKey(writeType)) - { - componentToEngines[writeType] = new List(); - } - - componentToEngines[writeType].Add(engine); + duplicateMutations.Add(updateType); } + else + { + mutatedComponentTypes.Add(updateType); + } + + if (!componentToEngines.ContainsKey(updateType)) + { + componentToEngines[updateType] = new List(); + } + + componentToEngines[updateType].Add(engine); } } } diff --git a/test/ComponentTest.cs b/test/ComponentTest.cs index 98204a8..c10ff29 100644 --- a/test/ComponentTest.cs +++ b/test/ComponentTest.cs @@ -85,7 +85,7 @@ namespace Tests public MockComponent mockComponent; } - [Writes(typeof(AddMockComponentMessage))] + [Sends(typeof(AddMockComponentMessage))] class EmitMockComponentMessageEngine : Engine { private Entity entity; @@ -359,7 +359,7 @@ namespace Tests } [Reads(typeof(RemoveComponentTestMessage))] - [Writes(typeof(CheckHasMockComponentMessage))] + [Sends(typeof(CheckHasMockComponentMessage))] class DoRemoveCheckEngine : Engine { private Entity entity; @@ -440,7 +440,7 @@ namespace Tests } [Reads(typeof(ActivateComponentMessage))] - [Writes(typeof(CheckHasMockComponentMessage))] + [Sends(typeof(CheckHasMockComponentMessage))] class DoActivateCheckEngine : Engine { private Entity entity; @@ -509,7 +509,6 @@ namespace Tests } [Reads(typeof(DeactivateComponentMessage))] - [Writes(typeof(MockComponent))] class DeactivateComponentEngine : Engine { public override void Update(double dt) @@ -522,7 +521,7 @@ namespace Tests } [Reads(typeof(DeactivateComponentMessage))] - [Writes(typeof(CheckHasMockComponentMessage))] + [Sends(typeof(CheckHasMockComponentMessage))] class DoDeactivateCheckEngine : Engine { private Entity entity; diff --git a/test/EngineTest.cs b/test/EngineTest.cs index a71982c..59e9a04 100644 --- a/test/EngineTest.cs +++ b/test/EngineTest.cs @@ -120,7 +120,7 @@ namespace Tests } [Reads(typeof(MockComponent))] - [Writes(typeof(MockComponent))] + [Updates(typeof(MockComponent))] public class UpdateComponentTestEngine : Engine { public override void Update(double dt) @@ -200,7 +200,7 @@ namespace Tests public string myString; } - [Writes(typeof(MockMessage))] + [Sends(typeof(MockMessage))] public class MessageEmitEngine : Engine { public override void Update(double dt) @@ -284,7 +284,7 @@ namespace Tests static bool someTest; - [Writes(typeof(MockMessage))] + [Sends(typeof(MockMessage))] class EmitMockMessageEngine : Engine { public override void Update(double dt) @@ -481,7 +481,6 @@ namespace Tests } [Reads(typeof(DestroyerComponent), typeof(MockComponent))] - [Writes(typeof(MockComponent))] class DestroyAndAddComponentEngine : Engine { public override void Update(double dt) @@ -646,7 +645,8 @@ namespace Tests Assert.IsFalse(hasEntity); } - [Writes(typeof(MockComponent), typeof(MockMessage))] + [Sends(typeof(MockMessage))] + [Updates(typeof(MockComponent))] class EngineThatWritesComponentAndMessage : Engine { public override void Update(double dt) { } @@ -657,7 +657,7 @@ namespace Tests { var worldBuilder = new WorldBuilder(); - Assert.Throws(() => worldBuilder.AddEngine(new EngineThatWritesComponentAndMessage())); + Assert.Throws(() => worldBuilder.AddEngine(new EngineThatWritesComponentAndMessage())); } struct MockComponentUpdateMessage : IMessage @@ -667,7 +667,7 @@ namespace Tests } [Reads(typeof(MockComponentUpdateMessage))] - [Writes(typeof(MockComponent))] + [Updates(typeof(MockComponent))] class RepeatUpdateEngine : Engine { public override void Update(double dt) diff --git a/test/SpawnerTest.cs b/test/SpawnerTest.cs index bfc7646..3d9b7d6 100644 --- a/test/SpawnerTest.cs +++ b/test/SpawnerTest.cs @@ -14,7 +14,7 @@ namespace Tests static Entity resultEntity; - [Writes(typeof(SpawnMessageA))] + [Sends(typeof(SpawnMessageA))] class MessageEmitter : Engine { public override void Update(double dt) diff --git a/test/WorldBuilderTest.cs b/test/WorldBuilderTest.cs index 2950d1c..adb9231 100644 --- a/test/WorldBuilderTest.cs +++ b/test/WorldBuilderTest.cs @@ -14,7 +14,7 @@ namespace Tests struct BMessage : IMessage { } [Reads(typeof(AMessage))] - [Writes(typeof(BMessage))] + [Sends(typeof(BMessage))] class AEngine : Engine { public override void Update(double dt) @@ -25,7 +25,7 @@ namespace Tests } [Reads(typeof(BMessage))] - [Writes(typeof(AMessage))] + [Sends(typeof(AMessage))] class BEngine : Engine { public override void Update(double dt) @@ -54,7 +54,7 @@ namespace Tests struct DMessage : IMessage { } [Reads(typeof(AMessage))] - [Writes(typeof(BMessage))] + [Sends(typeof(BMessage))] class AEngine : Engine { public override void Update(double dt) @@ -65,7 +65,7 @@ namespace Tests } [Reads(typeof(BMessage))] - [Writes(typeof(CMessage))] + [Sends(typeof(CMessage))] class BEngine : Engine { public override void Update(double dt) @@ -76,7 +76,7 @@ namespace Tests } [Reads(typeof(CMessage))] - [Writes(typeof(DMessage))] + [Sends(typeof(DMessage))] class CEngine : Engine { public override void Update(double dt) @@ -87,7 +87,7 @@ namespace Tests } [Reads(typeof(DMessage))] - [Writes(typeof(AMessage))] + [Sends(typeof(AMessage))] class DEngine : Engine { public override void Update(double dt) @@ -114,13 +114,13 @@ namespace Tests { struct AComponent : IComponent { } - [Writes(typeof(AComponent))] + [Updates(typeof(AComponent))] class AEngine : Engine { public override void Update(double dt) { } } - [Writes(typeof(AComponent))] + [Updates(typeof(AComponent))] class BEngine : Engine { public override void Update(double dt) { } @@ -142,7 +142,7 @@ namespace Tests struct AMessage : IMessage { } [Reads(typeof(AMessage))] - [Writes(typeof(AMessage))] + [Sends(typeof(AMessage))] class AEngine : Engine { public override void Update(double dt) @@ -186,7 +186,7 @@ namespace Tests { struct ANonMessage { } - [Writes(typeof(ANonMessage))] + [Sends(typeof(ANonMessage))] class MyEngine : Engine { public override void Update(double dt) @@ -216,7 +216,7 @@ namespace Tests struct CMessage : IMessage { } struct DMessage : IMessage { } - [Writes(typeof(AMessage))] + [Sends(typeof(AMessage))] class AEngine : Engine { public override void Update(double dt) @@ -225,7 +225,7 @@ namespace Tests } } - [Writes(typeof(BMessage))] + [Sends(typeof(BMessage))] class BEngine : Engine { public override void Update(double dt) @@ -235,7 +235,7 @@ namespace Tests } [Reads(typeof(AMessage), typeof(BMessage))] - [Writes(typeof(DMessage))] + [Sends(typeof(DMessage))] class CEngine : Engine { public override void Update(double dt)