Compare commits

...

3 Commits

Author SHA1 Message Date
metalgearsloth
6b059ed356 Version: 137.0.0 2023-07-13 20:22:47 +10:00
metalgearsloth
b69b4fd8fe Kill comp getstate / handlestate (#4183) 2023-07-13 20:19:58 +10:00
metalgearsloth
cb63499ec9 Add EntityQuery<MetaDataComponent> to EntityManager (#4166) 2023-07-13 20:14:47 +10:00
22 changed files with 346 additions and 162 deletions

View File

@@ -1,4 +1,4 @@
<Project>
<!-- This file automatically reset by Tools/version.py -->
<PropertyGroup><Version>136.0.1</Version></PropertyGroup>
</Project>
<Project>
<!-- This file automatically reset by Tools/version.py -->

View File

@@ -54,6 +54,13 @@ END TEMPLATE-->
*None yet*
## 137.0.0
### Breaking changes
* Component network state handler methods have been fully deprecated and replaced with the eventbus event equivalents (ComponentGetState and ComponentHandleState).
## 136.0.1
### Bugfixes

View File

@@ -0,0 +1,75 @@
using BenchmarkDotNet.Attributes;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.EntityManager;
public class ComponentIteratorBenchmark
{
private ISimulation _simulation = default!;
private IEntityManager _entityManager = default!;
[UsedImplicitly]
[Params(1, 10, 100, 1000)]
public int N;
public A[] Comps = default!;
[GlobalSetup]
public void GlobalSetup()
{
_simulation = RobustServerSimulation
.NewSimulation()
.RegisterComponents(f => f.RegisterClass<A>())
.InitializeInstance();
_entityManager = _simulation.Resolve<IEntityManager>();
Comps = new A[N+2];
var coords = new MapCoordinates(0, 0, new MapId(1));
_simulation.AddMap(coords.MapId);
for (var i = 0; i < N; i++)
{
var uid = _entityManager.SpawnEntity(null, coords);
_entityManager.AddComponent<A>(uid);
}
}
[Benchmark]
public A[] ComponentStructEnumerator()
{
var query = _entityManager.EntityQueryEnumerator<A>();
var i = 0;
while (query.MoveNext(out var comp))
{
Comps[i] = comp;
i++;
}
return Comps;
}
[Benchmark]
public A[] ComponentIEnumerable()
{
var i = 0;
foreach (var comp in _entityManager.EntityQuery<A>())
{
Comps[i] = comp;
i++;
}
return Comps;
}
[ComponentProtoName("A")]
public sealed class A : Component
{
}
}

View File

@@ -144,29 +144,6 @@ namespace Robust.Client.GameObjects
}
}
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
{
base.HandleComponentState(curState, nextState);
if (curState is not EyeComponentState state)
{
return;
}
DrawFov = state.DrawFov;
// TODO: Should be a way for content to override lerping and lerp the zoom
Zoom = state.Zoom;
Offset = state.Offset;
VisibilityMask = state.VisibilityMask;
}
protected override void OnRemove()
{
base.OnRemove();
Current = false;
}
/// <summary>
/// Updates the Eye of this entity with the transform position. This has to be called every frame to
/// keep the view following the entity.

View File

@@ -0,0 +1,33 @@
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
namespace Robust.Client.GameObjects;
public sealed class EyeSystem : SharedEyeSystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<EyeComponent, ComponentRemove>(OnRemove);
SubscribeLocalEvent<EyeComponent, ComponentHandleState>(OnHandleState);
}
private void OnRemove(EntityUid uid, EyeComponent component, ComponentRemove args)
{
component.Current = false;
}
private void OnHandleState(EntityUid uid, EyeComponent component, ref ComponentHandleState args)
{
if (args.Current is not EyeComponentState state)
{
return;
}
component.DrawFov = state.DrawFov;
// TODO: Should be a way for content to override lerping and lerp the zoom
component.Zoom = state.Zoom;
component.Offset = state.Offset;
component.VisibilityMask = state.VisibilityMask;
}
}

View File

