encompass-cs/encompass-cs/Collections/TypedComponentStore.cs

108 lines
3.4 KiB
C#
Raw Normal View History

2019-12-05 22:59:55 +00:00
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
2019-12-05 22:59:55 +00:00
namespace Encompass
{
internal abstract class TypedComponentStore
{
public abstract int Count { get; }
public abstract bool Has(int entity);
public abstract bool Remove(int entity, int priority);
public abstract void ForceRemove(int entity);
2019-12-05 22:59:55 +00:00
public abstract void Clear();
public abstract void ClearPriorities();
2019-12-05 22:59:55 +00:00
}
2020-03-20 22:45:58 +00:00
internal class TypedComponentStore<TComponent> : TypedComponentStore where TComponent : unmanaged
2019-12-05 22:59:55 +00:00
{
2020-03-20 07:09:57 +00:00
private readonly Dictionary<int, int> _indices = new Dictionary<int, int>(512);
private readonly Dictionary<int, int> _priorities = new Dictionary<int, int>(512);
private readonly TComponent[] _components = new TComponent[512];
private readonly IDManager _idManager = new IDManager();
2019-12-05 22:59:55 +00:00
2020-03-20 07:09:57 +00:00
public override int Count { get => _indices.Count; }
2019-12-05 22:59:55 +00:00
public unsafe ref readonly TComponent Get(int entityID)
2019-12-05 22:59:55 +00:00
{
2020-03-20 07:09:57 +00:00
if (!_indices.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); }
ref var refVal = ref _components[_indices[entityID]];
return ref Unsafe.AsRef<TComponent>(Unsafe.AsPointer(ref refVal));
2019-12-05 22:59:55 +00:00
}
public unsafe void Set(int entityID, TComponent component)
2019-12-05 22:59:55 +00:00
{
InternalSet(entityID, component);
2019-12-05 22:59:55 +00:00
}
public unsafe bool Set(int entityID, TComponent component, int priority)
2019-12-05 22:59:55 +00:00
{
2020-03-20 07:09:57 +00:00
if (!_priorities.ContainsKey(entityID) || priority < _priorities[entityID])
{
InternalSet(entityID, component);
2020-03-20 07:09:57 +00:00
_priorities[entityID] = priority;
2019-12-05 22:59:55 +00:00
return true;
}
return false;
}
private unsafe void InternalSet(int entityID, TComponent component)
{
2020-03-20 07:09:57 +00:00
if (!_indices.ContainsKey(entityID))
{
2020-03-20 07:09:57 +00:00
_indices[entityID] = _idManager.NextID();
}
2020-03-20 09:28:10 +00:00
_components[_indices[entityID]] = Unsafe.AsRef<TComponent>(Unsafe.AsPointer(ref component));
}
public override bool Remove(int entityID, int priority)
{
2020-03-20 07:09:57 +00:00
if (!_priorities.ContainsKey(entityID) || priority < _priorities[entityID])
{
2020-03-20 07:09:57 +00:00
_priorities[entityID] = priority;
2020-03-20 09:28:10 +00:00
ForceRemove(entityID);
return true;
}
return false;
}
public override void ForceRemove(int entityID)
{
2020-03-20 07:09:57 +00:00
_indices.Remove(entityID);
_priorities.Remove(entityID);
_idManager.Free(entityID);
}
public override bool Has(int entityID)
2019-12-05 22:59:55 +00:00
{
2020-03-20 07:09:57 +00:00
return _indices.ContainsKey(entityID);
2019-12-05 22:59:55 +00:00
}
public override void Clear()
{
2020-03-20 07:09:57 +00:00
foreach (var entityID in _indices.Keys)
{
_idManager.Free(entityID);
}
2020-03-20 07:09:57 +00:00
_indices.Clear();
_priorities.Clear();
2019-12-05 22:59:55 +00:00
}
public override void ClearPriorities()
{
2020-03-20 07:09:57 +00:00
_priorities.Clear();
}
public IEnumerable<(TComponent, int)> All()
2019-12-05 22:59:55 +00:00
{
2020-03-20 07:09:57 +00:00
foreach (var kvp in _indices)
2019-12-17 04:40:15 +00:00
{
2020-03-20 07:09:57 +00:00
yield return (_components[kvp.Value], kvp.Key);
2019-12-17 04:40:15 +00:00
}
2019-12-05 22:59:55 +00:00
}
}
}