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]) {
store[entity] = component;
priorities[entity] = priority;
return true;
}

View File

@ -38,12 +38,15 @@ namespace Encompass
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))
{
RegisterExistingOrPendingComponentMessage(entity, component);
return true;
}
return false;
}
private void RegisterExistingOrPendingComponentMessage<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
@ -52,9 +55,9 @@ namespace Encompass
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
@ -90,7 +93,7 @@ namespace Encompass
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();
}

View File

@ -22,6 +22,7 @@ namespace Encompass
internal readonly HashSet<Type> writeTypes = new HashSet<Type>();
internal readonly HashSet<Type> writePendingTypes = new HashSet<Type>();
internal readonly Dictionary<Type, int> writePriorities = new Dictionary<Type, int>();
internal readonly int defaultWritePriority = 0;
/// <summary>
/// If false, the Engine will ignore time dilation.
@ -51,6 +52,13 @@ namespace Encompass
writePendingTypes = activatesAttribute.writePendingTypes;
}
var defaultWritePriorityAttribute = GetType().GetCustomAttribute<DefaultWritePriority>(false);
if (defaultWritePriorityAttribute != null)
{
defaultWritePriority = defaultWritePriorityAttribute.writePriority;
}
foreach (var writesAttribute in GetType().GetCustomAttributes<Writes>(false))
{
writeTypes.UnionWith(writesAttribute.writeTypes);
@ -397,23 +405,24 @@ namespace Encompass
/// </exception>
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)))
{
throw new IllegalWriteException("Engine {0} tried to update undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
}
bool written;
if (writePendingTypes.Contains(typeof(TComponent)))
{
AddPendingComponent(entity, component, priority);
written = AddPendingComponent(entity, component, priority);
}
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);
}
@ -471,9 +480,9 @@ namespace Encompass
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>

View File

@ -131,7 +131,7 @@ namespace Encompass
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);
}

View File

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