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

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

@ -208,6 +208,77 @@ namespace Tests
} }
} }
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;
[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 EngineMessageSelfCycle public class EngineMessageSelfCycle
{ {
struct AMessage : IMessage { } struct AMessage : IMessage { }