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
{
public struct MutableComponentEntityPair<TComponent> where TComponent : struct, IComponent
{
public TComponent component;
}
internal class ComponentStore
{
private Dictionary<Type, TypedComponentStore> Stores = new Dictionary<Type, TypedComponentStore>(512);
@ -51,9 +56,9 @@ namespace Encompass
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

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Encompass
{
@ -16,27 +17,30 @@ namespace Encompass
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> priorities = new Dictionary<int, int>(128);
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 => 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); }
return store[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 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])
{
store[entityID] = component;
InternalSet(entityID, component);
priorities[entityID] = priority;
return true;
}
@ -44,13 +48,22 @@ namespace Encompass
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;
store.Remove(entityID);
indices.Remove(entityID);
priorities.Remove(entityID);
_idManager.Free(entityID);
return true;
}
@ -59,18 +72,19 @@ namespace Encompass
public override void ForceRemove(int entityID)
{
store.Remove(entityID);
indices.Remove(entityID);
priorities.Remove(entityID);
_idManager.Free(entityID);
}
public override bool Has(int entityID)
{
return store.ContainsKey(entityID);
return indices.ContainsKey(entityID);
}
public override void Clear()
{
store.Clear();
indices.Clear();
priorities.Clear();
}
@ -81,17 +95,17 @@ namespace Encompass
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()
{
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.Collections.Generic;
using MoonTools.FastCollections;
namespace Encompass
{
@ -154,19 +153,19 @@ namespace Encompass
// 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
@ -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

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 existingRead = readTypes.Contains(typeof(TComponent));
if (existingRead && immediateRead)
{
return componentManager.ReadImmediateOrExistingComponentByEntityAndType<TComponent>(entityID);
return ref componentManager.ReadImmediateOrExistingComponentByEntityAndType<TComponent>(entityID);
}
else if (existingRead)
{
return componentManager.ReadExistingComponentByEntityAndType<TComponent>(entityID);
return ref componentManager.ReadExistingComponentByEntityAndType<TComponent>(entityID);
}
else if (immediateRead)
{
return componentManager.ReadImmediateComponentByEntityAndType<TComponent>(entityID);
return ref componentManager.ReadImmediateComponentByEntityAndType<TComponent>(entityID);
}
else
{
@ -375,9 +375,9 @@ namespace Encompass
/// <exception cref="Encompass.Exceptions.IllegalReadException">
/// Thrown when the Engine does not declare that it reads the given Component Type.
/// </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>

View File

@ -57,9 +57,9 @@ namespace Encompass
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

View File

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