Skip to content

Commit

Permalink
Add enttraitarray back
Browse files Browse the repository at this point in the history
  • Loading branch information
metalgearsloth committed Sep 2, 2024
1 parent 262aff0 commit 13e860e
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 97 deletions.
205 changes: 108 additions & 97 deletions Robust.Shared/GameObjects/EntityManager.Components.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ public partial class EntityManager
private const int TypeCapacity = 32;
private const int EntityCapacity = 1024;

private Dictionary<EntityUid, IComponent>[] _entTraitArray
= Array.Empty<Dictionary<EntityUid, IComponent>>();

private readonly HashSet<IComponent> _deleteSet = new(TypeCapacity);

/// <inheritdoc />
Expand All @@ -48,6 +51,20 @@ public partial class EntityManager
/// <inheritdoc />
public event Action<RemovedComponentEventArgs>? ComponentRemoved;

public void InitializeComponents()
{
if (Initialized)
throw new InvalidOperationException("Already initialized.");

FillComponentDict();
_componentFactory.ComponentsAdded += OnComponentsAdded;
}

private void OnComponentsAdded(ComponentRegistration[] components)
{
RegisterComponents(components);
}

/// <summary>
/// Instantly clears all components from the manager. This will NOT shut them down gracefully.
/// Any entities relying on existing components will be broken.
Expand All @@ -57,6 +74,15 @@ public void ClearComponents()
_deleteSet.Clear();
}

private void RegisterComponents(IEnumerable<ComponentRegistration> components)
{
foreach (var reg in components)
{
var dict = new Dictionary<EntityUid, IComponent>();
CompIdx.AssignArray(ref _entTraitArray, reg.Idx, dict);
}
}

#region Component Management

/// <inheritdoc />
Expand Down Expand Up @@ -320,6 +346,25 @@ internal void AddComponentInternalOnly<T>(EntityUid uid, T component, ComponentR
_world.Set(uid, (object)component);
}

var dict = _entTraitArray[reg.Idx.Value];
DebugTools.Assert(dict != null);

// Code block to restrict access to ref comp.
{
ref var comp = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, uid, out var exists);
if (exists)
{
// This will invalidate the comp ref as it removes the key from the dictionary.
// This is inefficient, but component overriding rarely ever happens.
RemoveComponentImmediate(uid, comp!, reg.Idx, false, false, meta: metadata);
dict.Add(uid, component);
}
else
{
comp = component;
}
}

// add the component to the netId grid
if (reg.NetID != null && component.NetSyncEnabled)
{
Expand Down Expand Up @@ -651,6 +696,8 @@ private void DeleteComponent(EntityUid entityUid, IComponent component, CompIdx
}
}

_entTraitArray[idx.Value].Remove(entityUid);