@@ -532,7 +532,6 @@ namespace Robust.Client.GameStates
var handleState = new ComponentHandleState(compState, null);
_entities.EventBus.RaiseComponentEvent(comp, ref handleState);
comp.HandleComponentState(compState, null);
comp.LastModifiedTick = _timing.LastRealTick;
}
@@ -561,7 +560,6 @@ namespace Robust.Client.GameStates
var stateEv = new ComponentHandleState(state, null);
_entities.EventBus.RaiseComponentEvent(comp, ref stateEv);
comp.HandleComponentState(state, null);
comp.ClearCreationTick(); // don't undo the re-adding.
comp.LastModifiedTick = _timing.LastRealTick;
}
@@ -1172,7 +1170,6 @@ namespace Robust.Client.GameStates
{
var handleState = new ComponentHandleState(cur, next);
bus.RaiseComponentEvent(comp, ref handleState);
comp.HandleComponentState(cur, next);
}
catch (Exception e)
{
@@ -1223,7 +1220,7 @@ namespace Robust.Client.GameStates
return;
using var _ = _timing.StartStateApplicationArea();
ResetEnt(meta, false);
ResetEnt(uid, meta, false);
}
/// <summary>
@@ -1301,24 +1298,24 @@ namespace Robust.Client.GameStates
{
using var _ = _timing.StartStateApplicationArea();
foreach (var meta in _entities.EntityQuery<MetaDataComponent>(true))
var query = _entityManager.AllEntityQueryEnumerator<MetaDataComponent>();
while (query.MoveNext(out var uid, out var meta))
{
ResetEnt(meta);
ResetEnt(uid, meta);
}
}
/// <summary>
/// Reset a given entity to the most recent server state.
/// </summary>
private void ResetEnt(MetaDataComponent meta, bool skipDetached = true)
private void ResetEnt(EntityUid uid, MetaDataComponent meta, bool skipDetached = true)
{
if (skipDetached && (meta.Flags & MetaDataFlags.Detached) != 0)
return;
meta.Flags &= ~MetaDataFlags.Detached;
var uid = meta.Owner;
if (!_processor.TryGetLastServerStates(uid, out var lastState))
return;
@@ -1334,7 +1331,6 @@ namespace Robust.Client.GameStates
var handleState = new ComponentHandleState(state, null);
_entityManager.EventBus.RaiseComponentEvent(comp, ref handleState);
comp.HandleComponentState(state, null);
}
// ensure we don't have any extra components

View File

@@ -87,10 +87,5 @@ namespace Robust.Server.GameObjects
Dirty();
}
}
public override ComponentState GetComponentState()
{
return new EyeComponentState(DrawFov, Zoom, Offset, VisibilityMask);
}
}
}

View File

@@ -0,0 +1,18 @@
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
namespace Robust.Server.GameObjects;
public sealed class EyeSystem : SharedEyeSystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<EyeComponent, ComponentGetState>(OnHandleState);
}
private void OnHandleState(EntityUid uid, EyeComponent component, ref ComponentGetState args)
{
args.State = new EyeComponentState(component.DrawFov, component.Zoom, component.Offset, component.VisibilityMask);
}
}

View File

@@ -162,10 +162,10 @@ namespace Robust.Shared.Scripting
public abstract void show(object obj);
#region EntityManager proxy methods
public T Comp<T>(EntityUid uid)
public T Comp<T>(EntityUid uid) where T : Component
=> ent.GetComponent<T>(uid);
public bool TryComp<T>(EntityUid uid, out T? comp)
public bool TryComp<T>(EntityUid uid, out T? comp) where T : Component
=> ent.TryGetComponent(uid, out comp);
public bool HasComp<T>(EntityUid uid)

View File

@@ -54,28 +54,6 @@ namespace Robust.Shared.Containers
Containers.Clear();
}
/// <inheritdoc />
public override ComponentState GetComponentState()
{
// naive implementation that just sends the full state of the component
Dictionary<string, ContainerManagerComponentState.ContainerData> containerSet = new(Containers.Count);
foreach (var container in Containers.Values)
{
var uidArr = new EntityUid[container.ContainedEntities.Count];
for (var index = 0; index < container.ContainedEntities.Count; index++)
{
uidArr[index] = container.ContainedEntities[index];
}
var sContainer = new ContainerManagerComponentState.ContainerData(container.ContainerType, container.ID, container.ShowContents, container.OccludesLight, uidArr);
containerSet.Add(container.ID, sContainer);
}
return new ContainerManagerComponentState(containerSet);
}
/// <inheritdoc />
public T MakeContainer<T>(string id)
where T : IContainer

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
@@ -23,6 +24,28 @@ namespace Robust.Shared.Containers
SubscribeLocalEvent<EntParentChangedMessage>(OnParentChanged);
SubscribeLocalEvent<ContainerManagerComponent, ComponentStartup>(OnStartupValidation);
SubscribeLocalEvent<ContainerManagerComponent, ComponentGetState>(OnContainerGetState);
}
private void OnContainerGetState(EntityUid uid, ContainerManagerComponent component, ref ComponentGetState args)
{
// naive implementation that just sends the full state of the component
Dictionary<string, ContainerManagerComponent.ContainerManagerComponentState.ContainerData> containerSet = new(component.Containers.Count);
foreach (var container in component.Containers.Values)
{
var uidArr = new EntityUid[container.ContainedEntities.Count];
for (var index = 0; index < container.ContainedEntities.Count; index++)
{
uidArr[index] = container.ContainedEntities[index];
}
var sContainer = new ContainerManagerComponent.ContainerManagerComponentState.ContainerData(container.ContainerType, container.ID, container.ShowContents, container.OccludesLight, uidArr);
containerSet.Add(container.ID, sContainer);
}
args.State = new ContainerManagerComponent.ContainerManagerComponentState(containerSet);
}
// TODO: Make ContainerManagerComponent ECS and make these proxy methods the real deal.

