using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Robust.Shared.GameObjects; using Robust.Shared.GameStates; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; namespace Robust.Shared.Containers; /// /// Holds data about a set of entity containers on this entity. /// [NetworkedComponent] [RegisterComponent, ComponentProtoName("ContainerContainer")] public sealed partial class ContainerManagerComponent : Component, ISerializationHooks { /// /// Dictionary containing the containers on this entity. /// The key is used as an identifier and can be freely chosen when a new container is added with . /// [DataField] public Dictionary Containers = new(); // Requires a custom serializer + copier to get rid of. Good luck void ISerializationHooks.AfterDeserialization() { foreach (var (id, container) in Containers) { container.Init(default!, id, (Owner, this)); } } [Serializable, NetSerializable] internal sealed class ContainerManagerComponentState : ComponentState { public Dictionary Containers; public ContainerManagerComponentState(Dictionary containers) { Containers = containers; } [Serializable, NetSerializable] public readonly struct ContainerData { public readonly string ContainerType; // TODO remove this. We dont have to send a whole string. public readonly bool ShowContents; public readonly bool OccludesLight; public readonly NetEntity[] ContainedEntities; public ContainerData(string containerType, bool showContents, bool occludesLight, NetEntity[] containedEntities) { ContainerType = containerType; ShowContents = showContents; OccludesLight = occludesLight; ContainedEntities = containedEntities; } public void Deconstruct(out string type, out bool showEnts, out bool occludesLight, out NetEntity[] ents) { type = ContainerType; showEnts = ShowContents; occludesLight = OccludesLight; ents = ContainedEntities; } } } public readonly struct AllContainersEnumerable : IEnumerable { private readonly ContainerManagerComponent? _manager; public AllContainersEnumerable(ContainerManagerComponent? manager) { _manager = manager; } public AllContainersEnumerator GetEnumerator() { return new(_manager); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct AllContainersEnumerator : IEnumerator { private Dictionary.ValueCollection.Enumerator _enumerator; public AllContainersEnumerator(ContainerManagerComponent? manager) { _enumerator = manager?.Containers.Values.GetEnumerator() ?? new(); Current = default; } public bool MoveNext() { while (_enumerator.MoveNext()) { Current = _enumerator.Current; return true; } return false; } void IEnumerator.Reset() { ((IEnumerator) _enumerator).Reset(); } [AllowNull] public BaseContainer Current { get; private set; } object IEnumerator.Current => Current; public void Dispose() { } } }