removed all component ID stuff

pull/5/head
Evan Hemsley 2019-12-05 14:59:55 -08:00
parent a4c3040239
commit 5513402573
13 changed files with 170 additions and 167 deletions

View File

@ -6,82 +6,23 @@ namespace Encompass
{
internal class ComponentStore
{
interface IComponentStore
private Dictionary<Type, TypedComponentStore> Stores = new Dictionary<Type, TypedComponentStore>();
public IEnumerable<(Type, TypedComponentStore)> StoresEnumerable()
{
T All<T>() where T : struct, IComponent;
}
abstract class TypedComponentStore
{
public abstract int Count { get; }
public abstract bool Has(Entity entity);
public abstract bool Remove(Entity entity);
public abstract void Clear();
}
class TypedComponentStore<TComponent> : TypedComponentStore where TComponent : struct, IComponent
{
private readonly Dictionary<Entity, TComponent> store = new Dictionary<Entity, TComponent>();
private readonly Dictionary<Entity, int> priorities = new Dictionary<Entity, int>();
public override int Count { get => store.Count; }
public TComponent Get(Entity entity)
foreach (var entry in Stores)
{
return store[entity];
}
public void Set(Entity entity, TComponent component)
{
store[entity] = component;
}
public void Set(Entity entity, TComponent component, int priority)
{
if (!priorities.ContainsKey(entity) || priority < priorities[entity]) {
store[entity] = component;
}
}
public override bool Has(Entity entity)
{
return store.ContainsKey(entity);
}
public override void Clear()
{
store.Clear();
}
public IEnumerable<(Entity, TComponent)> All()
{
return store.Select(kvp => (kvp.Key, kvp.Value));
}
// public override IEnumerable<T> All<T>()
// {
// return store.Values.Cast<T>();
// }
public override bool Remove(Entity entity)
{
throw new NotImplementedException();
yield return (entry.Key, entry.Value);
}
}
private readonly Dictionary<Type, TypedComponentStore> Stores = new Dictionary<Type, TypedComponentStore>();
public void RegisterComponentType<TComponent>() where TComponent : struct, IComponent
private TypedComponentStore<TComponent> Lookup<TComponent>() where TComponent : struct, IComponent
{
if (!Stores.ContainsKey(typeof(TComponent)))
{
var store = new TypedComponentStore<TComponent>();
Stores.Add(typeof(TComponent), store);
}
}
private TypedComponentStore<TComponent> Lookup<TComponent>() where TComponent : struct, IComponent
{
return Stores[typeof(TComponent)] as TypedComponentStore<TComponent>;
}
@ -105,9 +46,9 @@ namespace Encompass
Lookup<TComponent>().Set(entity, component);
}
public void Set<TComponent>(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent
public bool Set<TComponent>(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent
{
Lookup<TComponent>().Set(entity, component, priority);
return Lookup<TComponent>().Set(entity, component, priority);
}
public void Remove<TComponent>(Entity entity) where TComponent : struct, IComponent
@ -133,6 +74,17 @@ namespace Encompass
// return Lookup<TComponent>().All<TComponent>();
// }
public IEnumerable<(Entity, Type, IComponent)> AllInterfaceTyped()
{
foreach (var store in Stores.Values)
{
foreach (var thing in store.AllInterfaceTyped())
{
yield return thing;
}
}
}
public IEnumerable<(Entity, TComponent)> All<TComponent>() where TComponent : struct, IComponent
{
return Lookup<TComponent>().All();
@ -150,5 +102,10 @@ namespace Encompass
store.Clear();
}
}
public void SwapWith(ComponentStore other)
{
(Stores, other.Stores) = (other.Stores, Stores);
}
}
}