View File

@@ -208,21 +208,6 @@ namespace Robust.Shared.GameObjects
entManager.Dirty(this);
}
private static readonly ComponentState DefaultComponentState = new();
/// <inheritdoc />
public virtual ComponentState GetComponentState()
{
DebugTools.Assert(
Attribute.GetCustomAttribute(GetType(), typeof(NetworkedComponentAttribute)) != null,
$"Calling base {nameof(GetComponentState)} without being networked.");
return DefaultComponentState;
}
/// <inheritdoc />
public virtual void HandleComponentState(ComponentState? curState, ComponentState? nextState) { }
// these two methods clear the LastModifiedTick/CreationTick to mark it as "not different from prototype load".
// This is used as optimization in the game state system to avoid sending redundant component data.
internal virtual void ClearTicks()

View File

@@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using JetBrains.Annotations;
using Robust.Shared.GameStates;
using Robust.Shared.IoC;
using Robust.Shared.Log;
@@ -23,7 +24,7 @@ namespace Robust.Shared.GameObjects
/// <summary>
/// Mapping of component name to type.
/// </summary>
private readonly Dictionary<string, ComponentRegistration> names = new();
private readonly Dictionary<string, ComponentRegistration> _names = new();
/// <summary>
/// Mapping of lowercase component names to their registration.
@@ -107,11 +108,11 @@ namespace Robust.Shared.GameObjects
IgnoredComponentNames.Remove(name);
}
if (names.ContainsKey(name))
if (_names.ContainsKey(name))
{
if (!overwrite)
{
throw new InvalidOperationException($"{name} is already registered, previous: {names[name]}");
throw new InvalidOperationException($"{name} is already registered, previous: {_names[name]}");
}
RemoveComponent(name);
@@ -130,7 +131,7 @@ namespace Robust.Shared.GameObjects
var registration = new ComponentRegistration(name, type, idx);
names[name] = registration;
_names[name] = registration;
_lowerCaseNames[lowerCaseName] = name;
types[type] = registration;
CompIdx.AssignArray(ref _array, idx, registration);
@@ -213,7 +214,7 @@ namespace Robust.Shared.GameObjects
throw new InvalidOperationException($"Cannot add {name} to ignored components: It is already registered as ignored");
}
if (names.ContainsKey(name))
if (_names.ContainsKey(name))
{
if (!overwrite)
{
@@ -232,9 +233,9 @@ namespace Robust.Shared.GameObjects
if (_networkedComponents is not null)
throw new ComponentRegistrationLockException();
var registration = names[name];
var registration = _names[name];
names.Remove(registration.Name);
_names.Remove(registration.Name);
_lowerCaseNames.Remove(registration.Name.ToLowerInvariant());
types.Remove(registration.Type);
}
@@ -246,7 +247,7 @@ namespace Robust.Shared.GameObjects
componentName = lowerCaseName;
}
if (names.ContainsKey(componentName))
if (_names.ContainsKey(componentName))
{
return ComponentAvailability.Available;
}
@@ -313,7 +314,7 @@ namespace Robust.Shared.GameObjects
try
{
return names[componentName];
return _names[componentName];
}
catch (KeyNotFoundException)
{
@@ -321,6 +322,7 @@ namespace Robust.Shared.GameObjects
}
}
[Pure]
public string GetComponentName(Type componentType)
{
return GetRegistration(componentType).Name;
@@ -374,7 +376,7 @@ namespace Robust.Shared.GameObjects
componentName = lowerCaseName;
}
if (names.TryGetValue(componentName, out var tempRegistration))
if (_names.TryGetValue(componentName, out var tempRegistration))
{
registration = tempRegistration;
return true;
@@ -474,9 +476,9 @@ namespace Robust.Shared.GameObjects
// component names are 1:1 with component concrete types
// a subset of component names are networked
var networkedRegs = new List<ComponentRegistration>(names.Count);
var networkedRegs = new List<ComponentRegistration>(_names.Count);
foreach (var kvRegistration in names)
foreach (var kvRegistration in _names)
{
var registration = kvRegistration.Value;
if (Attribute.GetCustomAttribute(registration.Type, typeof(NetworkedComponentAttribute)) is NetworkedComponentAttribute)

View File

@@ -4,6 +4,7 @@ using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using JetBrains.Annotations;
using Robust.Shared.GameStates;
using Robust.Shared.Log;
using Robust.Shared.Physics.Components;
@@ -32,6 +33,8 @@ namespace Robust.Shared.GameObjects
private const int EntityCapacity = 1024;
private const int NetComponentCapacity = 8;
private static readonly ComponentState DefaultComponentState = new();
private readonly Dictionary<EntityUid, Dictionary<ushort, Component>> _netComponents
= new(EntityCapacity);
@@ -46,6 +49,8 @@ namespace Robust.Shared.GameObjects
private UniqueIndexHkm<EntityUid, Component> _entCompIndex =
new(ComponentCollectionCapacity);
private EntityQuery<MetaDataComponent> _metaQuery;
/// <inheritdoc />
public event Action<AddedComponentEventArgs>? ComponentAdded;
@@ -63,6 +68,7 @@ namespace Robust.Shared.GameObjects
FillComponentDict();
_componentFactory.ComponentAdded += OnComponentAdded;
_componentFactory.ComponentReferenceAdded += OnComponentReferenceAdded;
_metaQuery = GetEntityQuery<MetaDataComponent>();
}
/// <summary>
@@ -700,15 +706,15 @@ namespace Robust.Shared.GameObjects
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T GetComponent<T>(EntityUid uid)
public T GetComponent<T>(EntityUid uid) where T : IComponent
{
var dict = _entTraitArray[CompIdx.ArrayIndex<T>()];
DebugTools.Assert(dict != null, $"Unknown component: {typeof(T).Name}");
if (dict!.TryGetValue(uid, out var comp))
{
if (!comp.Deleted)
if (!comp!.Deleted)
{
return (T)(IComponent)comp;
return (T)(IComponent) comp;
}
}
@@ -1034,8 +1040,7 @@ namespace Robust.Shared.GameObjects
where TComp1 : Component
{
var trait1 = _entTraitArray[CompIdx.ArrayIndex<TComp1>()];
var metaTraits = _entTraitArray[CompIdx.ArrayIndex<MetaDataComponent>()];
return new EntityQueryEnumerator<TComp1>(trait1, metaTraits);
return new EntityQueryEnumerator<TComp1>(trait1, _metaQuery);
}
public EntityQueryEnumerator<TComp1, TComp2> EntityQueryEnumerator<TComp1, TComp2>()
@@ -1044,8 +1049,7 @@ namespace Robust.Shared.GameObjects
{
var trait1 = _entTraitArray[CompIdx.ArrayIndex<TComp1>()];
var trait2 = _entTraitArray[CompIdx.ArrayIndex<TComp2>()];
var metaTraits = _entTraitArray[CompIdx.ArrayIndex<MetaDataComponent>()];
return new EntityQueryEnumerator<TComp1, TComp2>(trait1, trait2, metaTraits);
return new EntityQueryEnumerator<TComp1, TComp2>(trait1, trait2, _metaQuery);
}
public EntityQueryEnumerator<TComp1, TComp2, TComp3> EntityQueryEnumerator<TComp1, TComp2, TComp3>()
@@ -1056,8 +1060,7 @@ namespace Robust.Shared.GameObjects
var trait1 = _entTraitArray[CompIdx.ArrayIndex<TComp1>()];
var trait2 = _entTraitArray[CompIdx.ArrayIndex<TComp2>()];
var trait3 = _entTraitArray[CompIdx.ArrayIndex<TComp3>()];
var metaTraits = _entTraitArray[CompIdx.ArrayIndex<MetaDataComponent>()];
return new EntityQueryEnumerator<TComp1, TComp2, TComp3>(trait1, trait2, trait3, metaTraits);
return new EntityQueryEnumerator<TComp1, TComp2, TComp3>(trait1, trait2, trait3, _metaQuery);
}
public EntityQueryEnumerator<TComp1, TComp2, TComp3, TComp4> EntityQueryEnumerator<TComp1, TComp2, TComp3, TComp4>()
@@ -1070,8 +1073,8 @@ namespace Robust.Shared.GameObjects
var trait2 = _entTraitArray[CompIdx.ArrayIndex<TComp2>()];
var trait3 = _entTraitArray[CompIdx.ArrayIndex<TComp3>()];
var trait4 = _entTraitArray[CompIdx.ArrayIndex<TComp4>()];
var metaTraits = _entTraitArray[CompIdx.ArrayIndex<MetaDataComponent>()];
return new EntityQueryEnumerator<TComp1, TComp2, TComp3, TComp4>(trait1, trait2, trait3, trait4, metaTraits);
return new EntityQueryEnumerator<TComp1, TComp2, TComp3, TComp4>(trait1, trait2, trait3, trait4, _metaQuery);
}
/// <inheritdoc />
@@ -1091,15 +1094,11 @@ namespace Robust.Shared.GameObjects
}
else
{
var metaComps = _entTraitArray[CompIdx.ArrayIndex<MetaDataComponent>()];
foreach (var t1Comp in comps!.Values)
foreach (var t1Comp in comps.Values)
{
if (t1Comp.Deleted || !metaComps.TryGetValue(t1Comp.Owner, out var metaComp)) continue;
if (t1Comp.Deleted || !_metaQuery.TryGetComponentInternal(t1Comp.Owner, out var metaComp)) continue;
var meta = (MetaDataComponent)metaComp;
if (meta.EntityPaused) continue;
if (metaComp.EntityPaused) continue;
yield return (T)(object)t1Comp;
}
@@ -1304,7 +1303,7 @@ namespace Robust.Shared.GameObjects
var getState = new ComponentGetState(session, fromTick);
eventBus.RaiseComponentEvent(component, ref getState);
return getState.State ?? component.GetComponentState();
return getState.State ?? DefaultComponentState;
}
public bool CanGetComponentState(IEventBus eventBus, IComponent component, ICommonSession player)
@@ -1369,6 +1368,7 @@ namespace Robust.Shared.GameObjects
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
public TComp1 GetComponent(EntityUid uid)
{
if (_traitDict.TryGetValue(uid, out var comp) && !comp.Deleted)
@@ -1378,6 +1378,7 @@ namespace Robust.Shared.GameObjects
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
public bool TryGetComponent([NotNullWhen(true)] EntityUid? uid, [NotNullWhen(true)] out TComp1? component)
{
if (uid == null)
@@ -1390,6 +1391,7 @@ namespace Robust.Shared.GameObjects
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
public bool TryGetComponent(EntityUid uid, [NotNullWhen(true)] out TComp1? component)
{
if (_traitDict.TryGetValue(uid, out var comp) && !comp.Deleted)
@@ -1403,12 +1405,14 @@ namespace Robust.Shared.GameObjects
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
public bool HasComponent(EntityUid uid)
{
return _traitDict.TryGetValue(uid, out var comp) && !comp.Deleted;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
public bool Resolve(EntityUid uid, [NotNullWhen(true)] ref TComp1? component, bool logMissing = true)
{
if (component != null)
@@ -1430,6 +1434,7 @@ namespace Robust.Shared.GameObjects
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
public TComp1? CompOrNull(EntityUid uid)
{
if (TryGetComponent(uid, out var comp))
@@ -1437,6 +1442,103 @@ namespace Robust.Shared.GameObjects
return null;
}
#region Internal
/// <summary>
/// Elides the component.Deleted check of <see cref="GetComponent"/>
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
internal TComp1 GetComponentInternal(EntityUid uid)
{
if (_traitDict.TryGetValue(uid, out var comp))
return (TComp1) comp;
throw new KeyNotFoundException($"Entity {uid} does not have a component of type {typeof(TComp1)}");
}
/// <summary>
/// Elides the component.Deleted check of <see cref="TryGetComponent(System.Nullable{Robust.Shared.GameObjects.EntityUid},out TComp1?)"/>
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
internal bool TryGetComponentInternal([NotNullWhen(true)] EntityUid? uid, [NotNullWhen(true)] out TComp1? component)
{
if (uid == null)
{
component = default;
return false;
}
return TryGetComponentInternal(uid.Value, out component);
}
/// <summary>
/// Elides the component.Deleted check of <see cref="TryGetComponent(System.Nullable{Robust.Shared.GameObjects.EntityUid},out TComp1?)"/>
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
internal bool TryGetComponentInternal(EntityUid uid, [NotNullWhen(true)] out TComp1? component)
{
if (_traitDict.TryGetValue(uid, out var comp))
{
component = (TComp1) comp;
return true;
}
component = default;
return false;
}
/// <summary>
/// Elides the component.Deleted check of <see cref="HasComponent"/>
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
internal bool HasComponentInternal(EntityUid uid)
{
return _traitDict.TryGetValue(uid, out var comp) && !comp.Deleted;
}
/// <summary>
/// Elides the component.Deleted check of <see cref="Resolve"/>
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
internal bool ResolveInternal(EntityUid uid, [NotNullWhen(true)] ref TComp1? component, bool logMissing = true)
{
if (component != null)
{
DebugTools.Assert(uid == component.Owner, "Specified Entity is not the component's Owner!");
return true;
}
if (_traitDict.TryGetValue(uid, out var comp))
{
component = (TComp1)comp;
return true;
}
if (logMissing)
_sawmill.Error($"Can't resolve \"{typeof(TComp1)}\" on entity {uid}!\n{new StackTrace(1, true)}");
return false;
}
/// <summary>
/// Elides the component.Deleted check of <see cref="CompOrNull"/>
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
internal TComp1? CompOrNullInternal(EntityUid uid)
{
if (TryGetComponent(uid, out var comp))
return comp;
return null;
}
#endregion
}
#region Query
@@ -1448,14 +1550,14 @@ namespace Robust.Shared.GameObjects
where TComp1 : Component
{
private Dictionary<EntityUid, Component>.Enumerator _traitDict;
private readonly Dictionary<EntityUid, Component> _metaDict;
private readonly EntityQuery<MetaDataComponent> _metaQuery;
public EntityQueryEnumerator(
Dictionary<EntityUid, Component> traitDict,
Dictionary<EntityUid, Component> metaDict)
EntityQuery<MetaDataComponent> metaQuery)
{
_traitDict = traitDict.GetEnumerator();
_metaDict = metaDict;
_metaQuery = metaQuery;
}
public bool MoveNext(out EntityUid uid, [NotNullWhen(true)] out TComp1? comp1)
@@ -1476,7 +1578,7 @@ namespace Robust.Shared.GameObjects
continue;
}
if (!_metaDict.TryGetValue(current.Key, out var metaComp) || ((MetaDataComponent)metaComp).EntityPaused)
if (!_metaQuery.TryGetComponentInternal(current.Key, out var metaComp) || metaComp.EntityPaused)
{
continue;
}
@@ -1508,16 +1610,16 @@ namespace Robust.Shared.GameObjects
{
private Dictionary<EntityUid, Component>.Enumerator _traitDict;
private readonly Dictionary<EntityUid, Component> _traitDict2;
private readonly Dictionary<EntityUid, Component> _metaDict;
private readonly EntityQuery<MetaDataComponent> _metaQuery;
public EntityQueryEnumerator(
Dictionary<EntityUid, Component> traitDict,
Dictionary<EntityUid, Component> traitDict2,
Dictionary<EntityUid, Component> metaDict)
EntityQuery<MetaDataComponent> metaQuery)
{
_traitDict = traitDict.GetEnumerator();
_traitDict2 = traitDict2;
_metaDict = metaDict;
_metaQuery = metaQuery;
}
public bool MoveNext(out EntityUid uid, [NotNullWhen(true)] out TComp1? comp1, [NotNullWhen(true)] out TComp2? comp2)
@@ -1539,7 +1641,7 @@ namespace Robust.Shared.GameObjects
continue;
}
if (!_metaDict.TryGetValue(current.Key, out var metaComp) || ((MetaDataComponent)metaComp).EntityPaused)
if (!_metaQuery.TryGetComponentInternal(current.Key, out var metaComp) || metaComp.EntityPaused)
{
continue;
}
@@ -1579,18 +1681,18 @@ namespace Robust.Shared.GameObjects
private Dictionary<EntityUid, Component>.Enumerator _traitDict;
private readonly Dictionary<EntityUid, Component> _traitDict2;
private readonly Dictionary<EntityUid, Component> _traitDict3;
private readonly Dictionary<EntityUid, Component> _metaDict;
private readonly EntityQuery<MetaDataComponent> _metaQuery;
public EntityQueryEnumerator(
Dictionary<EntityUid, Component> traitDict,
Dictionary<EntityUid, Component> traitDict2,
Dictionary<EntityUid, Component> traitDict3,
Dictionary<EntityUid, Component> metaDict)
EntityQuery<MetaDataComponent> metaQuery)
{
_traitDict = traitDict.GetEnumerator();
_traitDict2 = traitDict2;
_traitDict3 = traitDict3;
_metaDict = metaDict;
_metaQuery = metaQuery;
}
public bool MoveNext(out EntityUid uid, [NotNullWhen(true)] out TComp1? comp1, [NotNullWhen(true)] out TComp2? comp2, [NotNullWhen(true)] out TComp3? comp3)
@@ -1613,7 +1715,7 @@ namespace Robust.Shared.GameObjects
continue;
}
if (!_metaDict.TryGetValue(current.Key, out var metaComp) || ((MetaDataComponent)metaComp).EntityPaused)
if (!_metaQuery.TryGetComponentInternal(current.Key, out var metaComp) || metaComp.EntityPaused)
{
continue;
}
@@ -1664,20 +1766,20 @@ namespace Robust.Shared.GameObjects
private readonly Dictionary<EntityUid, Component> _traitDict2;
private readonly Dictionary<EntityUid, Component> _traitDict3;
private readonly Dictionary<EntityUid, Component> _traitDict4;
private readonly Dictionary<EntityUid, Component> _metaDict;
private readonly EntityQuery<MetaDataComponent> _metaQuery;
public EntityQueryEnumerator(
Dictionary<EntityUid, Component> traitDict,
Dictionary<EntityUid, Component> traitDict2,
Dictionary<EntityUid, Component> traitDict3,
Dictionary<EntityUid, Component> traitDict4,
Dictionary<EntityUid, Component> metaDict)
EntityQuery<MetaDataComponent> metaQuery)
{
_traitDict = traitDict.GetEnumerator();
_traitDict2 = traitDict2;
_traitDict3 = traitDict3;
_traitDict4 = traitDict4;
_metaDict = metaDict;
_metaQuery = metaQuery;
}
public bool MoveNext(out EntityUid uid, [NotNullWhen(true)] out TComp1? comp1, [NotNullWhen(true)] out TComp2? comp2, [NotNullWhen(true)] out TComp3? comp3, [NotNullWhen(true)] out TComp4? comp4)
@@ -1701,7 +1803,7 @@ namespace Robust.Shared.GameObjects
continue;
}
if (!_metaDict.TryGetValue(current.Key, out var metaComp) || ((MetaDataComponent)metaComp).EntityPaused)
if (!_metaQuery.TryGetComponentInternal(current.Key, out var metaComp) || metaComp.EntityPaused)
{
continue;
}

