MoonTools.ECS/src/EntityStorage.cs

101 lines
2.4 KiB
C#
Raw Normal View History

using System.Collections.Generic;
namespace MoonTools.ECS
2022-03-05 02:01:44 +00:00
{
2022-04-08 05:52:03 +00:00
internal class EntityStorage
2022-03-05 02:01:44 +00:00
{
private int nextID = 0;
2022-12-03 07:43:54 +00:00
// FIXME: why is this duplicated?
private readonly Stack<int> availableIDs = new Stack<int>();
private readonly HashSet<int> availableIDHash = new HashSet<int>();
2022-03-05 02:01:44 +00:00
2022-12-03 07:43:54 +00:00
private Dictionary<int, HashSet<int>> EntityToComponentTypeIndices = new Dictionary<int, HashSet<int>>();
private Dictionary<int, HashSet<int>> EntityToRelationTypeIndices = new Dictionary<int, HashSet<int>>();
2022-04-08 05:52:03 +00:00
public Entity Create()
{
2022-12-03 07:43:54 +00:00
var entity = new Entity(NextID());
EntityToComponentTypeIndices.TryAdd(entity.ID, new HashSet<int>());
EntityToRelationTypeIndices.TryAdd(entity.ID, new HashSet<int>());
return entity;
2022-04-08 05:52:03 +00:00
}
2022-04-08 05:52:03 +00:00
public bool Exists(in Entity entity)
{
return Taken(entity.ID);
2022-04-08 05:52:03 +00:00
}
public void Destroy(in Entity entity)
{
2022-12-03 07:43:54 +00:00
EntityToComponentTypeIndices[entity.ID].Clear();
EntityToRelationTypeIndices[entity.ID].Clear();
Release(entity.ID);
}
2022-12-03 07:43:54 +00:00
// Returns true if the component is new.
public bool SetComponent(int entityID, int storageIndex)
{
2022-12-03 07:43:54 +00:00
return EntityToComponentTypeIndices[entityID].Add(storageIndex);
}
2022-12-03 07:43:54 +00:00
public bool HasComponent(int entityID, int storageIndex)
{
2022-12-03 07:43:54 +00:00
return EntityToComponentTypeIndices[entityID].Contains(storageIndex);
}
// Returns true if the component existed.
public bool RemoveComponent(int entityID, int storageIndex)
{
return EntityToComponentTypeIndices[entityID].Remove(storageIndex);
}
public void AddRelation(int entityID, int relationIndex)
{
EntityToRelationTypeIndices[entityID].Add(relationIndex);
}
public void RemoveRelation(int entityId, int relationIndex)
{
EntityToRelationTypeIndices[entityId].Remove(relationIndex);
}
// TODO: should these ints be ID types?
public IEnumerable<int> ComponentTypeIndices(int entityID)
{
return EntityToComponentTypeIndices[entityID];
}
public IEnumerable<int> RelationTypeIndices(int entityID)
{
return EntityToRelationTypeIndices[entityID];
}
private int NextID()
{
if (availableIDs.Count > 0)
{
var id = availableIDs.Pop();
availableIDHash.Remove(id);
return id;
}
else
{
var id = nextID;
nextID += 1;
return id;
}
}
private bool Taken(int id)
{
return !availableIDHash.Contains(id) && id < nextID;
}
private void Release(int id)
{
availableIDs.Push(id);
availableIDHash.Add(id);
2022-04-08 05:52:03 +00:00
}
2022-03-05 02:01:44 +00:00
}
}