private void AddUtilityVerbs(EntityUid uid, DumpableComponent dumpable, GetVerbsEvent <UtilityVerb> args)
        {
            if (!args.CanAccess || !args.CanInteract)
            {
                return;
            }

            if (!TryComp <ServerStorageComponent>(uid, out var storage) || storage.StoredEntities == null || storage.StoredEntities.Count == 0)
            {
                return;
            }

            if (HasComp <DisposalUnitComponent>(args.Target))
            {
                UtilityVerb verb = new()
                {
                    Act = () =>
                    {
                        StartDoAfter(uid, args.Target, args.User, dumpable, storage);
                    },
                    Text       = Loc.GetString("dump-disposal-verb-name", ("unit", args.Target)),
                    IconEntity = uid
                };
                args.Verbs.Add(verb);
            }

            if (HasComp <PlaceableSurfaceComponent>(args.Target))
            {
                UtilityVerb verb = new()
                {
                    Act = () =>
                    {
                        StartDoAfter(uid, args.Target, args.User, dumpable, storage);
                    },
                    Text       = Loc.GetString("dump-placeable-verb-name", ("surface", args.Target)),
                    IconEntity = uid
                };
                args.Verbs.Add(verb);
            }
        }
        private void OnAfterInteract(EntityUid uid, DumpableComponent component, AfterInteractEvent args)
        {
            if (!args.CanReach)
            {
                return;
            }

            if (!TryComp <ServerStorageComponent>(args.Used, out var storage))
            {
                return;
            }

            if (storage.StoredEntities == null || storage.StoredEntities.Count == 0)
            {
                return;
            }

            if (HasComp <DisposalUnitComponent>(args.Target) || HasComp <PlaceableSurfaceComponent>(args.Target))
            {
                StartDoAfter(uid, args.Target.Value, args.User, component, storage);
                return;
            }
        }
        private void AddDumpVerb(EntityUid uid, DumpableComponent dumpable, GetVerbsEvent <AlternativeVerb> args)
        {
            if (!args.CanAccess || !args.CanInteract)
            {
                return;
            }

            if (!TryComp <ServerStorageComponent>(uid, out var storage) || storage.StoredEntities == null || storage.StoredEntities.Count == 0)
            {
                return;
            }

            AlternativeVerb verb = new()
            {
                Act = () =>
                {
                    StartDoAfter(uid, null, args.User, dumpable, storage, 0.6f);
                },
                Text        = Loc.GetString("dump-verb-name"),
                IconTexture = "/Textures/Interface/VerbIcons/drop.svg.192dpi.png",
            };

            args.Verbs.Add(verb);
        }
        private void StartDoAfter(EntityUid storageUid, EntityUid?targetUid, EntityUid userUid, DumpableComponent dumpable, ServerStorageComponent storage, float multiplier = 1)
        {
            if (dumpable.CancelToken != null)
            {
                dumpable.CancelToken.Cancel();
                dumpable.CancelToken = null;
                return;
            }

            if (storage.StoredEntities == null)
            {
                return;
            }

            float delay = storage.StoredEntities.Count * (float)dumpable.DelayPerItem.TotalSeconds * multiplier;

            dumpable.CancelToken = new CancellationTokenSource();
            _doAfterSystem.DoAfter(new DoAfterEventArgs(userUid, delay, dumpable.CancelToken.Token, target: targetUid)
            {
                BroadcastFinishedEvent  = new DumpCompletedEvent(userUid, targetUid, storage.StoredEntities),
                BroadcastCancelledEvent = new DumpCancelledEvent(dumpable.Owner),
                BreakOnTargetMove       = true,
                BreakOnUserMove         = true,
                BreakOnStun             = true,
                NeedHand = true
            });
        }