View File

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Encompass
{
internal abstract class TypedComponentStore
{
public abstract int Count { get; }
public abstract IEnumerable<(Entity, Type, IComponent)> AllInterfaceTyped();
public abstract bool Has(Entity entity);
public abstract void Remove(Entity entity);
public abstract void Clear();
}
internal class TypedComponentStore<TComponent> : TypedComponentStore where TComponent : struct, IComponent
{
private readonly Dictionary<Entity, TComponent> store = new Dictionary<Entity, TComponent>();
private readonly Dictionary<Entity, int> priorities = new Dictionary<Entity, int>();
public override int Count { get => store.Count; }
public TComponent Get(Entity entity)
{
return store[entity];
}
public void Set(Entity entity, TComponent component)
{
store[entity] = component;
}
public bool Set(Entity entity, TComponent component, int priority)
{
if (!priorities.ContainsKey(entity) || priority < priorities[entity]) {
store[entity] = component;
return true;
}
return false;
}
public override bool Has(Entity entity)
{
return store.ContainsKey(entity);
}
public override void Clear()
{
store.Clear();
}
public IEnumerable<(Entity, TComponent)> All()
{
return store.Select(kvp => (kvp.Key, kvp.Value));
}
public override IEnumerable<(Entity, Type, IComponent)> AllInterfaceTyped()
{
return store.Select(kvp => (kvp.Key, typeof(TComponent), (IComponent)kvp.Value));
}
// public override IEnumerable<T> All<T>()
// {
// return store.Values.Cast<T>();
// }
public override void Remove(Entity entity)
{
store.Remove(entity);
priorities.Remove(entity);
}
}
}

View File