if (archetypeChange)
{
DebugTools.Assert(_world.Has(entityUid, idx.Type));
Expand Down Expand Up @@ -732,10 +779,7 @@ public bool TryComp(ref ArchEntity entity, CompIdx idx, [NotNullWhen(true)] out
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool HasComponent<T>(EntityUid uid) where T : IComponent
{
if (!_world.TryGetAlive(uid, out T? comp))
return false;

return !comp!.Deleted;
return _entTraitArray[CompIdx.ArrayIndex<T>()].TryGetValue(uid, out var comp) && !comp.Deleted;
}

/// <inheritdoc />
Expand All @@ -749,10 +793,8 @@ public bool HasComponent<T>(EntityUid? uid) where T : IComponent
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool HasComponent(EntityUid uid, Type type)
{
if (!_world.TryGetAlive(uid, type, out var comp))
return false;

return !((IComponent)comp!).Deleted;
var dict = _entTraitArray[_componentFactory.GetArrayIndex(type)];
return dict.TryGetValue(uid, out var comp) && !comp.Deleted;
}

/// <inheritdoc />
Expand Down Expand Up @@ -857,17 +899,28 @@ public T GetComponent<T>(EntityUid uid) where T : IComponent

public IComponent GetComponent(EntityUid uid, CompIdx type)
{
if (TryGetComponent(uid, type, out var comp))
return comp;
var dict = _entTraitArray[type.Value];
if (dict.TryGetValue(uid, out var comp))
{
if (!comp.Deleted)
return comp;
}

throw new KeyNotFoundException($"Entity {uid} does not have a component of type {_componentFactory.IdxToType(type)}");
}

/// <inheritdoc />
public IComponent GetComponent(EntityUid uid, Type type)
{
if (TryGetComponent(uid, type, out var component))
return component;
// ReSharper disable once InvertIf
var dict = _entTraitArray[_componentFactory.GetArrayIndex(type)];
if (dict.TryGetValue(uid, out var comp))
{
if (!comp.Deleted)
{
return comp;
}
}

throw new KeyNotFoundException($"Entity {uid} does not have a component of type {type}");
}
Expand Down Expand Up @@ -929,11 +982,12 @@ public bool TryGetComponent<T>([NotNullWhen(true)] EntityUid? uid, [NotNullWhen(
/// <inheritdoc />
public bool TryGetComponent(EntityUid uid, Type type, [NotNullWhen(true)] out IComponent? component)
{
if (_world.TryGetAlive(uid, type, out var comp))
var dict = _entTraitArray[_componentFactory.GetArrayIndex(type)];
if (dict.TryGetValue(uid, out var comp))
{
component = (IComponent)comp!;
if (!component.Deleted)
if (!comp.Deleted)
{
component = comp;
return true;
}
}
Expand All @@ -944,15 +998,7 @@ public bool TryGetComponent(EntityUid uid, Type type, [NotNullWhen(true)] out IC

public bool TryGetComponent(EntityUid uid, CompIdx type, [NotNullWhen(true)] out IComponent? component)
{
if (_world.TryGetAlive(uid, type.Type.Id, out var comp))
{
component = (IComponent)comp!;
if (component != null! && !component.Deleted)
return true;
}

component = null;
return false;
return TryGetComponent(uid, type.Type.Type, out component);
}

/// <inheritdoc />
Expand Down Expand Up @@ -998,12 +1044,16 @@ public bool TryGetComponent([NotNullWhen(true)] EntityUid? uid, ushort netId,

public EntityQuery<TComp1> GetEntityQuery<TComp1>() where TComp1 : IComponent
{
return new EntityQuery<TComp1>(this, _world, null, _resolveSawmill);
var comps = _entTraitArray[CompIdx.ArrayIndex<TComp1>()];
DebugTools.Assert(comps != null, $"Unknown component: {typeof(TComp1).Name}");
return new EntityQuery<TComp1>(comps, _resolveSawmill);
}

public EntityQuery<IComponent> GetEntityQuery(Type type)
{
return new EntityQuery<IComponent>(this, _world, type, _resolveSawmill);
var comps = _entTraitArray[_componentFactory.GetArrayIndex(type)];
DebugTools.Assert(comps != null, $"Unknown component: {type.Name}");
return new EntityQuery<IComponent>(comps, _resolveSawmill);
}

/// <inheritdoc />
Expand Down Expand Up @@ -1325,6 +1375,13 @@ public bool CanGetComponentState(IEventBus eventBus, IComponent component, IComm
}

#endregion

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void FillComponentDict()
{
Array.Fill(_entTraitArray, null);
RegisterComponents(_componentFactory.GetAllRegistrations());
}
}

public readonly struct NetComponentEnumerable
Expand Down Expand Up @@ -1355,61 +1412,32 @@ public NetComponentEnumerator(Dictionary<ushort, IComponent> dictionary) =>
}
}

public readonly struct ArchEntityQuery<TComp1> where TComp1 : IComponent
{
private readonly IEntityManager _manager;
private readonly World _world;
private readonly ComponentType? _type;
private readonly ISawmill _sawmill;
private readonly Query _query;

public ArchEntityQuery(IEntityManager manager, World world, ISawmill sawmill)
{
_manager = manager;
_world = world;
_sawmill = sawmill;
_query = world.Query(new QueryDescription().WithAll<TComp1>());
_query.Match();
}

public bool TryComp(EntityUid uid, out TComp1? component)
{
return _world.TryGetAlive(uid, out component);
}
}

public readonly struct EntityQuery<TComp1> where TComp1 : IComponent
{
private readonly IEntityManager _manager;
private readonly World _world;
private readonly ComponentType? _type;
private readonly Dictionary<EntityUid, IComponent> _traitDict;
private readonly ISawmill _sawmill;
private readonly int _compId;

public EntityQuery(IEntityManager manager, World world, ComponentType? type, ISawmill sawmill)
public EntityQuery(Dictionary<EntityUid, IComponent> traitDict, ISawmill sawmill)
{
_manager = manager;
_world = world;
_type = type;
_traitDict = traitDict;
_sawmill = sawmill;

_compId = Component<TComp1>.ComponentType.Id;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
public TComp1 GetComponent(EntityUid uid)
{
return _type == null
? _manager.GetComponent<TComp1>(uid)
: (TComp1)_manager.GetComponent(uid, _type.Value.Type);
if (_traitDict.TryGetValue(uid, out var comp) && !comp.Deleted)
return (TComp1) comp;

throw new KeyNotFoundException($"Entity {uid} does not have a component of type {typeof(TComp1)}");
}

[MethodImpl(MethodImplOptions.AggressiveInlining), Pure]
public Entity<TComp1> Get(EntityUid uid)
{
if (_world.TryGet(uid, out TComp1? comp) && comp != null && !comp.Deleted)
return new Entity<TComp1>(uid, comp);
if (_traitDict.TryGetValue(uid, out var comp) && !comp.Deleted)
return new Entity<TComp1>(uid, (TComp1) comp);

throw new KeyNotFoundException($"Entity {uid} does not have a component of type {typeof(TComp1)}");
}
Expand All @@ -1431,29 +1459,14 @@ public bool TryGetComponent([NotNullWhen(true)] EntityUid? uid, [NotNullWhen(tru
[Pure]
public bool TryGetComponent(EntityUid uid, [NotNullWhen(true)] out TComp1? component)
{
if (_type != null)
if (_traitDict.TryGetValue(uid, out var comp) && !comp.Deleted)
{
if (_manager.TryGetComponent(uid, _type.Value.Type, out var comp))
{
component = (TComp1) comp;
return true;
}

component = default;
return false;
}
else
{
if (!_world.TryGetAlive(uid, _compId, out var obj))
{
component = default;
return false;
}

DebugTools.AssertNotNull(obj);
component = (TComp1) obj!;
component = (TComp1) comp;
return true;
}

component = default;
return false;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand All @@ -1478,18 +1491,14 @@ public bool TryComp([NotNullWhen(true)] EntityUid? uid, [NotNullWhen(true)] out
[Pure]
public bool HasComponent(EntityUid uid)
{
return _type == null
? _manager.HasComponent<TComp1>(uid)
: _manager.HasComponent(uid, _type.Value.Type);
return _traitDict.TryGetValue(uid, out var comp) && !comp.Deleted;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
public bool HasComponent(EntityUid? uid)
{
return _type == null
? _manager.HasComponent<TComp1>(uid)
: _manager.HasComponent(uid, _type.Value.Type);
return uid != null && HasComponent(uid.Value);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand All @@ -1502,8 +1511,9 @@ public bool Resolve(EntityUid uid, [NotNullWhen(true)] ref TComp1? component, bo
return true;
}

if (TryGetComponent(uid, out component))
if (_traitDict.TryGetValue(uid, out var comp) && !comp.Deleted)
{
component = (TComp1)comp;
return true;
}

Expand Down Expand Up @@ -1547,8 +1557,8 @@ public TComp1 Comp(EntityUid uid)
[Pure]
internal TComp1 GetComponentInternal(EntityUid uid)
{
if (TryGetComponentInternal(uid, out var comp))
return comp;
if (_traitDict.TryGetValue(uid, out var comp))
return (TComp1) comp;

throw new KeyNotFoundException($"Entity {uid} does not have a component of type {typeof(TComp1)}");
}
Expand Down Expand Up @@ -1576,8 +1586,9 @@ internal bool TryGetComponentInternal([NotNullWhen(true)] EntityUid? uid, [NotNu
[Pure]
internal bool TryGetComponentInternal(EntityUid uid, [NotNullWhen(true)] out TComp1? component)
{
if (_world.TryGet(uid, out component!))
if (_traitDict.TryGetValue(uid, out var comp))
{
component = (TComp1) comp;
return true;
}

Expand All @@ -1592,8 +1603,7 @@ internal bool TryGetComponentInternal(EntityUid uid, [NotNullWhen(true)] out TCo
[Pure]
internal bool HasComponentInternal(EntityUid uid)
{
// TODO fix checking deleted
return _world.TryGet(uid, out TComp1? comp) && !comp!.Deleted;
return _traitDict.TryGetValue(uid, out var comp) && !comp.Deleted;
}

/// <summary>
Expand All @@ -1609,8 +1619,9 @@ internal bool ResolveInternal(EntityUid uid, [NotNullWhen(true)] ref TComp1? com
return true;
}

if (TryGetComponentInternal(uid, out component))
if (_traitDict.TryGetValue(uid, out var comp))
{
component = (TComp1)comp;
return true;
}

Expand Down
1 change: 1 addition & 0 deletions Robust.Shared/GameObjects/EntityManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ public virtual void Initialize()
_eventBus = new EntityEventBus(this, _reflection);

InitializeArch();
InitializeComponents();
_metaReg = _componentFactory.GetRegistration(typeof(MetaDataComponent));
_xformReg = _componentFactory.GetRegistration(typeof(TransformComponent));
_xformName = _xformReg.Name;
Expand Down

0 comments on commit 13e860e

Please sign in to comment.