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

113 lines
3.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Encompass
{
internal abstract class TypedComponentStore
{
public abstract int Count { get; }
public abstract IEnumerable<(int, Type, IComponent)> AllInterfaceTyped();
public abstract bool Has(int entity);
public abstract bool Remove(int entity, int priority);
public abstract void ForceRemove(int entity);
public abstract void Clear();
public abstract void ClearPriorities();
}
internal class TypedComponentStore<TComponent> : TypedComponentStore where TComponent : struct, IComponent
{
private readonly Dictionary<int, int> indices = new Dictionary<int, int>(512);
private readonly Dictionary<int, int> priorities = new Dictionary<int, int>(512);
private TComponent[] components = new TComponent[512];
private readonly IDManager _idManager = new IDManager();
public override int Count { get => indices.Count; }
public unsafe ref readonly 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); }
ref var refVal = ref components[indices[entityID]];
return ref Unsafe.AsRef<TComponent>(Unsafe.AsPointer(ref refVal));
}
public unsafe void Set(int entityID, TComponent component)
{
InternalSet(entityID, component);
}
public unsafe bool Set(int entityID, TComponent component, int priority)
{
if (!priorities.ContainsKey(entityID) || priority < priorities[entityID])
{
InternalSet(entityID, component);
priorities[entityID] = priority;
return true;
}
return false;
}
private unsafe void InternalSet(int entityID, TComponent component)
{
var index = _idManager.NextID();
var ptr = Unsafe.AsPointer(ref component);
indices[entityID] = index;
components[index] = Unsafe.AsRef<TComponent>(ptr);
}
public override bool Remove(int entityID, int priority)
{
if (!priorities.ContainsKey(entityID) || priority < priorities[entityID])
{
priorities[entityID] = priority;
indices.Remove(entityID);
priorities.Remove(entityID);
_idManager.Free(entityID);
return true;
}
return false;
}
public override void ForceRemove(int entityID)
{
indices.Remove(entityID);
priorities.Remove(entityID);
_idManager.Free(entityID);
}
public override bool Has(int entityID)
{
return indices.ContainsKey(entityID);
}
public override void Clear()
{
indices.Clear();
priorities.Clear();
}
public override void ClearPriorities()
{
priorities.Clear();
}
public IEnumerable<(TComponent, int)> All()
{
foreach (var kvp in indices)
{
yield return (components[kvp.Value], kvp.Key);
}
}
public override IEnumerable<(int, Type, IComponent)> AllInterfaceTyped()
{
foreach (var kvp in indices)
{
yield return (kvp.Key, typeof(TComponent), (IComponent)components[kvp.Value]);
}
}
}
}