converting component storage to pack data and return refs
continuous-integration/drone/push Build is passing Details

pull/3/head
Evan Hemsley 2020-03-19 15:44:04 -07:00
parent 72a7f8bfbf
commit 98955f3048
6 changed files with 58 additions and 38 deletions

View File

@ -4,6 +4,11 @@ using System.Collections.Generic;
namespace Encompass namespace Encompass
{ {
public struct MutableComponentEntityPair<TComponent> where TComponent : struct, IComponent
{
public TComponent component;
}
internal class ComponentStore internal class ComponentStore
{ {
private Dictionary<Type, TypedComponentStore> Stores = new Dictionary<Type, TypedComponentStore>(512); private Dictionary<Type, TypedComponentStore> Stores = new Dictionary<Type, TypedComponentStore>(512);
@ -51,9 +56,9 @@ namespace Encompass
return ComponentBitSet.EntityBitArray(entityID); return ComponentBitSet.EntityBitArray(entityID);
} }
public TComponent Get<TComponent>(int entityID) where TComponent : struct, IComponent public ref readonly TComponent Get<TComponent>(int entityID) where TComponent : struct, IComponent
{ {
return Lookup<TComponent>().Get(entityID); return ref Lookup<TComponent>().Get(entityID);
} }
public virtual void Set<TComponent>(int entityID, TComponent component) where TComponent : struct, IComponent public virtual void Set<TComponent>(int entityID, TComponent component) where TComponent : struct, IComponent

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Encompass namespace Encompass
{ {
@ -16,27 +17,30 @@ namespace Encompass
internal class TypedComponentStore<TComponent> : TypedComponentStore where TComponent : struct, IComponent internal class TypedComponentStore<TComponent> : TypedComponentStore where TComponent : struct, IComponent
{ {
private readonly Dictionary<int, TComponent> store = new Dictionary<int, TComponent>(128); private readonly Dictionary<int, int> indices = new Dictionary<int, int>(512);
private readonly Dictionary<int, int> priorities = new Dictionary<int, int>(128); 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 => store.Count; } public override int Count { get => indices.Count; }
public TComponent Get(int entityID) public unsafe ref readonly TComponent Get(int entityID)
{ {
if (!store.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); } if (!indices.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); }
return store[entityID]; ref var refVal = ref components[indices[entityID]];
return ref Unsafe.AsRef<TComponent>(Unsafe.AsPointer(ref refVal));
} }
public void Set(int entityID, TComponent component) public unsafe void Set(int entityID, TComponent component)
{ {
store[entityID] = component; InternalSet(entityID, component);
} }
public bool Set(int entityID, TComponent component, int priority) public unsafe bool Set(int entityID, TComponent component, int priority)
{ {
if (!priorities.ContainsKey(entityID) || priority < priorities[entityID]) if (!priorities.ContainsKey(entityID) || priority < priorities[entityID])
{ {
store[entityID] = component; InternalSet(entityID, component);
priorities[entityID] = priority; priorities[entityID] = priority;
return true; return true;
} }
@ -44,13 +48,22 @@ namespace Encompass
return false; 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) public override bool Remove(int entityID, int priority)
{ {
if (!priorities.ContainsKey(entityID) || priority < priorities[entityID]) if (!priorities.ContainsKey(entityID) || priority < priorities[entityID])
{ {
priorities[entityID] = priority; priorities[entityID] = priority;
store.Remove(entityID); indices.Remove(entityID);
priorities.Remove(entityID); priorities.Remove(entityID);
_idManager.Free(entityID);
return true; return true;
} }
@ -59,18 +72,19 @@ namespace Encompass
public override void ForceRemove(int entityID) public override void ForceRemove(int entityID)
{ {
store.Remove(entityID); indices.Remove(entityID);
priorities.Remove(entityID); priorities.Remove(entityID);
_idManager.Free(entityID);
} }
public override bool Has(int entityID) public override bool Has(int entityID)
{ {
return store.ContainsKey(entityID); return indices.ContainsKey(entityID);
} }
public override void Clear() public override void Clear()
{ {
store.Clear(); indices.Clear();
priorities.Clear(); priorities.Clear();
} }
@ -81,17 +95,17 @@ namespace Encompass
public IEnumerable<(TComponent, int)> All() public IEnumerable<(TComponent, int)> All()
{ {
foreach (var kvp in store) foreach (var kvp in indices)
{ {
yield return (kvp.Value, kvp.Key); yield return (components[kvp.Value], kvp.Key);
} }
} }
public override IEnumerable<(int, Type, IComponent)> AllInterfaceTyped() public override IEnumerable<(int, Type, IComponent)> AllInterfaceTyped()
{ {
foreach (var kvp in store) foreach (var kvp in indices)
{ {
yield return (kvp.Key, typeof(TComponent), (IComponent)kvp.Value); yield return (kvp.Key, typeof(TComponent), (IComponent)components[kvp.Value]);
} }
} }
} }

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using MoonTools.FastCollections;
namespace Encompass namespace Encompass
{ {
@ -154,19 +153,19 @@ namespace Encompass
// component getters // component getters
internal TComponent ReadImmediateOrExistingComponentByEntityAndType<TComponent>(int entityID) where TComponent : struct, IComponent internal ref readonly TComponent ReadImmediateOrExistingComponentByEntityAndType<TComponent>(int entityID) where TComponent : struct, IComponent
{ {
return upToDateComponentStore.Get<TComponent>(entityID); return ref upToDateComponentStore.Get<TComponent>(entityID);
} }
internal TComponent ReadExistingComponentByEntityAndType<TComponent>(int entityID) where TComponent : struct, IComponent internal ref readonly TComponent ReadExistingComponentByEntityAndType<TComponent>(int entityID) where TComponent : struct, IComponent
{ {
return existingComponentStore.Get<TComponent>(entityID); return ref existingComponentStore.Get<TComponent>(entityID);
} }
internal TComponent ReadImmediateComponentByEntityAndType<TComponent>(int entityID) where TComponent : struct, IComponent internal ref readonly TComponent ReadImmediateComponentByEntityAndType<TComponent>(int entityID) where TComponent : struct, IComponent
{ {
return immediateComponentStore.Get<TComponent>(entityID); return ref immediateComponentStore.Get<TComponent>(entityID);
} }
// has checkers // has checkers
@ -214,9 +213,9 @@ namespace Encompass
} }
} }
internal TComponent GetComponentByEntityAndType<TComponent>(int entityID) where TComponent : struct, IComponent internal ref readonly TComponent GetComponentByEntityAndType<TComponent>(int entityID) where TComponent : struct, IComponent
{ {
return existingComponentStore.Get<TComponent>(entityID); return ref existingComponentStore.Get<TComponent>(entityID);
} }
internal bool EntityHasComponentOfType<TComponent>(int entityID) where TComponent : struct, IComponent internal bool EntityHasComponentOfType<TComponent>(int entityID) where TComponent : struct, IComponent

View File

@ -344,21 +344,21 @@ namespace Encompass
} }
} }
private TComponent GetComponentHelper<TComponent>(int entityID) where TComponent : struct, IComponent private ref readonly TComponent GetComponentHelper<TComponent>(int entityID) where TComponent : struct, IComponent
{ {
var immediateRead = readImmediateTypes.Contains(typeof(TComponent)); var immediateRead = readImmediateTypes.Contains(typeof(TComponent));
var existingRead = readTypes.Contains(typeof(TComponent)); var existingRead = readTypes.Contains(typeof(TComponent));
if (existingRead && immediateRead) if (existingRead && immediateRead)
{ {
return componentManager.ReadImmediateOrExistingComponentByEntityAndType<TComponent>(entityID); return ref componentManager.ReadImmediateOrExistingComponentByEntityAndType<TComponent>(entityID);
} }
else if (existingRead) else if (existingRead)
{ {
return componentManager.ReadExistingComponentByEntityAndType<TComponent>(entityID); return ref componentManager.ReadExistingComponentByEntityAndType<TComponent>(entityID);
} }
else if (immediateRead) else if (immediateRead)
{ {
return componentManager.ReadImmediateComponentByEntityAndType<TComponent>(entityID); return ref componentManager.ReadImmediateComponentByEntityAndType<TComponent>(entityID);
} }
else else
{ {
@ -375,9 +375,9 @@ namespace Encompass
/// <exception cref="Encompass.Exceptions.IllegalReadException"> /// <exception cref="Encompass.Exceptions.IllegalReadException">
/// Thrown when the Engine does not declare that it reads the given Component Type. /// Thrown when the Engine does not declare that it reads the given Component Type.
/// </exception> /// </exception>
protected TComponent GetComponent<TComponent>(Entity entity) where TComponent : struct, IComponent protected ref readonly TComponent GetComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
{ {
return GetComponentHelper<TComponent>(entity.ID); return ref GetComponentHelper<TComponent>(entity.ID);
} }
/// <summary> /// <summary>

View File

@ -57,9 +57,9 @@ namespace Encompass
return enumerator.Current; return enumerator.Current;
} }
protected TComponent GetComponent<TComponent>(Entity entity) where TComponent : struct, IComponent protected ref readonly TComponent GetComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
{ {
return componentManager.GetComponentByEntityAndType<TComponent>(entity.ID); return ref componentManager.GetComponentByEntityAndType<TComponent>(entity.ID);
} }
protected bool HasComponent<TComponent>(Entity entity) where TComponent : struct, IComponent protected bool HasComponent<TComponent>(Entity entity) where TComponent : struct, IComponent

View File

@ -1,6 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>8.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RootNamespace>Encompass</RootNamespace> <RootNamespace>Encompass</RootNamespace>
<PackageId>EncompassECS.Framework</PackageId> <PackageId>EncompassECS.Framework</PackageId>
<Version>0.20.0</Version> <Version>0.20.0</Version>