using Content.Shared.Access.Components; using Content.Shared.Access.Systems; using Content.Shared.Hands.EntitySystems; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Popups; using Content.Shared.Storage.Components; using Content.Shared.Whitelist; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.Timing; namespace Content.Shared.SmartFridge; public sealed class SmartFridgeSystem : EntitySystem { [Dependency] private readonly AccessReaderSystem _accessReader = default!; [Dependency] private readonly EntityWhitelistSystem _whitelist = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly SharedHandsSystem _hands = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnInteractUsing); SubscribeLocalEvent(OnItemRemoved); SubscribeLocalEvent(OnGetDumpableVerb); SubscribeLocalEvent(OnDump); Subs.BuiEvents(SmartFridgeUiKey.Key, sub => { sub.Event(OnDispenseItem); }); } private bool DoInsert(Entity ent, EntityUid user, IEnumerable usedItems, bool playSound) { if (!_container.TryGetContainer(ent, ent.Comp.Container, out var container)) return false; if (!Allowed(ent, user)) return true; bool anyInserted = false; foreach (var used in usedItems) { if (!_whitelist.CheckBoth(used, ent.Comp.Blacklist, ent.Comp.Whitelist)) continue; anyInserted = true; _container.Insert(used, container); var key = new SmartFridgeEntry(Identity.Name(used, EntityManager)); if (!ent.Comp.Entries.Contains(key)) ent.Comp.Entries.Add(key); ent.Comp.ContainedEntries.TryAdd(key, new()); var entries = ent.Comp.ContainedEntries[key]; if (!entries.Contains(GetNetEntity(used))) entries.Add(GetNetEntity(used)); Dirty(ent); } if (anyInserted && playSound) { _audio.PlayPredicted(ent.Comp.InsertSound, ent, user); } return anyInserted; } private void OnInteractUsing(Entity ent, ref InteractUsingEvent args) { if (!_hands.CanDrop(args.User, args.Used)) return; args.Handled = DoInsert(ent, args.User, [args.Used], true); } private void OnItemRemoved(Entity ent, ref EntRemovedFromContainerMessage args) { var key = new SmartFridgeEntry(Identity.Name(args.Entity, EntityManager)); if (ent.Comp.ContainedEntries.TryGetValue(key, out var contained)) { contained.Remove(GetNetEntity(args.Entity)); } Dirty(ent); } private bool Allowed(Entity machine, EntityUid user) { if (_accessReader.IsAllowed(user, machine)) return true; _popup.PopupPredicted(Loc.GetString("smart-fridge-component-try-eject-access-denied"), machine, user); _audio.PlayPredicted(machine.Comp.SoundDeny, machine, user); return false; } private void OnDispenseItem(Entity ent, ref SmartFridgeDispenseItemMessage args) { if (!_timing.IsFirstTimePredicted) return; if (!Allowed(ent, args.Actor)) return; if (!ent.Comp.ContainedEntries.TryGetValue(args.Entry, out var contained)) { _audio.PlayPredicted(ent.Comp.SoundDeny, ent, args.Actor); _popup.PopupPredicted(Loc.GetString("smart-fridge-component-try-eject-unknown-entry"), ent, args.Actor); return; } foreach (var item in contained) { if (!_container.TryRemoveFromContainer(GetEntity(item))) continue; _audio.PlayPredicted(ent.Comp.SoundVend, ent, args.Actor); contained.Remove(item); Dirty(ent); return; } _audio.PlayPredicted(ent.Comp.SoundDeny, ent, args.Actor); _popup.PopupPredicted(Loc.GetString("smart-fridge-component-try-eject-out-of-stock"), ent, args.Actor); } private void OnGetDumpableVerb(Entity ent, ref GetDumpableVerbEvent args) { if (_accessReader.IsAllowed(args.User, ent)) { args.Verb = Loc.GetString("dump-smartfridge-verb-name", ("unit", ent)); } } private void OnDump(Entity ent, ref DumpEvent args) { if (args.Handled) return; args.Handled = true; args.PlaySound = true; DoInsert(ent, args.User, args.DumpQueue, false); } }