From 1ea7071ffbfd5ba25a128e2202f074e2a2667e74 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Sun, 17 Sep 2023 11:03:11 +1000 Subject: [PATCH] Backport some arch comp net changes (#4408) Co-authored-by: ElectroJr --- Robust.Client/GameStates/ClientDirtySystem.cs | 3 +- .../GameStates/ClientGameStateManager.cs | 73 ++++---- .../EntitySystems/MapLoaderSystem.cs | 2 +- .../EntitySystems/ServerMetaDataSystem.cs | 8 +- .../GameObjects/ServerEntityManager.cs | 12 -- Robust.Server/GameStates/PvsSystem.cs | 4 +- .../GameObjects/ComponentEventArgs.cs | 5 +- .../Components/MetaDataComponent.cs | 7 + .../GameObjects/EntityManager.Components.cs | 177 +++++++++--------- .../GameObjects/EntityManager.Network.cs | 15 ++ Robust.Shared/GameObjects/EntityManager.cs | 14 +- .../GameObjects/EntitySystem.Proxy.cs | 4 +- .../GameObjects/IEntityManager.Components.cs | 34 ++-- .../GameObjects/IEntityManager.Network.cs | 6 + 14 files changed, 195 insertions(+), 169 deletions(-) diff --git a/Robust.Client/GameStates/ClientDirtySystem.cs b/Robust.Client/GameStates/ClientDirtySystem.cs index 723188485..25013259e 100644 --- a/Robust.Client/GameStates/ClientDirtySystem.cs +++ b/Robust.Client/GameStates/ClientDirtySystem.cs @@ -1,7 +1,6 @@ using Robust.Client.Timing; using Robust.Shared.GameObjects; using Robust.Shared.IoC; -using Robust.Shared.Log; using Robust.Shared.Utility; using System; using System.Collections.Generic; @@ -54,7 +53,7 @@ public sealed class ClientDirtySystem : EntitySystem var uid = args.BaseArgs.Owner; var comp = args.BaseArgs.Component; - if (!_timing.InPrediction || !comp.NetSyncEnabled || IsClientSide(uid)) + if (!_timing.InPrediction || !comp.NetSyncEnabled || IsClientSide(uid, args.Meta)) return; // Was this component added during prediction? If yes, then there is no need to re-add it when resetting. diff --git a/Robust.Client/GameStates/ClientGameStateManager.cs b/Robust.Client/GameStates/ClientGameStateManager.cs index c1eb5087c..7f8f37232 100644 --- a/Robust.Client/GameStates/ClientGameStateManager.cs +++ b/Robust.Client/GameStates/ClientGameStateManager.cs @@ -47,7 +47,7 @@ namespace Robust.Client.GameStates = new(); // Game state dictionaries that get used every tick. - private readonly Dictionary _toApply = new(); + private readonly Dictionary _toApply = new(); private readonly Dictionary _toCreate = new(); private readonly Dictionary _compStateWork = new(); private readonly Dictionary> _pendingReapplyNetStates = new(); @@ -497,11 +497,7 @@ namespace Robust.Client.GameStates countReset += 1; - var netComps = _entityManager.GetNetComponentsOrNull(entity); - if (netComps == null) - continue; - - foreach (var (netId, comp) in netComps.Value) + foreach (var (netId, comp) in meta.NetComponents) { if (!comp.NetSyncEnabled) continue; @@ -549,13 +545,13 @@ namespace Robust.Client.GameStates { foreach (var netId in netIds) { - if (_entities.HasComponent(entity, netId)) + if (meta.NetComponents.ContainsKey(netId)) continue; if (!last.TryGetValue(netId, out var state)) continue; - var comp = _entityManager.AddComponent(entity, netId); + var comp = _entityManager.AddComponent(entity, netId, meta); if (_sawmill.Level <= LogLevel.Debug) _sawmill.Debug($" A component was removed: {comp.GetType()}"); @@ -597,11 +593,11 @@ namespace Robust.Client.GameStates foreach (var netEntity in createdEntities) { - var createdEntity = _entityManager.GetEntity(netEntity); + var (createdEntity, meta) = _entityManager.GetEntityData(netEntity); var compData = new Dictionary(); outputData.Add(netEntity, compData); - foreach (var (netId, component) in _entityManager.GetNetComponents(createdEntity)) + foreach (var (netId, component) in meta.NetComponents) { if (!component.NetSyncEnabled) continue; @@ -692,9 +688,9 @@ namespace Robust.Client.GameStates var uid = _entities.CreateEntity(metaState.PrototypeId); _toCreate.Add(es.NetEntity, es); - _toApply.Add(uid, (es.NetEntity, false, GameTick.Zero, es, null)); - var newMeta = metas.GetComponent(uid); + _toApply.Add(uid, (es.NetEntity, newMeta, false, GameTick.Zero, es, null)); + // Client creates a client-side net entity for the newly created entity. // We need to clear this mapping before assigning the real net id. @@ -742,7 +738,7 @@ namespace Robust.Client.GameStates continue; } - _toApply.Add(uid, (es.NetEntity, isEnteringPvs, meta.LastStateApplied, es, null)); + _toApply.Add(uid, (es.NetEntity, meta, isEnteringPvs, meta.LastStateApplied, es, null)); meta.LastStateApplied = curState.ToSequence; } @@ -756,19 +752,17 @@ namespace Robust.Client.GameStates { foreach (var es in nextState.EntityStates.Span) { - if (!_entityManager.TryGetEntity(es.NetEntity, out var uid)) + if (!_entityManager.TryGetEntityData(es.NetEntity, out var uid, out var meta)) continue; - DebugTools.Assert(metas.HasComponent(uid)); - // Does the next state actually have any future information about this entity that could be used for interpolation? if (es.EntityLastModified != nextState.ToSequence) continue; if (_toApply.TryGetValue(uid.Value, out var state)) - _toApply[uid.Value] = (es.NetEntity, state.EnteringPvs, state.LastApplied, state.curState, es); + _toApply[uid.Value] = (es.NetEntity, meta, state.EnteringPvs, state.LastApplied, state.curState, es); else - _toApply[uid.Value] = (es.NetEntity, false, GameTick.Zero, null, es); + _toApply[uid.Value] = (es.NetEntity, meta, false, GameTick.Zero, null, es); } } @@ -783,7 +777,7 @@ namespace Robust.Client.GameStates if (!metas.TryGetComponent(uid, out var meta)) continue; - _toApply[uid] = (_entityManager.GetNetEntity(uid, meta), false, GameTick.Zero, null, null); + _toApply[uid] = (meta.NetEntity, meta, false, GameTick.Zero, null, null); } var queuedBroadphaseUpdates = new List<(EntityUid, TransformComponent)>(enteringPvs); @@ -793,7 +787,7 @@ namespace Robust.Client.GameStates { foreach (var (entity, data) in _toApply) { - HandleEntityState(entity, data.NetEntity, _entities.EventBus, data.curState, + HandleEntityState(entity, data.NetEntity, data.Meta, _entities.EventBus, data.curState, data.nextState, data.LastApplied, curState.ToSequence, data.EnteringPvs); if (!data.EnteringPvs) @@ -1133,7 +1127,7 @@ namespace Robust.Client.GameStates #endif } - private void HandleEntityState(EntityUid uid, NetEntity netEntity, IEventBus bus, EntityState? curState, + private void HandleEntityState(EntityUid uid, NetEntity netEntity, MetaDataComponent meta, IEventBus bus, EntityState? curState, EntityState? nextState, GameTick lastApplied, GameTick toTick, bool enteringPvs) { _compStateWork.Clear(); @@ -1142,7 +1136,7 @@ namespace Robust.Client.GameStates if (curState?.NetComponents != null) { RemQueue toRemove = new(); - foreach (var (id, comp) in _entities.GetNetComponents(uid)) + foreach (var (id, comp) in meta.NetComponents) { if (comp.NetSyncEnabled && !curState.NetComponents.Contains(id)) toRemove.Add(comp); @@ -1150,7 +1144,7 @@ namespace Robust.Client.GameStates foreach (var comp in toRemove) { - _entities.RemoveComponent(uid, comp); + _entities.RemoveComponent(uid, comp, meta); } } @@ -1163,12 +1157,11 @@ namespace Robust.Client.GameStates // the entity. most notably, all entities will have been ejected from their containers. foreach (var (id, state) in _processor.GetLastServerStates(netEntity)) { - if (!_entityManager.TryGetComponent(uid, id, out var comp)) + if (!meta.NetComponents.TryGetValue(id, out var comp)) { - comp = _compFactory.GetComponent(id); - var newComp = (Component)comp; - newComp.Owner = uid; - _entityManager.AddComponent(uid, newComp, true); + comp = (Component) _compFactory.GetComponent(id); + comp.Owner = uid; + _entityManager.AddComponent(uid, comp, true, metadata: meta); } _compStateWork[id] = (comp, state, null); @@ -1178,12 +1171,11 @@ namespace Robust.Client.GameStates { foreach (var compChange in curState.ComponentChanges.Span) { - if (!_entityManager.TryGetComponent(uid, compChange.NetID, out var comp)) + if (!meta.NetComponents.TryGetValue(compChange.NetID, out var comp)) { - comp = _compFactory.GetComponent(compChange.NetID); - var newComp = (Component)comp; - newComp.Owner = uid; - _entityManager.AddComponent(uid, newComp, true); + comp = (Component) _compFactory.GetComponent(compChange.NetID); + comp.Owner = uid; + _entityManager.AddComponent(uid, comp, true, metadata:meta); } else if (compChange.LastModifiedTick <= lastApplied && lastApplied != GameTick.Zero) continue; @@ -1199,7 +1191,7 @@ namespace Robust.Client.GameStates if (compState.LastModifiedTick != toTick + 1) continue; - if (!_entityManager.TryGetComponent(uid, compState.NetID, out var comp)) + if (!meta.NetComponents.TryGetValue(compState.NetID, out var comp)) { // The component can be null here due to interp, because the NEXT state will have a new // component, but the component does not yet exist. @@ -1227,7 +1219,7 @@ namespace Robust.Client.GameStates continue; if (_compStateWork.ContainsKey(netId.Value) || - !_entityManager.TryGetComponent(uid, type, out var comp) || + !meta.NetComponents.TryGetValue(netId.Value, out var comp) || !lastState.TryGetValue(netId.Value, out var lastCompState)) { continue; @@ -1398,12 +1390,11 @@ namespace Robust.Client.GameStates foreach (var (id, state) in lastState) { - if (!_entityManager.TryGetComponent(uid, id, out var comp)) + if (!meta.NetComponents.TryGetValue(id, out var comp)) { - comp = _compFactory.GetComponent(id); - var newComp = (Component)comp; - newComp.Owner = uid; - _entityManager.AddComponent(uid, newComp, true); + comp = (Component) _compFactory.GetComponent(id); + comp.Owner = uid; + _entityManager.AddComponent(uid, comp, true, meta); } var handleState = new ComponentHandleState(state, null); @@ -1412,7 +1403,7 @@ namespace Robust.Client.GameStates // ensure we don't have any extra components RemQueue toRemove = new(); - foreach (var (id, comp) in _entities.GetNetComponents(uid)) + foreach (var (id, comp) in meta.NetComponents) { if (comp.NetSyncEnabled && !lastState.ContainsKey(id)) toRemove.Add(comp); diff --git a/Robust.Server/GameObjects/EntitySystems/MapLoaderSystem.cs b/Robust.Server/GameObjects/EntitySystems/MapLoaderSystem.cs index 2f26d5e81..723acac05 100644 --- a/Robust.Server/GameObjects/EntitySystems/MapLoaderSystem.cs +++ b/Robust.Server/GameObjects/EntitySystems/MapLoaderSystem.cs @@ -879,7 +879,7 @@ public sealed class MapLoaderSystem : EntitySystem return; } - foreach (var (netId, component) in EntityManager.GetNetComponents(entity)) + foreach (var component in metadata.NetComponents.Values) { var compName = _factory.GetComponentName(component.GetType()); diff --git a/Robust.Server/GameObjects/EntitySystems/ServerMetaDataSystem.cs b/Robust.Server/GameObjects/EntitySystems/ServerMetaDataSystem.cs index 27db309de..8f91c3fc6 100644 --- a/Robust.Server/GameObjects/EntitySystems/ServerMetaDataSystem.cs +++ b/Robust.Server/GameObjects/EntitySystems/ServerMetaDataSystem.cs @@ -7,6 +7,7 @@ namespace Robust.Server.GameObjects; public sealed class ServerMetaDataSystem : MetaDataSystem { [Dependency] private readonly PvsSystem _pvsSystem = default!; + private EntityQuery _mQuery; public override void Initialize() { @@ -16,6 +17,7 @@ public sealed class ServerMetaDataSystem : MetaDataSystem EntityManager.ComponentAdded += OnComponentAdded; EntityManager.ComponentRemoved += OnComponentRemoved; + _mQuery = GetEntityQuery(); } public override void Shutdown() @@ -45,7 +47,7 @@ public sealed class ServerMetaDataSystem : MetaDataSystem if (obj.Terminating || !removed.NetSyncEnabled || (!removed.SessionSpecific && !removed.SendOnlyToOwner)) return; - foreach (var (_, comp) in EntityManager.GetNetComponents(obj.BaseArgs.Owner)) + foreach (var comp in obj.Meta.NetComponents.Values) { if (comp.LifeStage >= ComponentLifeStage.Removing) continue; @@ -55,7 +57,7 @@ public sealed class ServerMetaDataSystem : MetaDataSystem } // remove the flag - MetaData(obj.BaseArgs.Owner).Flags &= ~MetaDataFlags.SessionSpecific; + obj.Meta.Flags &= ~MetaDataFlags.SessionSpecific; } /// @@ -67,7 +69,7 @@ public sealed class ServerMetaDataSystem : MetaDataSystem if ((meta.Flags & MetaDataFlags.SessionSpecific) == 0) return; - foreach (var (_, comp) in EntityManager.GetNetComponents(uid)) + foreach (var (_, comp) in meta.NetComponents) { if (comp.SessionSpecific || comp.SendOnlyToOwner) Dirty(uid, comp); diff --git a/Robust.Server/GameObjects/ServerEntityManager.cs b/Robust.Server/GameObjects/ServerEntityManager.cs index 74d976c4e..6682d3b1a 100644 --- a/Robust.Server/GameObjects/ServerEntityManager.cs +++ b/Robust.Server/GameObjects/ServerEntityManager.cs @@ -139,9 +139,6 @@ namespace Robust.Server.GameObjects { _networkManager.RegisterNetMessage(HandleEntityNetworkMessage); - // For syncing component deletions. - ComponentRemoved += OnComponentRemoved; - _playerManager.PlayerStatusChanged += OnPlayerStatusChanged; _configurationManager.OnValueChanged(CVars.NetLogLateMsg, b => _logLateMsgs = b, true); @@ -168,15 +165,6 @@ namespace Robust.Server.GameObjects return _lastProcessedSequencesCmd[session]; } - private void OnComponentRemoved(RemovedComponentEventArgs e) - { - if (e.Terminating || !e.BaseArgs.Component.NetSyncEnabled) - return; - - if (TryGetComponent(e.BaseArgs.Owner, out MetaDataComponent? meta)) - meta.LastComponentRemoved = _gameTiming.CurTick; - } - /// public void SendSystemNetworkMessage(EntityEventArgs message, bool recordReplay = true) { diff --git a/Robust.Server/GameStates/PvsSystem.cs b/Robust.Server/GameStates/PvsSystem.cs index d245f8352..2a71b71d0 100644 --- a/Robust.Server/GameStates/PvsSystem.cs +++ b/Robust.Server/GameStates/PvsSystem.cs @@ -1204,7 +1204,7 @@ Transform last modified: {Transform(uid).LastModifiedTick}"); bool sendCompList = meta.LastComponentRemoved > fromTick; HashSet? netComps = sendCompList ? new() : null; - foreach (var (netId, component) in EntityManager.GetNetComponents(entityUid)) + foreach (var (netId, component) in meta.NetComponents) { if (!component.NetSyncEnabled) continue; @@ -1253,7 +1253,7 @@ Transform last modified: {Transform(uid).LastModifiedTick}"); HashSet netComps = new(); - foreach (var (netId, component) in EntityManager.GetNetComponents(entityUid)) + foreach (var (netId, component) in meta.NetComponents) { if (!component.NetSyncEnabled) continue; diff --git a/Robust.Shared/GameObjects/ComponentEventArgs.cs b/Robust.Shared/GameObjects/ComponentEventArgs.cs index d54815767..8901a1e73 100644 --- a/Robust.Shared/GameObjects/ComponentEventArgs.cs +++ b/Robust.Shared/GameObjects/ComponentEventArgs.cs @@ -46,10 +46,13 @@ namespace Robust.Shared.GameObjects public readonly bool Terminating; - public RemovedComponentEventArgs(ComponentEventArgs baseArgs, bool terminating) + public readonly MetaDataComponent Meta; + + public RemovedComponentEventArgs(ComponentEventArgs baseArgs, bool terminating, MetaDataComponent meta) { BaseArgs = baseArgs; Terminating = terminating; + Meta = meta; } } diff --git a/Robust.Shared/GameObjects/Components/MetaDataComponent.cs b/Robust.Shared/GameObjects/Components/MetaDataComponent.cs index fc3162ccc..c5a752aa7 100644 --- a/Robust.Shared/GameObjects/Components/MetaDataComponent.cs +++ b/Robust.Shared/GameObjects/Components/MetaDataComponent.cs @@ -8,6 +8,7 @@ using Robust.Shared.Timing; using Robust.Shared.Utility; using Robust.Shared.ViewVariables; using System; +using System.Collections.Generic; namespace Robust.Shared.GameObjects { @@ -63,6 +64,12 @@ namespace Robust.Shared.GameObjects [DataField("desc")] internal string? _entityDescription; internal EntityPrototype? _entityPrototype; + /// + /// The components attached to the entity that are currently networked. + /// + [ViewVariables] + internal readonly Dictionary NetComponents = new(); + /// /// Network identifier for this entity. /// diff --git a/Robust.Shared/GameObjects/EntityManager.Components.cs b/Robust.Shared/GameObjects/EntityManager.Components.cs index 61d1f166d..e095de539 100644 --- a/Robust.Shared/GameObjects/EntityManager.Components.cs +++ b/Robust.Shared/GameObjects/EntityManager.Components.cs @@ -35,9 +35,6 @@ namespace Robust.Shared.GameObjects private static readonly ComponentState DefaultComponentState = new(); - private readonly Dictionary> _netComponents - = new(EntityCapacity); - private readonly Dictionary> _entTraitDict = new(); @@ -70,7 +67,6 @@ namespace Robust.Shared.GameObjects /// public void ClearComponents() { - _netComponents.Clear(); _entCompIndex.Clear(); _deleteSet.Clear(); foreach (var dict in _entTraitDict.Values) @@ -175,13 +171,13 @@ namespace Robust.Shared.GameObjects } } - public Component AddComponent(EntityUid uid, ushort netId) + public Component AddComponent(EntityUid uid, ushort netId, MetaDataComponent? meta = null) { var newComponent = (Component)_componentFactory.GetComponent(netId); #pragma warning disable CS0618 // Type or member is obsolete newComponent.Owner = uid; #pragma warning restore CS0618 // Type or member is obsolete - AddComponent(uid, newComponent); + AddComponent(uid, newComponent, metadata: meta); return newComponent; } @@ -249,7 +245,7 @@ namespace Robust.Shared.GameObjects } /// - public void AddComponent(EntityUid uid, T component, bool overwrite = false) where T : Component + public void AddComponent(EntityUid uid, T component, bool overwrite = false, MetaDataComponent? metadata = null) where T : Component { if (!uid.IsValid() || !EntityExists(uid)) throw new ArgumentException($"Entity {uid} is not valid.", nameof(uid)); @@ -267,19 +263,23 @@ namespace Robust.Shared.GameObjects } #pragma warning restore CS0618 // Type or member is obsolete - AddComponentInternal(uid, component, overwrite, false); + AddComponentInternal(uid, component, overwrite, false, metadata); } - private void AddComponentInternal(EntityUid uid, T component, bool overwrite, bool skipInit) where T : Component + private void AddComponentInternal(EntityUid uid, T component, bool overwrite, bool skipInit, MetaDataComponent? metadata = null) where T : Component + { + // get interface aliases for mapping + var reg = _componentFactory.GetRegistration(component); + AddComponentInternal(uid, component, reg, overwrite, skipInit, metadata); + } + + private void AddComponentInternal(EntityUid uid, T component, ComponentRegistration reg, bool overwrite, bool skipInit, MetaDataComponent? metadata = null) where T : Component { // We can't use typeof(T) here in case T is just Component DebugTools.Assert(component is MetaDataComponent || - GetComponent(uid).EntityLifeStage < EntityLifeStage.Terminating, + (metadata ?? MetaQuery.GetComponent(uid)).EntityLifeStage < EntityLifeStage.Terminating, $"Attempted to add a {component.GetType().Name} component to an entity ({ToPrettyString(uid)}) while it is terminating"); - // get interface aliases for mapping - var reg = _componentFactory.GetRegistration(component); - // Check that there is no existing component. var type = reg.Idx; var dict = _entTraitArray[type.Value]; @@ -291,7 +291,7 @@ namespace Robust.Shared.GameObjects throw new InvalidOperationException( $"Component reference type {component.GetType().Name} already occupied by {duplicate}"); - RemoveComponentImmediate(duplicate, uid, false); + RemoveComponentImmediate(duplicate, uid, false, metadata); } // actually ADD the component @@ -303,14 +303,8 @@ namespace Robust.Shared.GameObjects { // the main comp grid keeps this in sync var netId = reg.NetID.Value; - - if (!_netComponents.TryGetValue(uid, out var netSet)) - { - netSet = new Dictionary(NetComponentCapacity); - _netComponents.Add(uid, netSet); - } - - netSet.Add(netId, component); + metadata ??= MetaQuery.GetComponentInternal(uid); + metadata.NetComponents.Add(netId, component); } else { @@ -326,7 +320,7 @@ namespace Robust.Shared.GameObjects if (skipInit) return; - var metadata = GetComponent(uid); + metadata ??= MetaQuery.GetComponentInternal(uid); if (!metadata.EntityInitialized && !metadata.EntityInitializing) return; @@ -345,45 +339,48 @@ namespace Robust.Shared.GameObjects /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool RemoveComponent(EntityUid uid) + public bool RemoveComponent(EntityUid uid, MetaDataComponent? meta = null) { - return RemoveComponent(uid, typeof(T)); + return RemoveComponent(uid, typeof(T), meta); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool RemoveComponent(EntityUid uid, Type type) + public bool RemoveComponent(EntityUid uid, Type type, MetaDataComponent? meta = null) { if (!TryGetComponent(uid, type, out var comp)) return false; - RemoveComponentImmediate((Component)comp, uid, false); + RemoveComponentImmediate((Component)comp, uid, false, meta); return true; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool RemoveComponent(EntityUid uid, ushort netId) + public bool RemoveComponent(EntityUid uid, ushort netId, MetaDataComponent? meta = null) { - if (!TryGetComponent(uid, netId, out var comp)) + if (!MetaQuery.Resolve(uid, ref meta)) return false; - RemoveComponentImmediate((Component)comp, uid, false); + if (!TryGetComponent(uid, netId, out var comp, meta)) + return false; + + RemoveComponentImmediate((Component)comp, uid, false, meta); return true; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RemoveComponent(EntityUid uid, IComponent component) + public void RemoveComponent(EntityUid uid, IComponent component, MetaDataComponent? meta = null) { - RemoveComponent(uid, (Component)component); + RemoveComponent(uid, (Component)component, meta); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RemoveComponent(EntityUid uid, Component component) + public void RemoveComponent(EntityUid uid, Component component, MetaDataComponent? meta = null) { - RemoveComponentImmediate(component, uid, false); + RemoveComponentImmediate(component, uid, false, meta); } /// @@ -405,9 +402,12 @@ namespace Robust.Shared.GameObjects /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool RemoveComponentDeferred(EntityUid uid, ushort netId) + public bool RemoveComponentDeferred(EntityUid uid, ushort netId, MetaDataComponent? meta = null) { - if (!TryGetComponent(uid, netId, out var comp)) + if (!MetaQuery.Resolve(uid, ref meta)) + return false; + + if (!TryGetComponent(uid, netId, out var comp, meta)) return false; RemoveComponentDeferred((Component)comp, uid, false); @@ -443,22 +443,28 @@ namespace Robust.Shared.GameObjects } /// - public void RemoveComponents(EntityUid uid) + public void RemoveComponents(EntityUid uid, MetaDataComponent? meta = null) { + if (!MetaQuery.Resolve(uid, ref meta)) + return; + foreach (var comp in InSafeOrder(_entCompIndex[uid])) { - RemoveComponentImmediate(comp, uid, false); + RemoveComponentImmediate(comp, uid, false, meta); } } /// - public void DisposeComponents(EntityUid uid) + public void DisposeComponents(EntityUid uid, MetaDataComponent? meta = null) { + if (!MetaQuery.Resolve(uid, ref meta)) + return; + foreach (var comp in InSafeOrder(_entCompIndex[uid])) { try { - RemoveComponentImmediate(comp, uid, true); + RemoveComponentImmediate(comp, uid, true, meta); } catch (Exception) { @@ -467,7 +473,6 @@ namespace Robust.Shared.GameObjects } _entCompIndex.Remove(uid); - _netComponents.Remove(uid); } private void RemoveComponentDeferred(Component component, EntityUid uid, bool terminating) @@ -508,8 +513,12 @@ namespace Robust.Shared.GameObjects #endif } - private void RemoveComponentImmediate(Component component, EntityUid uid, bool terminating) + private void RemoveComponentImmediate(Component component, EntityUid uid, bool terminating, + MetaDataComponent? meta) { + if (!MetaQuery.ResolveInternal(uid, ref meta)) + return; + if (component.Deleted) { _sawmill.Warning($"Deleting an already deleted component. Entity: {ToPrettyString(uid)}, Component: {_componentFactory.GetComponentName(component.GetType())}."); @@ -541,10 +550,11 @@ namespace Robust.Shared.GameObjects _runtimeLog.LogException(e, nameof(RemoveComponentImmediate)); } #endif - var eventArgs = new RemovedComponentEventArgs(new ComponentEventArgs(component, uid), terminating); + var eventArgs = new RemovedComponentEventArgs(new ComponentEventArgs(component, uid), terminating, meta); + meta.LastComponentRemoved = _gameTiming.CurTick; ComponentRemoved?.Invoke(eventArgs); _eventBus.OnComponentRemoved(eventArgs); - DeleteComponent(uid, component, terminating); + DeleteComponent(uid, component, terminating, meta); } /// @@ -556,6 +566,9 @@ namespace Robust.Shared.GameObjects continue; var uid = component.Owner; + if (!MetaQuery.TryGetComponentInternal(uid, out var meta)) + continue; + #if EXCEPTION_TOLERANCE try { @@ -579,30 +592,28 @@ namespace Robust.Shared.GameObjects _runtimeLog.LogException(e, nameof(CullRemovedComponents)); } #endif - var eventArgs = new RemovedComponentEventArgs(new ComponentEventArgs(component, uid), false); + + var eventArgs = new RemovedComponentEventArgs(new ComponentEventArgs(component, uid), false, meta); + meta.LastComponentRemoved = _gameTiming.CurTick; ComponentRemoved?.Invoke(eventArgs); _eventBus.OnComponentRemoved(eventArgs); - - DeleteComponent(uid, component, false); + DeleteComponent(uid, component, false, meta); } _deleteSet.Clear(); } - private void DeleteComponent(EntityUid entityUid, Component component, bool terminating) + private void DeleteComponent(EntityUid entityUid, Component component, bool terminating, MetaDataComponent? metadata = null) { - var type = component.GetType(); - var reg = _componentFactory.GetRegistration(type); + var reg = _componentFactory.GetRegistration(component); - if (!terminating && reg.NetID != null && _netComponents.TryGetValue(entityUid, out var netSet)) + if (!terminating && reg.NetID != null) { - if (netSet.Count == 1) - _netComponents.Remove(entityUid); - else - netSet.Remove(reg.NetID.Value); + metadata ??= MetaQuery.GetComponent(entityUid); + var netSet = metadata.NetComponents; - if (component.NetSyncEnabled) - DirtyEntity(entityUid); + if (netSet.Remove(reg.NetID.Value) && component.NetSyncEnabled) + DirtyEntity(entityUid, metadata); } _entTraitArray[reg.Idx.Value].Remove(entityUid); @@ -651,23 +662,25 @@ namespace Robust.Shared.GameObjects /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool HasComponent(EntityUid uid, ushort netId) + public bool HasComponent(EntityUid uid, ushort netId, MetaDataComponent? meta = null) { - return _netComponents.TryGetValue(uid, out var netSet) - && netSet.ContainsKey(netId); + if (!MetaQuery.Resolve(uid, ref meta)) + return false; + + return meta.NetComponents.ContainsKey(netId); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool HasComponent(EntityUid? uid, ushort netId) + public bool HasComponent(EntityUid? uid, ushort netId, MetaDataComponent? meta = null) { if (!uid.HasValue) { + DebugTools.AssertNull(meta); return false; } - return _netComponents.TryGetValue(uid.Value, out var netSet) - && netSet.ContainsKey(netId); + return HasComponent(uid.Value, netId, meta); } /// @@ -752,9 +765,9 @@ namespace Robust.Shared.GameObjects } /// - public IComponent GetComponent(EntityUid uid, ushort netId) + public IComponent GetComponent(EntityUid uid, ushort netId, MetaDataComponent? meta = null) { - return _netComponents[uid][netId]; + return (meta ?? MetaQuery.GetComponentInternal(uid)).NetComponents[netId]; } /// @@ -763,7 +776,7 @@ namespace Robust.Shared.GameObjects var dict = _entTraitArray[type.Value]; if (dict.TryGetValue(uid, out var comp)) { - return comp; + return comp; } throw new KeyNotFoundException($"Entity {uid} does not have a component of type {type}"); @@ -868,10 +881,10 @@ namespace Robust.Shared.GameObjects } /// - public bool TryGetComponent(EntityUid uid, ushort netId, [MaybeNullWhen(false)] out IComponent component) + public bool TryGetComponent(EntityUid uid, ushort netId, [MaybeNullWhen(false)] out IComponent component, MetaDataComponent? meta = null) { - if (_netComponents.TryGetValue(uid, out var netSet) - && netSet.TryGetValue(netId, out var comp)) + if (MetaQuery.TryGetComponentInternal(uid, out var metadata) + && metadata.NetComponents.TryGetValue(netId, out var comp)) { component = comp; return true; @@ -883,23 +896,16 @@ namespace Robust.Shared.GameObjects /// public bool TryGetComponent([NotNullWhen(true)] EntityUid? uid, ushort netId, - [MaybeNullWhen(false)] out IComponent component) + [MaybeNullWhen(false)] out IComponent component, MetaDataComponent? meta = null) { if (!uid.HasValue) { + DebugTools.AssertNull(meta); component = default; return false; } - if (_netComponents.TryGetValue(uid.Value, out var netSet) - && netSet.TryGetValue(netId, out var comp)) - { - component = comp; - return true; - } - - component = default; - return false; + return TryGetComponent(uid.Value, netId, out component, meta); } public EntityQuery GetEntityQuery() where TComp1 : Component @@ -967,17 +973,18 @@ namespace Robust.Shared.GameObjects } /// - public NetComponentEnumerable GetNetComponents(EntityUid uid) + public NetComponentEnumerable GetNetComponents(EntityUid uid, MetaDataComponent? meta = null) { - return new NetComponentEnumerable(_netComponents[uid]); + meta ??= MetaQuery.GetComponentInternal(uid); + return new NetComponentEnumerable(meta.NetComponents); } /// - public NetComponentEnumerable? GetNetComponentsOrNull(EntityUid uid) + public NetComponentEnumerable? GetNetComponentsOrNull(EntityUid uid, MetaDataComponent? meta = null) { - return _netComponents.TryGetValue(uid, out var data) - ? new NetComponentEnumerable(data) - : null; + return MetaQuery.Resolve(uid, ref meta) + ? new NetComponentEnumerable(meta.NetComponents) + : null; } #region Join Functions diff --git a/Robust.Shared/GameObjects/EntityManager.Network.cs b/Robust.Shared/GameObjects/EntityManager.Network.cs index 2cc317841..fd3a73a67 100644 --- a/Robust.Shared/GameObjects/EntityManager.Network.cs +++ b/Robust.Shared/GameObjects/EntityManager.Network.cs @@ -72,6 +72,21 @@ public partial class EntityManager return false; } + /// + public bool TryGetEntityData(NetEntity nEntity, [NotNullWhen(true)] out EntityUid? entity, [NotNullWhen(true)] out MetaDataComponent? meta) + { + if (NetEntityLookup.TryGetValue(nEntity, out var went)) + { + entity = went.Item1; + meta = went.Item2; + return true; + } + + entity = null; + meta = null; + return false; + } + /// public bool TryGetEntity(NetEntity? nEntity, [NotNullWhen(true)] out EntityUid? entity) { diff --git a/Robust.Shared/GameObjects/EntityManager.cs b/Robust.Shared/GameObjects/EntityManager.cs index fd57862a7..3e4df6fe7 100644 --- a/Robust.Shared/GameObjects/EntityManager.cs +++ b/Robust.Shared/GameObjects/EntityManager.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Runtime.CompilerServices; using Prometheus; using Robust.Shared.Log; using Robust.Shared.Map; @@ -85,6 +86,9 @@ namespace Robust.Shared.GameObjects private string _xformName = string.Empty; + private ComponentRegistration _metaReg = default!; + private ComponentRegistration _xformReg = default!; + private SharedMapSystem _mapSystem = default!; private ISawmill _sawmill = default!; @@ -111,7 +115,9 @@ namespace Robust.Shared.GameObjects _eventBus = new EntityEventBus(this); InitializeComponents(); - _xformName = _componentFactory.GetComponentName(typeof(TransformComponent)); + _metaReg = _componentFactory.GetRegistration(typeof(MetaDataComponent)); + _xformReg = _componentFactory.GetRegistration(typeof(TransformComponent)); + _xformName = _xformReg.Name; _sawmill = LogManager.GetSawmill("entity"); _resolveSawmill = LogManager.GetSawmill("resolve"); @@ -645,10 +651,12 @@ namespace Robust.Shared.GameObjects Entities.Add(uid); // add the required MetaDataComponent directly. - AddComponentInternal(uid, metadata, false, false); + AddComponentInternal(uid, metadata, _metaReg, false, true, metadata); // allocate the required TransformComponent - AddComponent(uid); + var xformComp = Unsafe.As(_componentFactory.GetComponent(_xformReg)); + xformComp.Owner = uid; + AddComponentInternal(uid, xformComp, false, true, metadata); return uid; } diff --git a/Robust.Shared/GameObjects/EntitySystem.Proxy.cs b/Robust.Shared/GameObjects/EntitySystem.Proxy.cs index e0e3f3e1a..24bce1399 100644 --- a/Robust.Shared/GameObjects/EntitySystem.Proxy.cs +++ b/Robust.Shared/GameObjects/EntitySystem.Proxy.cs @@ -915,9 +915,9 @@ public partial class EntitySystem #region NetEntities [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected bool IsClientSide(EntityUid entity) + protected bool IsClientSide(EntityUid entity, MetaDataComponent? meta = null) { - return EntityManager.IsClientSide(entity); + return EntityManager.IsClientSide(entity, meta); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/Robust.Shared/GameObjects/IEntityManager.Components.cs b/Robust.Shared/GameObjects/IEntityManager.Components.cs index f28522163..527f3988e 100644 --- a/Robust.Shared/GameObjects/IEntityManager.Components.cs +++ b/Robust.Shared/GameObjects/IEntityManager.Components.cs @@ -49,7 +49,7 @@ namespace Robust.Shared.GameObjects /// /// Adds a Component with a given network id to an entity. /// - Component AddComponent(EntityUid uid, ushort netId); + Component AddComponent(EntityUid uid, ushort netId, MetaDataComponent? meta = null); /// /// Adds an uninitialized Component type to an entity. @@ -70,7 +70,7 @@ namespace Robust.Shared.GameObjects /// Entity being modified. /// Component to add. /// Should it overwrite existing components? - void AddComponent(EntityUid uid, T component, bool overwrite = false) where T : Component; + void AddComponent(EntityUid uid, T component, bool overwrite = false, MetaDataComponent? metadata = null) where T : Component; /// /// Removes the component with the specified reference type, @@ -78,7 +78,7 @@ namespace Robust.Shared.GameObjects /// /// The component reference type to remove. /// Entity UID to modify. - bool RemoveComponent(EntityUid uid); + bool RemoveComponent(EntityUid uid, MetaDataComponent? meta = null); /// /// Removes the component with a specified type. @@ -86,7 +86,7 @@ namespace Robust.Shared.GameObjects /// Entity UID to modify. /// A trait or component type to check for. /// Returns false if the entity did not have the specified component. - bool RemoveComponent(EntityUid uid, Type type); + bool RemoveComponent(EntityUid uid, Type type, MetaDataComponent? meta = null); /// /// Removes the component with a specified network ID. @@ -94,14 +94,14 @@ namespace Robust.Shared.GameObjects /// Entity UID to modify. /// Network ID of the component to remove. /// Returns false if the entity did not have the specified component. - bool RemoveComponent(EntityUid uid, ushort netID); + bool RemoveComponent(EntityUid uid, ushort netID, MetaDataComponent? meta = null); /// /// Removes the specified component. Throws if the given component does not belong to the entity. /// /// Entity UID to modify. /// Component to remove. - void RemoveComponent(EntityUid uid, IComponent component); + void RemoveComponent(EntityUid uid, IComponent component, MetaDataComponent? meta = null); /// /// Immediately shuts down a component, but defers the removal and deletion until the end of the tick. @@ -125,7 +125,7 @@ namespace Robust.Shared.GameObjects /// Entity UID to modify. /// Network ID of the component to remove. /// Returns false if the entity did not have the specified component. - bool RemoveComponentDeferred(EntityUid uid, ushort netID); + bool RemoveComponentDeferred(EntityUid uid, ushort netID, MetaDataComponent? meta = null); /// /// Immediately shuts down a component, but defers the removal and deletion until the end of the tick. @@ -147,7 +147,7 @@ namespace Robust.Shared.GameObjects /// Removes all components from an entity, except the required components. /// /// Entity UID to modify. - void RemoveComponents(EntityUid uid); + void RemoveComponents(EntityUid uid, MetaDataComponent? meta = null); /// /// Removes ALL components from an entity. This includes the required components, @@ -155,7 +155,7 @@ namespace Robust.Shared.GameObjects /// used when deleting an entity. /// /// Entity UID to modify. - void DisposeComponents(EntityUid uid); + void DisposeComponents(EntityUid uid, MetaDataComponent? meta = null); /// /// Checks if the entity has a component type. @@ -187,7 +187,7 @@ namespace Robust.Shared.GameObjects /// Entity UID to check. /// A trait or component type to check for. /// True if the entity has the component type, otherwise false. - bool HasComponent(EntityUid ?uid, Type type); + bool HasComponent(EntityUid? uid, Type type); /// /// Checks if the entity has a component with a given network ID. This does not check @@ -196,7 +196,7 @@ namespace Robust.Shared.GameObjects /// Entity UID to check. /// Network ID to check for. /// True if the entity has a component with the given network ID, otherwise false. - bool HasComponent(EntityUid uid, ushort netId); + bool HasComponent(EntityUid uid, ushort netId, MetaDataComponent? meta = null); /// /// Checks if the entity has a component with a given network ID. This does not check @@ -205,7 +205,7 @@ namespace Robust.Shared.GameObjects /// Entity UID to check. /// Network ID to check for. /// True if the entity has a component with the given network ID, otherwise false. - bool HasComponent(EntityUid? uid, ushort netId); + bool HasComponent(EntityUid? uid, ushort netId, MetaDataComponent? meta = null); /// /// This method will always return a component for a certain entity, adding it if it's not there already. @@ -255,7 +255,7 @@ namespace Robust.Shared.GameObjects /// Entity UID to look on. /// Network ID of the component to retrieve. /// The component with the specified network id. - IComponent GetComponent(EntityUid uid, ushort netId); + IComponent GetComponent(EntityUid uid, ushort netId, MetaDataComponent? meta = null); /// /// Returns the component of a specific type, even if it has been marked for deletion. @@ -318,7 +318,7 @@ namespace Robust.Shared.GameObjects /// Component Network ID to check for. /// Component with the specified network id. /// If the component existed in the entity. - bool TryGetComponent(EntityUid uid, ushort netId, [NotNullWhen(true)] out IComponent? component); + bool TryGetComponent(EntityUid uid, ushort netId, [NotNullWhen(true)] out IComponent? component, MetaDataComponent? meta = null); /// /// Returns the component with a specified network ID. This does not check @@ -328,7 +328,7 @@ namespace Robust.Shared.GameObjects /// Component Network ID to check for. /// Component with the specified network id. /// If the component existed in the entity. - bool TryGetComponent([NotNullWhen(true)] EntityUid? uid, ushort netId, [NotNullWhen(true)] out IComponent? component); + bool TryGetComponent([NotNullWhen(true)] EntityUid? uid, ushort netId, [NotNullWhen(true)] out IComponent? component, MetaDataComponent? meta = null); /// /// Returns a cached struct enumerator with the specified component. @@ -364,7 +364,7 @@ namespace Robust.Shared.GameObjects /// /// Entity UID to look on. /// All components that have a network ID. - NetComponentEnumerable GetNetComponents(EntityUid uid); + NetComponentEnumerable GetNetComponents(EntityUid uid, MetaDataComponent? meta = null); /// /// Returns ALL networked components on an entity, including deleted ones. Returns null if the entity does @@ -372,7 +372,7 @@ namespace Robust.Shared.GameObjects /// /// Entity UID to look on. /// All components that have a network ID. - public NetComponentEnumerable? GetNetComponentsOrNull(EntityUid uid); + public NetComponentEnumerable? GetNetComponentsOrNull(EntityUid uid, MetaDataComponent? meta = null); /// /// Gets a component state. diff --git a/Robust.Shared/GameObjects/IEntityManager.Network.cs b/Robust.Shared/GameObjects/IEntityManager.Network.cs index 415369504..8fb461eab 100644 --- a/Robust.Shared/GameObjects/IEntityManager.Network.cs +++ b/Robust.Shared/GameObjects/IEntityManager.Network.cs @@ -22,6 +22,12 @@ public partial interface IEntityManager /// public bool TryGetEntity(NetEntity? nEntity, [NotNullWhen(true)] out EntityUid? entity); + /// + /// Tries to returns the corresponding local along with the metdata component. + /// + public bool TryGetEntityData(NetEntity nEntity, [NotNullWhen(true)] out EntityUid? entity, + [NotNullWhen(true)] out MetaDataComponent? meta); + /// /// TryGet version of ///