using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Robust.Shared.Map; using Robust.Shared.Utility; namespace Robust.Shared.GameObjects; public partial class EntityManager { // TODO POOLING // Just add overrides that take in an existing collection. /// /// Inverse lookup for net entities. /// Regular lookup uses MetadataComponent. /// protected readonly Dictionary NetEntityLookup = new(EntityCapacity); /// /// Clears an old inverse lookup for a particular entityuid. /// Do not call this unless you are sure of what you're doing. /// internal void ClearNetEntity(NetEntity netEntity) { NetEntityLookup.Remove(netEntity); } /// /// Set the inverse lookup for a particular entityuid. /// Do not call this unless you are sure of what you're doing. /// internal void SetNetEntity(EntityUid uid, NetEntity netEntity, MetaDataComponent component) { DebugTools.Assert(component.NetEntity == NetEntity.Invalid || _netMan.IsClient); DebugTools.Assert(!NetEntityLookup.ContainsKey(netEntity)); NetEntityLookup[netEntity] = (uid, component); component.NetEntity = netEntity; } /// public virtual bool IsClientSide(EntityUid uid, MetaDataComponent? metadata = null) { return false; } #region NetEntity /// public bool TryParseNetEntity(string arg, [NotNullWhen(true)] out EntityUid? entity) { if (!NetEntity.TryParse(arg, out var netEntity) || !TryGetEntity(netEntity, out entity)) { entity = null; return false; } return true; } /// public bool TryGetEntity(NetEntity nEntity, [NotNullWhen(true)] out EntityUid? entity) { if (NetEntityLookup.TryGetValue(nEntity, out var went)) { entity = went.Item1; return true; } entity = null; 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) { if (nEntity == null) { entity = null; return false; } return TryGetEntity(nEntity.Value, out entity); } /// public bool TryGetNetEntity(EntityUid uid, [NotNullWhen(true)] out NetEntity? netEntity, MetaDataComponent? metadata = null) { if (uid == EntityUid.Invalid) { netEntity = null; return false; } // TODO NetEntity figure out why this happens // I wanted this to logMissing but it seems to break a loootttt of dodgy stuff on content. if (MetaQuery.Resolve(uid, ref metadata, false)) { netEntity = metadata.NetEntity; return true; } netEntity = NetEntity.Invalid; return false; } /// public bool TryGetNetEntity(EntityUid? uid, [NotNullWhen(true)] out NetEntity? netEntity, MetaDataComponent? metadata = null) { if (uid == null) { netEntity = null; return false; } return TryGetNetEntity(uid.Value, out netEntity, metadata); } /// public virtual EntityUid EnsureEntity(NetEntity nEntity, EntityUid callerEntity) { // On server we don't want to ensure any reserved entities for later or flag for comp state handling // so this is just GetEntity. Client-side code overrides this method. return GetEntity(nEntity); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public EntityUid? EnsureEntity(NetEntity? nEntity, EntityUid callerEntity) { if (nEntity == null) return null; return EnsureEntity(nEntity.Value, callerEntity); } /// public EntityUid GetEntity(NetEntity nEntity) { if (nEntity == NetEntity.Invalid) return EntityUid.Invalid; if (!NetEntityLookup.TryGetValue(nEntity, out var tuple)) return EntityUid.Invalid; return tuple.Item1; } public (EntityUid, MetaDataComponent) GetEntityData(NetEntity nEntity) { return NetEntityLookup[nEntity]; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public EntityUid? GetEntity(NetEntity? nEntity) { if (nEntity == null) return null; return GetEntity(nEntity.Value); } /// public NetEntity GetNetEntity(EntityUid uid, MetaDataComponent? metadata = null) { if (uid == EntityUid.Invalid) return NetEntity.Invalid; if (!MetaQuery.Resolve(uid, ref metadata)) return NetEntity.Invalid; return metadata.NetEntity; } /// public NetEntity? GetNetEntity(EntityUid? uid, MetaDataComponent? metadata = null) { if (uid == null) return null; return GetNetEntity(uid.Value, metadata); } #endregion #region NetCoordinates /// public NetCoordinates GetNetCoordinates(EntityCoordinates coordinates, MetaDataComponent? metadata = null) { return new NetCoordinates(GetNetEntity(coordinates.EntityId, metadata), coordinates.Position); } /// public NetCoordinates? GetNetCoordinates(EntityCoordinates? coordinates, MetaDataComponent? metadata = null) { if (coordinates == null) return null; return new NetCoordinates(GetNetEntity(coordinates.Value.EntityId, metadata), coordinates.Value.Position); } /// public EntityCoordinates GetCoordinates(NetCoordinates coordinates) { return new EntityCoordinates(GetEntity(coordinates.NetEntity), coordinates.Position); } /// public EntityCoordinates? GetCoordinates(NetCoordinates? coordinates) { if (coordinates == null) return null; return new EntityCoordinates(GetEntity(coordinates.Value.NetEntity), coordinates.Value.Position); } /// public virtual EntityCoordinates EnsureCoordinates(NetCoordinates netCoordinates, EntityUid callerEntity) { // See EnsureEntity return GetCoordinates(netCoordinates); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public EntityCoordinates? EnsureCoordinates(NetCoordinates? netCoordinates, EntityUid callerEntity) { if (netCoordinates == null) return null; return EnsureCoordinates(netCoordinates.Value, callerEntity); } #endregion #region Collection helpers /// public HashSet GetEntitySet(HashSet netEntities) { var entities = new HashSet(netEntities.Count); foreach (var netEntity in netEntities) { entities.Add(GetEntity(netEntity)); } return entities; } /// public List GetEntityList(List netEntities) { var entities = new List(netEntities.Count); foreach (var netEntity in netEntities) { entities.Add(GetEntity(netEntity)); } return entities; } public Dictionary GetEntityDictionary(Dictionary netEntities) { var entities = new Dictionary(netEntities.Count); foreach (var pair in netEntities) { entities.Add(GetEntity(pair.Key), pair.Value); } return entities; } public Dictionary GetEntityDictionary(Dictionary netEntities) where T : notnull { var entities = new Dictionary(netEntities.Count); foreach (var pair in netEntities) { entities.Add(pair.Key, GetEntity(pair.Value)); } return entities; } public Dictionary GetEntityDictionary(Dictionary netEntities) where T : notnull { var entities = new Dictionary(netEntities.Count); foreach (var pair in netEntities) { entities.Add(pair.Key, GetEntity(pair.Value)); } return entities; } public Dictionary GetEntityDictionary(Dictionary netEntities) { var entities = new Dictionary(netEntities.Count); foreach (var pair in netEntities) { entities.Add(GetEntity(pair.Key), GetEntity(pair.Value)); } return entities; } public Dictionary GetEntityDictionary(Dictionary netEntities) { var entities = new Dictionary(netEntities.Count); foreach (var pair in netEntities) { entities.Add(GetEntity(pair.Key), GetEntity(pair.Value)); } return entities; } public HashSet EnsureEntitySet(HashSet netEntities, EntityUid callerEntity) { var entities = new HashSet(netEntities.Count); foreach (var netEntity in netEntities) { entities.Add(EnsureEntity(netEntity, callerEntity)); } return entities; } public void EnsureEntitySet(HashSet netEntities, EntityUid callerEntity, HashSet entities) { entities.Clear(); entities.EnsureCapacity(netEntities.Count); foreach (var netEntity in netEntities) { entities.Add(EnsureEntity(netEntity, callerEntity)); } } /// public List EnsureEntityList(List netEntities, EntityUid callerEntity) { var entities = new List(netEntities.Count); foreach (var netEntity in netEntities) { entities.Add(EnsureEntity(netEntity, callerEntity)); } return entities; } public void EnsureEntityList(List netEntities, EntityUid callerEntity, List entities) { entities.Clear(); entities.EnsureCapacity(netEntities.Count); foreach (var netEntity in netEntities) { entities.Add(EnsureEntity(netEntity, callerEntity)); } } public void EnsureEntityDictionary(Dictionary netEntities, EntityUid callerEntity, Dictionary entities) { entities.Clear(); entities.EnsureCapacity(netEntities.Count); foreach (var pair in netEntities) { entities.TryAdd(EnsureEntity(pair.Key, callerEntity), pair.Value); } } public void EnsureEntityDictionaryNullableValue(Dictionary netEntities, EntityUid callerEntity, Dictionary entities) { entities.Clear(); entities.EnsureCapacity(netEntities.Count); foreach (var pair in netEntities) { entities.TryAdd(EnsureEntity(pair.Key, callerEntity), pair.Value); } } public void EnsureEntityDictionary(Dictionary netEntities, EntityUid callerEntity, Dictionary entities) where TKey : notnull { entities.Clear(); entities.EnsureCapacity(netEntities.Count); foreach (var pair in netEntities) { entities.TryAdd(pair.Key, EnsureEntity(pair.Value, callerEntity)); } } public void EnsureEntityDictionary(Dictionary netEntities, EntityUid callerEntity, Dictionary entities) where TKey : notnull { entities.Clear(); entities.EnsureCapacity(netEntities.Count); foreach (var pair in netEntities) { entities.TryAdd(pair.Key, EnsureEntity(pair.Value, callerEntity)); } } public void EnsureEntityDictionary(Dictionary netEntities, EntityUid callerEntity, Dictionary entities) { entities.Clear(); entities.EnsureCapacity(netEntities.Count); foreach (var pair in netEntities) { entities.TryAdd(EnsureEntity(pair.Key, callerEntity), EnsureEntity(pair.Value, callerEntity)); } } public void EnsureEntityDictionary(Dictionary netEntities, EntityUid callerEntity, Dictionary entities) { entities.Clear(); entities.EnsureCapacity(netEntities.Count); foreach (var pair in netEntities) { entities.TryAdd(EnsureEntity(pair.Key, callerEntity), EnsureEntity(pair.Value, callerEntity)); } } /// public List GetEntityList(ICollection netEntities) { var entities = new List(netEntities.Count); foreach (var netEntity in netEntities) { entities.Add(GetEntity(netEntity)); } return entities; } /// public List GetEntityList(List netEntities) { var entities = new List(netEntities.Count); foreach (var netEntity in netEntities) { entities.Add(GetEntity(netEntity)); } return entities; } /// public EntityUid[] GetEntityArray(NetEntity[] netEntities) { var entities = new EntityUid[netEntities.Length]; for (var i = 0; i < netEntities.Length; i++) { entities[i] = GetEntity(netEntities[i]); } return entities; } /// public EntityUid?[] GetEntityArray(NetEntity?[] netEntities) { var entities = new EntityUid?[netEntities.Length]; for (var i = 0; i < netEntities.Length; i++) { entities[i] = GetEntity(netEntities[i]); } return entities; } /// public HashSet GetNetEntitySet(HashSet entities) { var newSet = new HashSet(entities.Count); foreach (var ent in entities) { MetaQuery.TryGetComponent(ent, out var metadata); newSet.Add(GetNetEntity(ent, metadata)); } return newSet; } /// public List GetNetEntityList(List entities) { var netEntities = new List(entities.Count); foreach (var netEntity in entities) { netEntities.Add(GetNetEntity(netEntity)); } return netEntities; } /// public List GetNetEntityList(IReadOnlyList entities) { var netEntities = new List(entities.Count); foreach (var netEntity in entities) { netEntities.Add(GetNetEntity(netEntity)); } return netEntities; } /// public List GetNetEntityList(ICollection entities) { var netEntities = new List(entities.Count); foreach (var netEntity in entities) { netEntities.Add(GetNetEntity(netEntity)); } return netEntities; } /// public List GetNetEntityList(List entities) { var netEntities = new List(entities.Count); foreach (var netEntity in entities) { netEntities.Add(GetNetEntity(netEntity)); } return netEntities; } /// public NetEntity[] GetNetEntityArray(EntityUid[] entities) { var netEntities = new NetEntity[entities.Length]; for (var i = 0; i < entities.Length; i++) { netEntities[i] = GetNetEntity(entities[i]); } return netEntities; } /// public NetEntity?[] GetNetEntityArray(EntityUid?[] entities) { var netEntities = new NetEntity?[entities.Length]; for (var i = 0; i < entities.Length; i++) { netEntities[i] = GetNetEntity(entities[i]); } return netEntities; } /// public Dictionary GetNetEntityDictionary(Dictionary entities) { var netEntities = new Dictionary(entities.Count); foreach (var pair in entities) { netEntities.Add(GetNetEntity(pair.Key), pair.Value); } return netEntities; } /// public Dictionary GetNetEntityDictionary(Dictionary entities) where T : notnull { var netEntities = new Dictionary(entities.Count); foreach (var pair in entities) { netEntities.Add(pair.Key, GetNetEntity(pair.Value)); } return netEntities; } /// public Dictionary GetNetEntityDictionary(Dictionary entities) where T : notnull { var netEntities = new Dictionary(entities.Count); foreach (var pair in entities) { netEntities.Add(pair.Key, GetNetEntity(pair.Value)); } return netEntities; } /// public Dictionary GetNetEntityDictionary(Dictionary entities) { var netEntities = new Dictionary(entities.Count); foreach (var pair in entities) { netEntities.Add(GetNetEntity(pair.Key), GetNetEntity(pair.Value)); } return netEntities; } /// public Dictionary GetNetEntityDictionary(Dictionary entities) { var netEntities = new Dictionary(entities.Count); foreach (var pair in entities) { netEntities.Add(GetNetEntity(pair.Key), GetNetEntity(pair.Value)); } return netEntities; } /// public HashSet GetEntitySet(HashSet netEntities) { var entities = new HashSet(netEntities.Count); foreach (var netCoordinates in netEntities) { entities.Add(GetCoordinates(netCoordinates)); } return entities; } /// public List GetEntityList(List netEntities) { var entities = new List(netEntities.Count); foreach (var netCoordinates in netEntities) { entities.Add(GetCoordinates(netCoordinates)); } return entities; } /// public List GetEntityList(ICollection netEntities) { var entities = new List(netEntities.Count); foreach (var netCoordinates in netEntities) { entities.Add(GetCoordinates(netCoordinates)); } return entities; } /// public List GetEntityList(List netEntities) { var entities = new List(netEntities.Count); foreach (var netCoordinates in netEntities) { entities.Add(GetCoordinates(netCoordinates)); } return entities; } /// public EntityCoordinates[] GetEntityArray(NetCoordinates[] netEntities) { var entities = new EntityCoordinates[netEntities.Length]; for (var i = 0; i < netEntities.Length; i++) { entities[i] = GetCoordinates(netEntities[i]); } return entities; } /// public EntityCoordinates?[] GetEntityArray(NetCoordinates?[] netEntities) { var entities = new EntityCoordinates?[netEntities.Length]; for (var i = 0; i < netEntities.Length; i++) { entities[i] = GetCoordinates(netEntities[i]); } return entities; } /// public HashSet GetNetCoordinatesSet(HashSet entities) { var newSet = new HashSet(entities.Count); foreach (var coordinates in entities) { newSet.Add(GetNetCoordinates(coordinates)); } return newSet; } /// public List GetNetCoordinatesList(List entities) { var netEntities = new List(entities.Count); foreach (var netCoordinates in entities) { netEntities.Add(GetNetCoordinates(netCoordinates)); } return netEntities; } /// public List GetNetCoordinatesList(ICollection entities) { var netEntities = new List(entities.Count); foreach (var netCoordinates in entities) { netEntities.Add(GetNetCoordinates(netCoordinates)); } return netEntities; } /// public List GetNetCoordinatesList(List entities) { var netEntities = new List(entities.Count); foreach (var netCoordinates in entities) { netEntities.Add(GetNetCoordinates(netCoordinates)); } return netEntities; } /// public NetCoordinates[] GetNetCoordinatesArray(EntityCoordinates[] entities) { var netEntities = new NetCoordinates[entities.Length]; for (var i = 0; i < entities.Length; i++) { netEntities[i] = GetNetCoordinates(entities[i]); } return netEntities; } /// public NetCoordinates?[] GetNetCoordinatesArray(EntityCoordinates?[] entities) { var netEntities = new NetCoordinates?[entities.Length]; for (var i = 0; i < entities.Length; i++) { netEntities[i] = GetNetCoordinates(entities[i]); } return netEntities; } #endregion }