using System.Diagnostics.CodeAnalysis; using Content.Shared.Chemistry.Components; using Content.Shared.Inventory; using Content.Shared.Whitelist; using Robust.Shared.Containers; namespace Content.Shared.Containers; /// /// System for getting container that is linked to subject entity. Container is supposed to be present in certain character slot. /// Can be used for linking ammo feeder, solution source for spray nozzle, etc. /// public sealed class SlotBasedConnectedContainerSystem : EntitySystem { [Dependency] private readonly SharedContainerSystem _containers = default!; [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; [Dependency] private readonly InventorySystem _inventory = default!; /// public override void Initialize() { SubscribeLocalEvent(OnGettingConnectedContainer); } /// /// Try get connected container entity in character slots for . /// /// /// Entity for which connected container is required. If /// is used - tries to find container in slot, returns false and null otherwise. /// /// Found connected container entity or null. /// True if connected container was found, false otherwise. public bool TryGetConnectedContainer(EntityUid uid, [NotNullWhen(true)] out EntityUid? slotEntity) { if (!TryComp(uid, out var component)) { slotEntity = null; return false; } return TryGetConnectedContainer(uid, component.TargetSlot, component.ContainerWhitelist, out slotEntity); } private void OnGettingConnectedContainer(Entity ent, ref GetConnectedContainerEvent args) { if (TryGetConnectedContainer(ent, ent.Comp.TargetSlot, ent.Comp.ContainerWhitelist, out var val)) args.ContainerEntity = val; } private bool TryGetConnectedContainer(EntityUid uid, SlotFlags slotFlag, EntityWhitelist? providerWhitelist, [NotNullWhen(true)] out EntityUid? slotEntity) { slotEntity = null; if (!_containers.TryGetContainingContainer((uid, null, null), out var container)) return false; var user = container.Owner; if (!_inventory.TryGetContainerSlotEnumerator(user, out var enumerator, slotFlag)) return false; while (enumerator.NextItem(out var item)) { if (_whitelistSystem.IsWhitelistFailOrNull(providerWhitelist, item)) continue; slotEntity = item; return true; } return false; } } /// /// Event for an attempt of getting container, connected to entity on which event was raised. /// Fills if connected container exists. /// [ByRefEvent] public struct GetConnectedContainerEvent { /// /// Container entity, if it exists, or null. /// public EntityUid? ContainerEntity; }