diff --git a/TODO b/TODO index 7324834..4429109 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,4 @@ - look at test coverage - docs -- WritesPending and writes redundant? \ No newline at end of file +- make sure two different engines that Write the same component cannot have same priority \ No newline at end of file diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 1e8de7e..74bb81d 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -186,6 +186,8 @@ namespace Encompass var writtenComponentTypesWithoutPriority = new HashSet(); var writtenComponentTypesWithPriority = new HashSet(); var duplicateWritesWithoutPriority = new List(); + var duplicateWritesWithSamePriority = new List(); + var writePriorities = new Dictionary>(); var writeMessageToEngines = new Dictionary>(); foreach (var engine in engines) @@ -196,7 +198,31 @@ namespace Encompass { var componentType = writeType.GetGenericArguments()[0]; - if (!engine.writePriorities.ContainsKey(componentType)) + if (engine.writePriorities.ContainsKey(componentType)) + { + var priority = engine.writePriorities[componentType]; + + writtenComponentTypesWithPriority.Add(componentType); + + if (!writePriorities.ContainsKey(componentType)) + { + writePriorities[componentType] = new HashSet(); + } + + if (writePriorities[componentType].Contains(priority)) + { + duplicateWritesWithSamePriority.Add(componentType); + } + else if (writtenComponentTypesWithoutPriority.Contains(componentType)) + { + duplicateWritesWithoutPriority.Add(componentType); + } + else + { + writePriorities[componentType].Add(priority); + } + } + else { if (writtenComponentTypesWithoutPriority.Contains(componentType) || writtenComponentTypesWithPriority.Contains(componentType)) { @@ -207,10 +233,6 @@ namespace Encompass writtenComponentTypesWithoutPriority.Add(componentType); } } - else - { - writtenComponentTypesWithPriority.Add(componentType); - } if (!writeMessageToEngines.ContainsKey(componentType)) { @@ -235,6 +257,20 @@ namespace Encompass throw new EngineWriteConflictException(errorString); } + if (duplicateWritesWithSamePriority.Count > 0) + { + var errorString = "Multiple Engines write the same Component with the same priority: "; + foreach (var componentType in duplicateWritesWithSamePriority) + { + errorString += "\n" + + 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."; + + throw new EngineWriteConflictException(errorString); + } + var engineOrder = new List(); foreach (var engine in engineGraph.TopologicalSort()) { diff --git a/test/WorldBuilderTest.cs b/test/WorldBuilderTest.cs index a93b1b5..32d1207 100644 --- a/test/WorldBuilderTest.cs +++ b/test/WorldBuilderTest.cs @@ -275,6 +275,68 @@ namespace Tests } } + public class PriorityConflict + { + [Writes(typeof(MockComponent), 2)] + class AEngine : Engine + { + public override void Update(double dt) + { + + } + } + + [Writes(typeof(MockComponent), 2)] + class BEngine : Engine + { + public override void Update(double dt) + { + + } + } + + [Test] + public void PriorityConflictTest() + { + var worldBuilder = new WorldBuilder(); + worldBuilder.AddEngine(new AEngine()); + worldBuilder.AddEngine(new BEngine()); + + Assert.Throws(() => worldBuilder.Build()); + } + } + + public class EngineWriteConflict + { + [Writes(typeof(MockComponent))] + class AEngine : Engine + { + public override void Update(double dt) + { + + } + } + + [Writes(typeof(MockComponent), 2)] + class BEngine : Engine + { + public override void Update(double dt) + { + + } + } + + [Test] + public void EngineWriteConflictPriorityAndNoPriorityTest() + { + var worldBuilder = new WorldBuilder(); + worldBuilder.AddEngine(new AEngine()); + worldBuilder.AddEngine(new BEngine()); + + Assert.Throws(() => worldBuilder.Build()); + } + } + public class LegalEngines { static List order = new List();