View File

@@ -75,7 +75,6 @@ namespace Robust.Shared.GameObjects
public event Action<EntityUid>? EntityDirtied; // only raised after initialization
private string _xformName = string.Empty;
private string _metaName = string.Empty;
private ISawmill _sawmill = default!;
private ISawmill _resolveSawmill = default!;
@@ -102,7 +101,6 @@ namespace Robust.Shared.GameObjects
InitializeComponents();
_xformName = _componentFactory.GetComponentName(typeof(TransformComponent));
_metaName = _componentFactory.GetComponentName(typeof(MetaDataComponent));
_sawmill = LogManager.GetSawmill("entity");
_resolveSawmill = LogManager.GetSawmill("resolve");
@@ -114,7 +112,7 @@ namespace Robust.Shared.GameObjects
/// </summary>
public bool IsDefault(EntityUid uid)
{
if (!TryGetComponent<MetaDataComponent>(uid, out var metadata) || metadata.EntityPrototype == null)
if (!_metaQuery.TryGetComponent(uid, out var metadata) || metadata.EntityPrototype == null)
return false;
var prototype = metadata.EntityPrototype;

View File

@@ -398,7 +398,7 @@ public partial class EntitySystem
/// <inheritdoc cref="IEntityManager.GetComponent&lt;T&gt;"/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected T Comp<T>(EntityUid uid) where T : class, IComponent
protected T Comp<T>(EntityUid uid) where T : Component
{
return EntityManager.GetComponent<T>(uid);
}

View File

@@ -1,7 +1,4 @@
using System;
using Robust.Shared.GameStates;
using Robust.Shared.Network;
using Robust.Shared.Players;
using Robust.Shared.Timing;
namespace Robust.Shared.GameObjects
@@ -63,24 +60,5 @@ namespace Robust.Shared.GameObjects
/// This is the last game tick Dirty() was called.
/// </summary>
GameTick LastModifiedTick { get; }
/// <summary>
/// Get the component's state for replicating on the client.
/// </summary>
/// <returns>ComponentState object</returns>
ComponentState GetComponentState();
/// <summary>
/// Handles an incoming component state from the server.
/// </summary>
/// <remarks>
/// This function should only be called on the client.
/// Both, one, or neither of the two states can be null.
/// On the next tick, curState will be nextState.
/// Passing null for both arguments should do nothing.
/// </remarks>
/// <param name="curState">Current component state for this tick.</param>
/// <param name="nextState">Next component state for the next tick.</param>
void HandleComponentState(ComponentState? curState, ComponentState? nextState);
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using JetBrains.Annotations;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
@@ -153,6 +154,7 @@ namespace Robust.Shared.GameObjects
/// <exception cref="UnknownComponentException">
/// Thrown if no component exists with the given type <see cref="componentType"/>.
/// </exception>
[Pure]
string GetComponentName(Type componentType);
/// <summary>

View File

@@ -236,7 +236,7 @@ namespace Robust.Shared.GameObjects
/// <typeparam name="T">A trait or type of a component to retrieve.</typeparam>
/// <param name="uid">Entity UID to look on.</param>
/// <returns>The component of Type from the Entity.</returns>
T GetComponent<T>(EntityUid uid);
T GetComponent<T>(EntityUid uid) where T : IComponent;
/// <summary>
/// Returns the component of a specific type.

View File

@@ -0,0 +1,6 @@
namespace Robust.Shared.GameObjects;
public abstract class SharedEyeSystem : EntitySystem
{
}

View File

@@ -41,6 +41,7 @@ namespace Robust.UnitTesting.Client.GameObjects.Components
var (sim, gridIdA, gridIdB) = SimulationFactory();
var entMan = sim.Resolve<IEntityManager>();
var mapMan = sim.Resolve<IMapManager>();
var xformSystem = entMan.System<SharedTransformSystem>();
var gridA = mapMan.GetGrid(gridIdA);
var gridB = mapMan.GetGrid(gridIdB);
@@ -51,18 +52,22 @@ namespace Robust.UnitTesting.Client.GameObjects.Components
var child = entMan.SpawnEntity(null, initialPos);
var parentTrans = entMan.GetComponent<TransformComponent>(parent);
var childTrans = entMan.GetComponent<TransformComponent>(child);
ComponentHandleState handleState;
var compState = new TransformComponentState(new Vector2(5, 5), new Angle(0), gridB.Owner, false, false);
parentTrans.HandleComponentState(compState, null);
handleState = new ComponentHandleState(compState, null);
xformSystem.OnHandleState(parent, parentTrans, ref handleState);
compState = new TransformComponentState(new Vector2(6, 6), new Angle(0), gridB.Owner, false, false);
childTrans.HandleComponentState(compState, null);
handleState = new ComponentHandleState(compState, null);
xformSystem.OnHandleState(child, childTrans, ref handleState);
// World pos should be 6, 6 now.
// Act
var oldWpos = childTrans.WorldPosition;
compState = new TransformComponentState(new Vector2(1, 1), new Angle(0), parent, false, false);
childTrans.HandleComponentState(compState, null);
handleState = new ComponentHandleState(compState, null);
xformSystem.OnHandleState(child, childTrans, ref handleState);
var newWpos = childTrans.WorldPosition;
// Assert

View File

@@ -5,6 +5,7 @@ using NUnit.Framework;
using Robust.Server.Containers;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Utility;
@@ -269,7 +270,8 @@ namespace Robust.UnitTesting.Server.GameObjects.Components
public void Container_Serialize()
{
var sim = SimulationFactory();
var containerSys = sim.Resolve<IEntitySystemManager>().GetEntitySystem<ContainerSystem>();
var entManager = sim.Resolve<IEntityManager>();
var containerSys = entManager.System<ContainerSystem>();
var entity = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), new Vector2(0, 0)));
var container = containerSys.MakeContainer<Container>(entity, "dummy");
@@ -279,10 +281,12 @@ namespace Robust.UnitTesting.Server.GameObjects.Components
container.ShowContents = true;
container.Insert(childEnt);
var containerMan = IoCManager.Resolve<IEntityManager>().GetComponent<IContainerManager>(entity);
var state = (ContainerManagerComponent.ContainerManagerComponentState)containerMan.GetComponentState();
var containerMan = entManager.GetComponent<IContainerManager>(entity);
var getState = new ComponentGetState();
entManager.EventBus.RaiseComponentEvent(containerMan, ref getState);
var state = (ContainerManagerComponent.ContainerManagerComponentState)getState.State!;
Assert.That(state.Containers.Count, Is.EqualTo(1));
Assert.That(state.Containers, Has.Count.EqualTo(1));
var cont = state.Containers.Values.First();
Assert.That(cont.Id, Is.EqualTo("dummy"));
Assert.That(cont.OccludesLight, Is.True);