@ -9,41 +9,25 @@ namespace Encompass
internal class ComponentManager
{
private readonly DrawLayerManager drawLayerManager;
private readonly ComponentMessageManager componentMessageManager;
private readonly ComponentStore componentStore = new ComponentStore();
private readonly Dictionary<(Entity, Type), IComponent> componentWriteData = new Dictionary<(Entity, Type), IComponent>();
private readonly Dictionary<(Entity, Type), int> componentWritePriorities = new Dictionary<(Entity, Type), int>();
private readonly HashSet<Entity> entitiesMarkedForRemoval = new HashSet<Entity>();
public ComponentManager(DrawLayerManager drawLayerManager)
public ComponentManager(DrawLayerManager drawLayerManager, ComponentMessageManager componentMessageManager)
{
this.drawLayerManager = drawLayerManager;
this.componentMessageManager = componentMessageManager;
}
internal void MarkComponentForWrite<TComponent>(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent
internal void SetComponentStore(ComponentStore componentStore)
{
componentStore.RegisterComponentType<TComponent>();
if (componentWriteData.ContainsKey((entity, typeof(TComponent))))
{
var currentPriority = componentWritePriorities[(entity, typeof(TComponent))];
if (priority < currentPriority)
{
componentWriteData[(entity, typeof(TComponent))] = component;
componentWritePriorities[(entity, typeof(TComponent))] = priority;
}
}
else
{
componentWriteData.Add((entity, typeof(TComponent)), component);
componentWritePriorities[(entity, typeof(TComponent))] = priority;
}
this.componentStore.SwapWith(componentStore);
}
internal void RegisterDrawableComponent<TComponent>(Guid componentID, TComponent component) where TComponent : IDrawableComponent
internal void RegisterDrawableComponent<TComponent>(Entity entity, TComponent component, int layer) where TComponent : struct, IComponent
{
drawLayerManager.RegisterComponentWithLayer(componentID, component.Layer);
drawLayerManager.RegisterComponentWithLayer(entity, component, layer);
}
internal void AddComponent<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
@ -53,16 +37,12 @@ namespace Encompass
internal void WriteComponents()
{
foreach (var keyValuePair in componentWriteData)
{
var (entity, type) = keyValuePair.Key;
var component = keyValuePair.Value;
componentStore.SwapWith(componentMessageManager.ComponentStore);
}
AddComponent(entity, component);
}
componentWriteData.Clear();
componentWritePriorities.Clear();
internal IEnumerable<(TComponent, Entity)> GetComponentsIncludingEntity<TComponent>() where TComponent : struct, IComponent
{
return componentStore.All<TComponent>().Select(pair => (pair.Item2, pair.Item1));
}
internal IEnumerable<TComponent> GetComponentsByType<TComponent>() where TComponent : struct, IComponent
@ -95,7 +75,7 @@ namespace Encompass
foreach (var entity in entitiesMarkedForRemoval)
{
componentStore.Remove(entity);
drawLayerManager.UnRegisterComponentWithLayer(entity);
drawLayerManager.UnRegisterEntityWithLayer(entity);
}
entitiesMarkedForRemoval.Clear();

View File

@ -14,6 +14,8 @@ namespace Encompass
private readonly Dictionary<Type, Dictionary<Entity, int>> typeToEntityToPendingComponentPriority = new Dictionary<Type, Dictionary<Entity, int>>();
public ComponentStore ComponentStore { get => componentStore; }
internal void ClearMessages()
{
componentStore.ClearAll();
@ -35,9 +37,10 @@ namespace Encompass
internal void AddPendingComponentMessage<TComponent>(PendingComponentMessage<TComponent> pendingComponentMessage) where TComponent : struct, IComponent
{
RegisterExistingOrPendingComponentMessage(pendingComponentMessage.entity, pendingComponentMessage.component);
pendingComponentStore.Set(pendingComponentMessage.entity, pendingComponentMessage.component, pendingComponentMessage.priority);
if (pendingComponentStore.Set(pendingComponentMessage.entity, pendingComponentMessage.component, pendingComponentMessage.priority))
{
RegisterExistingOrPendingComponentMessage(pendingComponentMessage.entity, pendingComponentMessage.component);
}
}
private void RegisterExistingOrPendingComponentMessage<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent

View File

@ -7,11 +7,12 @@ namespace Encompass
internal class DrawLayerManager
{
private readonly SortedList<int, int> layerOrder = new SortedList<int, int>();
private readonly ComponentStore componentStore = new ComponentStore();
private readonly Dictionary<int, HashSet<Guid>> layerIndexToComponentIDs = new Dictionary<int, HashSet<Guid>>();
private readonly Dictionary<int, ComponentStore> layerIndexToComponentStore = new Dictionary<int, ComponentStore>();
private readonly Dictionary<int, HashSet<GeneralRenderer>> layerIndexToGeneralRenderers = new Dictionary<int, HashSet<GeneralRenderer>>();
private readonly Dictionary<Guid, int> componentIDToLayerIndex = new Dictionary<Guid, int>();
private readonly Dictionary<Type, Dictionary<Entity, int>> typeToEntityToLayer = new Dictionary<Type, Dictionary<Entity, int>>();
public IEnumerable<int> LayerOrder { get { return layerOrder.Values; } }
@ -49,23 +50,23 @@ namespace Encompass
RegisterGeneralRendererWithLayer(renderer, newLayer);
}
public void RegisterComponentWithLayer(Guid id, int layer)
public void RegisterComponentWithLayer<TComponent>(Entity entity, TComponent component, int layer) where TComponent : struct, IComponent
{
if (componentIDToLayerIndex.ContainsKey(id)) { UnRegisterComponentWithLayer(id); }
if (typeToEntityToLayer[typeof(TComponent)].ContainsKey(entity)) { UnRegisterComponentWithLayer(entity, component); }
if (layerIndexToComponentIDs.ContainsKey(layer))
if (layerIndexToComponentStore.ContainsKey(layer))
{
var set = layerIndexToComponentIDs[layer];
set.Add(id);
var set = layerIndexToComponentStore[layer];
set.Set<TComponent>(entity, component);
}
else
{
var set = new HashSet<Guid>();
layerIndexToComponentIDs.Add(layer, set);
set.Add(id);
var set = new ComponentStore();
layerIndexToComponentStore.Add(layer, set);
set.Set<TComponent>(entity, component);
}
componentIDToLayerIndex[id] = layer;
typeToEntityToLayer[typeof(TComponent)].Add(entity, layer);
if (!layerOrder.ContainsKey(layer))
{
@ -73,21 +74,19 @@ namespace Encompass
}
}
public void UnRegisterComponentWithLayer(Entity entity)
public void UnRegisterComponentWithLayer<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
{
if (componentIDToLayerIndex.ContainsKey(id))
if (typeToEntityToLayer[typeof(TComponent)].ContainsKey(entity))
{
var layer = componentIDToLayerIndex[id];
layerIndexToComponentIDs[layer].Remove(id);
var layer = typeToEntityToLayer[typeof(TComponent)][entity];
layerIndexToComponentStore[layer].Remove<TComponent>(entity);
}
componentIDToLayerIndex.Remove(id);
typeToEntityToLayer[typeof(TComponent)].Remove(entity);
}
public IEnumerable<Guid> ComponentIDsByLayer(int layer)
public void UnRegisterEntityWithLayer(Entity entity)
{
return layerIndexToComponentIDs.ContainsKey(layer) ?
layerIndexToComponentIDs[layer] :
Enumerable.Empty<Guid>();
componentStore.Remove(entity);
}
public IEnumerable<GeneralRenderer> GeneralRenderersByLayer(int layer)
@ -96,5 +95,10 @@ namespace Encompass
layerIndexToGeneralRenderers[layer] :
Enumerable.Empty<GeneralRenderer>();
}
public IEnumerable<(Entity, Type, IComponent)> AllInLayer(int layer)
{
return layerIndexToComponentStore[layer].AllInterfaceTyped();
}
}
}

