DefaultWritePriority attribute for engines

pull/5/head
Evan Hemsley 2019-09-26 13:26:48 -07:00
parent 5872e916ac
commit 5f72bef256
4 changed files with 109 additions and 13 deletions

View File

@ -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;
}
}
}

View File

@ -37,4 +37,4 @@ namespace Encompass
this.priorities.Add(writeType, priority); this.priorities.Add(writeType, priority);
} }
} }
} }

View File

@ -192,16 +192,26 @@ namespace Encompass
foreach (var engine in engines) foreach (var engine in engines)
{ {
var defaultWritePriorityAttribute = engine.GetType().GetCustomAttribute<DefaultWritePriority>(false);
var writeTypes = engine.sendTypes.Where((type) => type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ComponentWriteMessage<>)); var writeTypes = engine.sendTypes.Where((type) => type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ComponentWriteMessage<>));
foreach (var writeType in writeTypes) foreach (var writeType in writeTypes)
{ {
var componentType = writeType.GetGenericArguments()[0]; var componentType = writeType.GetGenericArguments()[0];
int? priority = null;
if (engine.writePriorities.ContainsKey(componentType)) 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); writtenComponentTypesWithPriority.Add(componentType);
if (!writePriorities.ContainsKey(componentType)) if (!writePriorities.ContainsKey(componentType))
@ -209,7 +219,7 @@ namespace Encompass
writePriorities[componentType] = new HashSet<int>(); writePriorities[componentType] = new HashSet<int>();
} }
if (writePriorities[componentType].Contains(priority)) if (writePriorities[componentType].Contains(priority.Value))
{ {
duplicateWritesWithSamePriority.Add(componentType); duplicateWritesWithSamePriority.Add(componentType);
} }
@ -219,7 +229,7 @@ namespace Encompass
} }
else else
{ {
writePriorities[componentType].Add(priority); writePriorities[componentType].Add(priority.Value);
} }
} }
else else
@ -252,7 +262,7 @@ namespace Encompass
componentType.Name + " written by: " + componentType.Name + " written by: " +
string.Join(", ", writeMessageToEngines[componentType].Select((engine) => engine.GetType().Name)); 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); throw new EngineWriteConflictException(errorString);
} }
@ -266,7 +276,7 @@ namespace Encompass
componentType.Name + " written by: " + componentType.Name + " written by: " +
string.Join(", ", writeMessageToEngines[componentType].Select(engine => engine.GetType().Name)); 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); throw new EngineWriteConflictException(errorString);
} }

View File

@ -141,12 +141,12 @@ namespace Tests
public class MultipleEngineWriteWithPriority public class MultipleEngineWriteWithPriority
{ {
struct SetMessage : IMessage struct SetMessage : IMessage
{ {
public Entity entity; public Entity entity;
} }
struct AComponent : IComponent struct AComponent : IComponent
{ {
public int myInt; public int myInt;
} }
@ -156,7 +156,7 @@ namespace Tests
[WritesPending(typeof(AComponent))] [WritesPending(typeof(AComponent))]
class AEngine : Engine class AEngine : Engine
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var setMessage in ReadMessages<SetMessage>()) foreach (var setMessage in ReadMessages<SetMessage>())
{ {
@ -170,13 +170,84 @@ namespace Tests
[WritesPending(typeof(AComponent))] [WritesPending(typeof(AComponent))]
class BEngine : Engine class BEngine : Engine
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var setMessage in ReadMessages<SetMessage>()) foreach (var setMessage in ReadMessages<SetMessage>())
{ {
SetComponent(setMessage.entity, new AComponent { myInt = 1 }); SetComponent(setMessage.entity, new AComponent { myInt = 1 });
} }
} }
}
static AComponent resultComponent;
[ReadsPending(typeof(AComponent))]
class ReadComponentEngine : Engine
{
public override void Update(double dt)
{
resultComponent = ReadComponent<AComponent>().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<SetMessage>())
{
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<SetMessage>())
{
SetComponent(setMessage.entity, new AComponent { myInt = 1 });
}
}
} }
static AComponent resultComponent; static AComponent resultComponent;
@ -218,7 +289,7 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
} }
} }
@ -435,7 +506,7 @@ namespace Tests
resultMessages.Should().BeEmpty(); resultMessages.Should().BeEmpty();
world.Update(0.25); world.Update(0.25);
resultMessages.Should().NotBeEmpty(); resultMessages.Should().NotBeEmpty();
resultMessages.First().Should().BeOfType<AMessage>(); resultMessages.First().Should().BeOfType<AMessage>();
} }