fixes various write priority related bugs

pull/5/head
Evan Hemsley 2019-12-06 00:36:54 -08:00
parent bb5173f4e4
commit 25b8dc6749
5 changed files with 43 additions and 14 deletions

View File

@ -34,6 +34,7 @@ namespace Encompass
{ {
if (!priorities.ContainsKey(entity) || priority < priorities[entity]) { if (!priorities.ContainsKey(entity) || priority < priorities[entity]) {
store[entity] = component; store[entity] = component;
priorities[entity] = priority;
return true; return true;
} }

View File

@ -38,12 +38,15 @@ namespace Encompass
existingComponentStore.Set(entity, component); existingComponentStore.Set(entity, component);
} }
internal void AddPendingComponent<TComponent>(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent internal bool AddPendingComponent<TComponent>(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent
{ {
if (pendingComponentStore.Set(entity, component, priority)) if (pendingComponentStore.Set(entity, component, priority))
{ {
RegisterExistingOrPendingComponentMessage(entity, component); RegisterExistingOrPendingComponentMessage(entity, component);
return true;
} }
return false;
} }
private void RegisterExistingOrPendingComponentMessage<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent private void RegisterExistingOrPendingComponentMessage<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
@ -52,9 +55,9 @@ namespace Encompass
UpToDateComponentStore.Set(entity, component); UpToDateComponentStore.Set(entity, component);
} }
public void UpdateComponent<TComponent>(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent public bool UpdateComponent<TComponent>(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent
{ {
UpToDateComponentStore.Set<TComponent>(entity, component, priority); return UpToDateComponentStore.Set<TComponent>(entity, component, priority);
} }
// general component reads by type // general component reads by type
@ -90,7 +93,7 @@ namespace Encompass
internal (Entity, TComponent) ReadFirstPendingComponentByType<TComponent>() where TComponent : struct, IComponent internal (Entity, TComponent) ReadFirstPendingComponentByType<TComponent>() where TComponent : struct, IComponent
{ {
if (!SomeExistingComponent<TComponent>()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } if (!SomePendingComponent<TComponent>()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); }
return ReadPendingComponentsByType<TComponent>().First(); return ReadPendingComponentsByType<TComponent>().First();
} }

View File

@ -22,6 +22,7 @@ namespace Encompass
internal readonly HashSet<Type> writeTypes = new HashSet<Type>(); internal readonly HashSet<Type> writeTypes = new HashSet<Type>();
internal readonly HashSet<Type> writePendingTypes = new HashSet<Type>(); internal readonly HashSet<Type> writePendingTypes = new HashSet<Type>();
internal readonly Dictionary<Type, int> writePriorities = new Dictionary<Type, int>(); internal readonly Dictionary<Type, int> writePriorities = new Dictionary<Type, int>();
internal readonly int defaultWritePriority = 0;
/// <summary> /// <summary>
/// If false, the Engine will ignore time dilation. /// If false, the Engine will ignore time dilation.
@ -51,6 +52,13 @@ namespace Encompass
writePendingTypes = activatesAttribute.writePendingTypes; writePendingTypes = activatesAttribute.writePendingTypes;
} }
var defaultWritePriorityAttribute = GetType().GetCustomAttribute<DefaultWritePriority>(false);
if (defaultWritePriorityAttribute != null)
{
defaultWritePriority = defaultWritePriorityAttribute.writePriority;
}
foreach (var writesAttribute in GetType().GetCustomAttributes<Writes>(false)) foreach (var writesAttribute in GetType().GetCustomAttributes<Writes>(false))
{ {
writeTypes.UnionWith(writesAttribute.writeTypes); writeTypes.UnionWith(writesAttribute.writeTypes);
@ -397,23 +405,24 @@ namespace Encompass
/// </exception> /// </exception>
protected void SetComponent<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent protected void SetComponent<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
{ {
var priority = writePriorities.ContainsKey(typeof(TComponent)) ? writePriorities[typeof(TComponent)] : 0; var priority = writePriorities.ContainsKey(typeof(TComponent)) ? writePriorities[typeof(TComponent)] : defaultWritePriority;
if (!writeTypes.Contains(typeof(TComponent))) if (!writeTypes.Contains(typeof(TComponent)))
{ {
throw new IllegalWriteException("Engine {0} tried to update undeclared Component {1}", GetType().Name, typeof(TComponent).Name); throw new IllegalWriteException("Engine {0} tried to update undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
} }
bool written;
if (writePendingTypes.Contains(typeof(TComponent))) if (writePendingTypes.Contains(typeof(TComponent)))
{ {
AddPendingComponent(entity, component, priority); written = AddPendingComponent(entity, component, priority);
} }
else else
{ {
componentUpdateManager.UpdateComponent(entity, component, priority); written = componentUpdateManager.UpdateComponent(entity, component, priority);
} }
if (component is IDrawableComponent drawableComponent) if (written && component is IDrawableComponent drawableComponent)
{ {
componentManager.RegisterDrawableComponent(entity, component, drawableComponent.Layer); componentManager.RegisterDrawableComponent(entity, component, drawableComponent.Layer);
} }
@ -471,9 +480,9 @@ namespace Encompass
componentUpdateManager.AddExistingComponent(entity, component); componentUpdateManager.AddExistingComponent(entity, component);
} }
internal void AddPendingComponent<TComponent>(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent internal bool AddPendingComponent<TComponent>(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent
{ {
componentUpdateManager.AddPendingComponent<TComponent>(entity, component, priority); return componentUpdateManager.AddPendingComponent<TComponent>(entity, component, priority);
} }
/// <summary> /// <summary>

View File

@ -131,7 +131,7 @@ namespace Encompass
senders.Add(engine); senders.Add(engine);
} }
foreach (var componentType in engine.readTypes.Union(engine.writeTypes)) foreach (var componentType in engine.readTypes.Union(engine.writeTypes).Union(engine.readPendingTypes))
{ {
RegisterComponent(componentType); RegisterComponent(componentType);
} }

View File

@ -223,14 +223,14 @@ namespace Tests
[Receives(typeof(SetMessage))] [Receives(typeof(SetMessage))]
[Writes(typeof(AComponent))] [Writes(typeof(AComponent))]
[WritesPending(typeof(AComponent))] [WritesPending(typeof(AComponent))]
[Encompass.DefaultWritePriority(1)] [Encompass.DefaultWritePriority(4)]
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>())
{ {
SetComponent(setMessage.entity, new AComponent { myInt = 0 }); SetComponent(setMessage.entity, new AComponent { myInt = 5 });
} }
} }
} }
@ -250,6 +250,20 @@ namespace Tests
} }
} }
[Receives(typeof(SetMessage))]
[Writes(typeof(AComponent), 2)]
[WritesPending(typeof(AComponent))]
class CEngine : Engine
{
public override void Update(double dt)
{
foreach (var setMessage in ReadMessages<SetMessage>())
{
SetComponent(setMessage.entity, new AComponent { myInt = 3 });
}
}
}
static AComponent resultComponent; static AComponent resultComponent;
[ReadsPending(typeof(AComponent))] [ReadsPending(typeof(AComponent))]
@ -267,6 +281,8 @@ namespace Tests
var worldBuilder = new WorldBuilder(); var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new AEngine()); worldBuilder.AddEngine(new AEngine());
worldBuilder.AddEngine(new BEngine()); worldBuilder.AddEngine(new BEngine());
worldBuilder.AddEngine(new CEngine());
worldBuilder.AddEngine(new ReadComponentEngine());
var entity = worldBuilder.CreateEntity(); var entity = worldBuilder.CreateEntity();
worldBuilder.SendMessage(new SetMessage { entity = entity }); worldBuilder.SendMessage(new SetMessage { entity = entity });
@ -275,7 +291,7 @@ namespace Tests
world.Update(0.01); world.Update(0.01);
Assert.That(resultComponent.myInt, Is.EqualTo(0)); Assert.That(resultComponent.myInt, Is.EqualTo(3));
} }
} }