View File

@ -215,6 +215,11 @@ namespace Encompass
return ReadComponentsHelper<TComponent>().Select((tuple) => (tuple.Item2, tuple.Item1));
}
internal IEnumerable<(TComponent, Entity)> InternalRead<TComponent>() where TComponent : struct, IComponent
{
return componentManager.GetComponentsIncludingEntity<TComponent>();
}
private (Entity, TComponent) ReadComponentHelper<TComponent>() where TComponent : struct, IComponent
{
var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage<TComponent>));
@ -397,8 +402,6 @@ namespace Encompass
{
var priority = writePriorities.ContainsKey(typeof(TComponent)) ? writePriorities[typeof(TComponent)] : 0;
componentManager.MarkComponentForWrite(entity, component, priority);
if (!sendTypes.Contains(typeof(ComponentWriteMessage<TComponent>)))
{
throw new IllegalWriteException("Engine {0} tried to update undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
@ -415,7 +418,7 @@ namespace Encompass
if (component is IDrawableComponent drawableComponent)
{
componentManager.RegisterDrawableComponent(componentID, drawableComponent);
componentManager.RegisterDrawableComponent<TComponent>(entity, component, drawableComponent.Layer);
}
}
@ -519,22 +522,13 @@ namespace Encompass
return ReadMessages<TMessage>().Any();
}
/// <summary>
/// Destroys the Entity with the specified ID. This also removes all of the Components associated with the Entity.
/// Entity destruction takes place after all the Engines have been processed by World Update.
/// </summary>
internal void Destroy(Guid entityID)
{
entityManager.MarkForDestroy(entityID);
}
/// <summary>
/// Destroys the specified Entity. This also removes all of the Components associated with the Entity.
/// Entity destruction takes place after all the Engines have been processed by World Update.
/// </summary>
protected void Destroy(Entity entity)
{
entityManager.MarkForDestroy(entity.ID);
entityManager.MarkForDestroy(entity);
}
/// <summary>

View File

@ -9,7 +9,7 @@ namespace Encompass
public override void Update(double dt)
{
foreach (var (component, entity) in ReadComponentsIncludingEntity<TComponent>())
foreach (var (component, entity) in InternalRead<TComponent>())
{
ComponentMessage<TComponent> componentMessage;
componentMessage.entity = entity;

View File

@ -37,16 +37,10 @@ namespace Encompass
{
foreach (var layer in drawLayerManager.LayerOrder)
{
var componentIDSet = drawLayerManager.ComponentIDsByLayer(layer);
var generalRendererSet = drawLayerManager.GeneralRenderersByLayer(layer);
foreach (var componentID in componentIDSet)
foreach (var (entity, componentType, component) in drawLayerManager.AllInLayer(layer))
{
var componentType = componentManager.GetComponentTypeByID(componentID);
var component = componentManager.GetComponentByID(componentType, componentID);
var entityID = componentManager.GetEntityIDByComponentID(componentID);
var entity = entityManager.GetEntity(entityID);
if (drawComponentTypeToOrderedRenderer.ContainsKey(componentType))
{
var internalRenderAction = drawComponentTypeToOrderedRenderer[componentType];

View File

@ -19,11 +19,6 @@ namespace Encompass
this.componentManager = componentManager;
}
internal Guid GetEntityIDByComponentID(Guid componentID)
{
return componentManager.GetEntityIDByComponentID(componentID);
}
internal Entity GetEntity(Guid entityID)
{
return entityManager.GetEntity(entityID);
@ -41,12 +36,12 @@ namespace Encompass
protected IEnumerable<TComponent> ReadComponents<TComponent>() where TComponent : struct, IComponent
{
return componentManager.GetComponentsByType<TComponent>().Select(tuple => tuple.Item2);
return componentManager.GetComponentsByType<TComponent>();
}
protected IEnumerable<(TComponent, Entity)> ReadComponentsIncludingEntity<TComponent>() where TComponent : struct, IComponent
{
return componentManager.GetComponentsByType<TComponent>().Select(tuple => (tuple.Item2, GetEntity(GetEntityIDByComponentID(tuple.Item1))));
return componentManager.GetComponentsIncludingEntity<TComponent>();
}
protected TComponent ReadComponent<TComponent>() where TComponent : struct, IComponent
@ -61,7 +56,7 @@ namespace Encompass
protected TComponent GetComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
{
return componentManager.GetComponentByEntityAndType<TComponent>(entity).Item2;
return componentManager.GetComponentByEntityAndType<TComponent>(entity);
}
protected bool HasComponent<TComponent>(Entity entity) where TComponent : struct, IComponent

View File

@ -56,11 +56,12 @@ namespace Encompass
}
messageManager.ClearMessages();
componentMessageManager.ClearMessages();
entityManager.DestroyMarkedEntities();
componentManager.RemoveMarkedComponents();
componentManager.WriteComponents();
componentManager.RemoveMarkedComponents();
componentMessageManager.ClearMessages();
}
/// <summary>

View File

@ -20,6 +20,7 @@ namespace Encompass
{
private readonly List<Engine> engines = new List<Engine>();
private readonly DirectedGraph<Engine, Unit> engineGraph = GraphBuilder.DirectedGraph<Engine>();
private readonly ComponentStore componentStore = new ComponentStore();
private readonly ComponentManager componentManager;
private readonly EntityManager entityManager;
@ -39,9 +40,9 @@ namespace Encompass
{
drawLayerManager = new DrawLayerManager();
timeManager = new TimeManager();
componentManager = new ComponentManager(drawLayerManager);
messageManager = new MessageManager(timeManager);
componentMessageManager = new ComponentMessageManager();
componentManager = new ComponentManager(drawLayerManager, componentMessageManager);
messageManager = new MessageManager(timeManager);
entityManager = new EntityManager(componentManager);
renderManager = new RenderManager(componentManager, drawLayerManager, entityManager);
}
@ -73,12 +74,13 @@ namespace Encompass
/// <summary>
/// Sets Component data for the specified Component Type on the specified Entity.
/// </summary>
public void SetComponent<TComponent>(Entity entity, TComponent component, int priority = 0) where TComponent : struct, IComponent
public void SetComponent<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
{
componentManager.MarkComponentForWrite(entity, component, priority);
componentStore.Set(entity, component);
if (component is IDrawableComponent drawableComponent)
{
componentManager.RegisterDrawableComponent(componentID, drawableComponent);
componentManager.RegisterDrawableComponent(entity, component, drawableComponent.Layer);
}
}
@ -346,8 +348,7 @@ namespace Encompass
renderManager
);
componentManager.RemoveMarkedComponents();
componentManager.WriteComponents();
componentManager.SetComponentStore(componentStore);
return world;
}

View File

@ -89,16 +89,16 @@ namespace Tests
worldBuilder.AddEngine(new ReadMockComponentEngine());
var entity = worldBuilder.CreateEntity();
worldBuilder.SetComponent(entity, new MockComponent { myInt = 20, myString = "what" }, 2);
worldBuilder.SetComponent(entity, new MockComponent { myInt = 50, myString = "hi" }, 0);
worldBuilder.SetComponent(entity, new MockComponent { myInt = 40, myString = "wassup" }, 1);
worldBuilder.SetComponent(entity, new MockComponent { myInt = 20, myString = "what" });
worldBuilder.SetComponent(entity, new MockComponent { myInt = 50, myString = "hi" });
worldBuilder.SetComponent(entity, new MockComponent { myInt = 40, myString = "wassup" });
var world = worldBuilder.Build();
world.Update(0.01);
Assert.That(gottenMockComponent.myInt, Is.EqualTo(50));
Assert.That(gottenMockComponent.myString, Is.EqualTo("hi"));
Assert.That(gottenMockComponent.myInt, Is.EqualTo(40));
Assert.That(gottenMockComponent.myString, Is.EqualTo("wassup"));
}
[Reads(typeof(MockComponent))]

View File

@ -557,7 +557,7 @@ namespace Tests
world.Update(0.01);
Assert.That(results, Does.Not.Contain((mockComponent, entity)));
Assert.That(results, Does.Not.Contain((mockComponent, entity)));
Assert.That(results, Does.Not.Contain((mockComponent, entityB)));
Assert.That(results, Does.Contain((mockComponent, entityC)));
}