diff --git a/encompass-cs/Attributes/DefaultWritePriority.cs b/encompass-cs/Attributes/DefaultWritePriority.cs new file mode 100644 index 0000000..cf0c065 --- /dev/null +++ b/encompass-cs/Attributes/DefaultWritePriority.cs @@ -0,0 +1,15 @@ +using System; + +namespace Encompass +{ + [AttributeUsage(AttributeTargets.Class)] + public class DefaultWritePriority : Attribute + { + public int writePriority; + + public DefaultWritePriority(int writePriority) + { + this.writePriority = writePriority; + } + } +} diff --git a/encompass-cs/Attributes/Writes.cs b/encompass-cs/Attributes/Writes.cs index 18c7e1f..b6edfe1 100644 --- a/encompass-cs/Attributes/Writes.cs +++ b/encompass-cs/Attributes/Writes.cs @@ -37,4 +37,4 @@ namespace Encompass this.priorities.Add(writeType, priority); } } -} \ No newline at end of file +} diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 5ffdec4..e8176b7 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -192,16 +192,26 @@ namespace Encompass foreach (var engine in engines) { + var defaultWritePriorityAttribute = engine.GetType().GetCustomAttribute(false); + var writeTypes = engine.sendTypes.Where((type) => type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ComponentWriteMessage<>)); foreach (var writeType in writeTypes) { var componentType = writeType.GetGenericArguments()[0]; + int? priority = null; if (engine.writePriorities.ContainsKey(componentType)) { - var priority = engine.writePriorities[componentType]; + priority = engine.writePriorities[componentType]; + } + else if (defaultWritePriorityAttribute != null) + { + priority = defaultWritePriorityAttribute.writePriority; + } + if (priority.HasValue) + { writtenComponentTypesWithPriority.Add(componentType); if (!writePriorities.ContainsKey(componentType)) @@ -209,7 +219,7 @@ namespace Encompass writePriorities[componentType] = new HashSet(); } - if (writePriorities[componentType].Contains(priority)) + if (writePriorities[componentType].Contains(priority.Value)) { duplicateWritesWithSamePriority.Add(componentType); } @@ -219,7 +229,7 @@ namespace Encompass } else { - writePriorities[componentType].Add(priority); + writePriorities[componentType].Add(priority.Value); } } else @@ -252,7 +262,7 @@ namespace Encompass componentType.Name + " written by: " + string.Join(", ", writeMessageToEngines[componentType].Select((engine) => engine.GetType().Name)); } - errorString += "\nTo resolve the conflict, add priority arguments to the Writes declarations."; + errorString += "\nTo resolve the conflict, add priority arguments to the Writes declarations or use a DefaultWritePriority attribute."; throw new EngineWriteConflictException(errorString); } @@ -266,7 +276,7 @@ namespace Encompass componentType.Name + " written by: " + string.Join(", ", writeMessageToEngines[componentType].Select(engine => engine.GetType().Name)); } - errorString += "\nTo resolve the conflict, add priority arguments to the Writes declarations."; + errorString += "\nTo resolve the conflict, add priority arguments to the Writes declarations or use a DefaultWritePriority attribute."; throw new EngineWriteConflictException(errorString); } diff --git a/test/WorldBuilderTest.cs b/test/WorldBuilderTest.cs index 32d1207..111b4ba 100644 --- a/test/WorldBuilderTest.cs +++ b/test/WorldBuilderTest.cs @@ -141,12 +141,12 @@ namespace Tests public class MultipleEngineWriteWithPriority { - struct SetMessage : IMessage + struct SetMessage : IMessage { public Entity entity; } - struct AComponent : IComponent + struct AComponent : IComponent { public int myInt; } @@ -156,7 +156,7 @@ namespace Tests [WritesPending(typeof(AComponent))] class AEngine : Engine { - public override void Update(double dt) + public override void Update(double dt) { foreach (var setMessage in ReadMessages()) { @@ -170,13 +170,84 @@ namespace Tests [WritesPending(typeof(AComponent))] class BEngine : Engine { - public override void Update(double dt) + public override void Update(double dt) { foreach (var setMessage in ReadMessages()) { SetComponent(setMessage.entity, new AComponent { myInt = 1 }); } - } + } + } + + static AComponent resultComponent; + + [ReadsPending(typeof(AComponent))] + class ReadComponentEngine : Engine + { + public override void Update(double dt) + { + resultComponent = ReadComponent().Item2; + } + } + + [Test] + public void LowerPriorityWrites() + { + var worldBuilder = new WorldBuilder(); + worldBuilder.AddEngine(new AEngine()); + worldBuilder.AddEngine(new BEngine()); + + var entity = worldBuilder.CreateEntity(); + worldBuilder.SendMessage(new SetMessage { entity = entity }); + + var world = worldBuilder.Build(); + + world.Update(0.01); + + Assert.That(resultComponent.myInt, Is.EqualTo(0)); + } + } + + public class DefaultWritePriority + { + struct SetMessage : IMessage + { + public Entity entity; + } + + struct AComponent : IComponent + { + public int myInt; + } + + [Receives(typeof(SetMessage))] + [Writes(typeof(AComponent))] + [WritesPending(typeof(AComponent))] + [Encompass.DefaultWritePriority(1)] + class AEngine : Engine + { + public override void Update(double dt) + { + foreach (var setMessage in ReadMessages()) + { + SetComponent(setMessage.entity, new AComponent { myInt = 0 }); + } + } + } + + + [Receives(typeof(SetMessage))] + [Writes(typeof(AComponent), 3)] + [WritesPending(typeof(AComponent))] + class BEngine : Engine + { + public override void Update(double dt) + { + foreach (var setMessage in ReadMessages()) + { + SetComponent(setMessage.entity, new AComponent { myInt = 1 }); + } + } } static AComponent resultComponent; @@ -218,7 +289,7 @@ namespace Tests { public override void Update(double dt) { - + } } @@ -435,7 +506,7 @@ namespace Tests resultMessages.Should().BeEmpty(); world.Update(0.25); - + resultMessages.Should().NotBeEmpty(); resultMessages.First().Should().BeOfType(); }