contiguous component storage
continuous-integration/drone/push Build is passing Details

pull/3/head
Evan Hemsley 2020-03-22 17:03:18 -07:00
parent e4d4df9fdd
commit 61845d752a
1 changed files with 41 additions and 20 deletions

View File

@ -15,17 +15,18 @@ namespace Encompass
internal class TypedComponentStore<TComponent> : TypedComponentStore where TComponent : struct internal class TypedComponentStore<TComponent> : TypedComponentStore where TComponent : struct
{ {
private readonly Dictionary<int, int> _indices = new Dictionary<int, int>(512); private int _nextID = 0;
private readonly Dictionary<int, int> _priorities = new Dictionary<int, int>(512); private readonly Dictionary<int, int> _entityIDToStorageIndex = new Dictionary<int, int>(128);
private readonly TComponent[] _components = new TComponent[512]; // TODO: allow specify size private readonly Dictionary<int, int> _storageIndexToEntityID = new Dictionary<int, int>(128);
private readonly IDManager _idManager = new IDManager(); private readonly Dictionary<int, int> _priorities = new Dictionary<int, int>(128);
private TComponent[] _components = new TComponent[128];
public override int Count { get => _indices.Count; } public override int Count { get => _entityIDToStorageIndex.Count; }
public ref TComponent Get(int entityID) public ref TComponent Get(int entityID)
{ {
if (!_indices.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); } if (!_entityIDToStorageIndex.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); }
return ref _components[_indices[entityID]]; return ref _components[_entityIDToStorageIndex[entityID]];
} }
public void Set(int entityID, in TComponent component) public void Set(int entityID, in TComponent component)
@ -47,12 +48,18 @@ namespace Encompass
private void InternalSet(int entityID, in TComponent component) private void InternalSet(int entityID, in TComponent component)
{ {
if (!_indices.ContainsKey(entityID)) if (!_entityIDToStorageIndex.ContainsKey(entityID))
{ {
_indices[entityID] = _idManager.NextID(); var index = _nextID++;
if (index >= _components.Length)
{
System.Array.Resize(ref _components, _components.Length * 2);
}
_entityIDToStorageIndex[entityID] = index;
_storageIndexToEntityID[index] = entityID;
} }
_components[_indices[entityID]] = component; _components[_entityIDToStorageIndex[entityID]] = component;
} }
public override bool Remove(int entityID, int priority) public override bool Remove(int entityID, int priority)
@ -69,26 +76,40 @@ namespace Encompass
public override void ForceRemove(int entityID) public override void ForceRemove(int entityID)
{ {
if (_indices.ContainsKey(entityID)) if (_entityIDToStorageIndex.ContainsKey(entityID))
{ {
_idManager.Free(_indices[entityID]); var storageIndex = _entityIDToStorageIndex[entityID];
_indices.Remove(entityID); _entityIDToStorageIndex.Remove(entityID);
_storageIndexToEntityID.Remove(storageIndex);
_priorities.Remove(entityID); _priorities.Remove(entityID);
// move a component into the hole to maintain contiguous memory
if (_nextID > 1 && storageIndex != _nextID - 1)
{
var lastStorageIndex = _nextID - 1;
var lastEntityID = _storageIndexToEntityID[lastStorageIndex];
_storageIndexToEntityID.Remove(lastStorageIndex);
_entityIDToStorageIndex[lastEntityID] = storageIndex;
_storageIndexToEntityID[storageIndex] = lastEntityID;
_components[storageIndex] = _components[lastStorageIndex];
}
_nextID--;
} }
} }
public override bool Has(int entityID) public override bool Has(int entityID)
{ {
return _indices.ContainsKey(entityID); return _entityIDToStorageIndex.ContainsKey(entityID);
} }
public override void Clear() public override void Clear()
{ {
foreach (var mappedID in _indices.Values) _nextID = 0;
{ _entityIDToStorageIndex.Clear();
_idManager.Free(mappedID); _storageIndexToEntityID.Clear();
}
_indices.Clear();
_priorities.Clear(); _priorities.Clear();
} }
@ -99,7 +120,7 @@ namespace Encompass
public IEnumerable<(TComponent, int)> All() public IEnumerable<(TComponent, int)> All()
{ {
foreach (var kvp in _indices) foreach (var kvp in _entityIDToStorageIndex)
{ {
yield return (_components[kvp.Value], kvp.Key); yield return (_components[kvp.Value], kvp.Key);
} }