Example #1
0
        /// <summary>
        /// Inserts storable entities into this storage container if possible, otherwise return to the hand of the user
        /// </summary>
        /// <returns>true if inserted, false otherwise</returns>
        private void OnInteractUsing(EntityUid uid, ServerStorageComponent storageComp, InteractUsingEvent args)
        {
            if (args.Handled)
            {
                return;
            }

            if (!storageComp.ClickInsert)
            {
                return;
            }

            if (TryComp(uid, out LockComponent? lockComponent) && lockComponent.Locked)
            {
                return;
            }

            Logger.DebugS(storageComp.LoggerName, $"Storage (UID {uid}) attacked by user (UID {args.User}) with entity (UID {args.Used}).");

            if (HasComp <PlaceableSurfaceComponent>(uid))
            {
                return;
            }

            if (PlayerInsertHeldEntity(uid, args.User, storageComp))
            {
                args.Handled = true;
            }
        }
Example #2
0
        private void AddTransferVerbs(EntityUid uid, ServerStorageComponent component, GetVerbsEvent <UtilityVerb> args)
        {
            if (!args.CanAccess || !args.CanInteract)
            {
                return;
            }

            var entities = component.Storage?.ContainedEntities;

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

            if (TryComp(uid, out LockComponent? lockComponent) && lockComponent.Locked)
            {
                return;
            }

            // if the target is storage, add a verb to transfer storage.
            if (TryComp(args.Target, out ServerStorageComponent? targetStorage) &&
                (!TryComp(uid, out LockComponent? targetLock) || !targetLock.Locked))
            {
                UtilityVerb verb = new()
                {
                    Text       = Loc.GetString("storage-component-transfer-verb"),
                    IconEntity = args.Using,
                    Act        = () => TransferEntities(uid, args.Target, component, lockComponent, targetStorage, targetLock)
                };

                args.Verbs.Add(verb);
            }
        }
Example #3
0
 private void OnBoundUIOpen(EntityUid uid, ServerStorageComponent storageComp, BoundUIOpenedEvent args)
 {
     if (!storageComp.IsOpen)
     {
         storageComp.IsOpen = true;
         UpdateStorageVisualization(uid, storageComp);
     }
 }
Example #4
0
        private void Popup(EntityUid uid, EntityUid player, string message, ServerStorageComponent storageComp)
        {
            if (!storageComp.ShowPopup)
            {
                return;
            }

            _popupSystem.PopupEntity(Loc.GetString(message), player, Filter.Entities(player));
        }
Example #5
0
        private void OnInsertItemMessage(EntityUid uid, ServerStorageComponent storageComp, StorageInsertItemMessage args)
        {
            // TODO move this to shared for prediction.
            if (args.Session.AttachedEntity == null)
            {
                return;
            }

            PlayerInsertHeldEntity(uid, args.Session.AttachedEntity.Value, storageComp);
        }
Example #6
0
        private void OnComponentInit(EntityUid uid, ServerStorageComponent storageComp, ComponentInit args)
        {
            base.Initialize();

            // ReSharper disable once StringLiteralTypo
            storageComp.Storage = _containerSystem.EnsureContainer <Container>(uid, "storagebase");
            storageComp.Storage.OccludesLight = storageComp.OccludesLight;
            UpdateStorageVisualization(uid, storageComp);
            RecalculateStorageUsed(storageComp);
            UpdateStorageUI(uid, storageComp);
        }
Example #7
0
        private void UpdateStorageUI(EntityUid uid, ServerStorageComponent storageComp)
        {
            if (storageComp.Storage == null)
            {
                return;
            }

            var state = new StorageBoundUserInterfaceState((List <EntityUid>)storageComp.Storage.ContainedEntities, storageComp.StorageUsed, storageComp.StorageCapacityMax);

            _uiSystem.GetUiOrNull(uid, StorageUiKey.Key)?.SetState(state);
        }
Example #8
0
 public override void Initialize()
 {
     base.Initialize();
     Contents = ContainerManagerComponent.Ensure <Container>($"{typeof(EntityStorageComponent).FullName}{Owner.Uid.ToString()}", Owner);
     if (!Owner.TryGetComponent(out StorageComponent))
     {
         StorageComponent = Owner.AddComponent <ServerStorageComponent>();
         // TODO: This is a terrible hack.
         // Components should not need to be manually initialized in Initialize().
         StorageComponent.Initialize();
     }
     entityQuery = new IntersectingEntityQuery(Owner);
 }
Example #9
0
        private void OnDestroy(EntityUid uid, ServerStorageComponent storageComp, DestructionEventArgs args)
        {
            var storedEntities = storageComp.StoredEntities?.ToList();

            if (storedEntities == null)
            {
                return;
            }

            foreach (var entity in storedEntities)
            {
                RemoveAndDrop(uid, entity, storageComp);
            }
        }
Example #10
0
        /// <summary>
        /// Sends a message to open the storage UI
        /// </summary>
        /// <returns></returns>
        private void OnActivate(EntityUid uid, ServerStorageComponent storageComp, ActivateInWorldEvent args)
        {
            if (!TryComp <ActorComponent>(args.User, out var actor))
            {
                return;
            }

            if (TryComp(uid, out LockComponent? lockComponent) && lockComponent.Locked)
            {
                return;
            }

            OpenStorageUI(uid, args.User, storageComp);
        }
Example #11
0
        private void UpdateStorageVisualization(EntityUid uid, ServerStorageComponent storageComp)
        {
            if (!TryComp <AppearanceComponent>(uid, out var appearance))
            {
                return;
            }

            appearance.SetData(StorageVisuals.Open, storageComp.IsOpen);
            appearance.SetData(SharedBagOpenVisuals.BagState, storageComp.IsOpen ? SharedBagState.Open : SharedBagState.Closed);

            if (HasComp <ItemCounterComponent>(uid))
            {
                appearance.SetData(StackVisuals.Hide, !storageComp.IsOpen);
            }
        }
Example #12
0
        private void OnBoundUIClosed(EntityUid uid, ServerStorageComponent storageComp, BoundUIClosedEvent args)
        {
            if (TryComp <ActorComponent>(args.Session.AttachedEntity, out var actor) && actor?.PlayerSession != null)
            {
                CloseNestedInterfaces(uid, actor.PlayerSession, storageComp);
            }

            // If UI is closed for everyone
            if (!_uiSystem.IsUiOpen(uid, args.UiKey))
            {
                storageComp.IsOpen = false;
                UpdateStorageVisualization(uid, storageComp);

                if (storageComp.StorageCloseSound is not null)
                {
                    SoundSystem.Play(storageComp.StorageCloseSound.GetSound(), Filter.Pvs(uid, entityManager: EntityManager), uid, storageComp.StorageCloseSound.Params);
                }
            }
        }
Example #13
0
        /// <summary>
        ///     This function gets called when the user clicked on an item in the storage UI. This will either place the
        ///     item in the user's hand if it is currently empty, or interact with the item using the user's currently
        ///     held item.
        /// </summary>
        private void OnInteractWithItem(EntityUid uid, ServerStorageComponent storageComp, StorageInteractWithItemEvent args)
        {
            // TODO move this to shared for prediction.
            if (args.Session.AttachedEntity is not EntityUid player)
            {
                return;
            }

            if (!_actionBlockerSystem.CanInteract(player, args.InteractedItemUID))
            {
                return;
            }

            if (storageComp.Storage == null || !storageComp.Storage.Contains(args.InteractedItemUID))
            {
                return;
            }

            // Does the player have hands?
            if (!TryComp(player, out HandsComponent? hands) || hands.Count == 0)
            {
                return;
            }

            // If the user's active hand is empty, try pick up the item.
            if (hands.ActiveHandEntity == null)
            {
                if (_sharedHandsSystem.TryPickupAnyHand(player, args.InteractedItemUID, handsComp: hands) &&
                    storageComp.StorageRemoveSound != null)
                {
                    SoundSystem.Play(storageComp.StorageRemoveSound.GetSound(), Filter.Pvs(uid, entityManager: EntityManager), uid, AudioParams.Default);
                }
                return;
            }

            // Else, interact using the held item
            _interactionSystem.InteractUsing(player, hands.ActiveHandEntity.Value, args.InteractedItemUID, Transform(args.InteractedItemUID).Coordinates, checkCanInteract: false);
        }
Example #14
0
        private void RecalculateStorageUsed(ServerStorageComponent storageComp)
        {
            storageComp.StorageUsed = 0;
            storageComp.SizeCache.Clear();

            if (storageComp.Storage == null)
            {
                return;
            }

            var itemQuery = GetEntityQuery <ItemComponent>();

            foreach (var entity in storageComp.Storage.ContainedEntities)
            {
                if (!itemQuery.TryGetComponent(entity, out var itemComp))
                {
                    continue;
                }

                storageComp.StorageUsed += itemComp.Size;
                storageComp.SizeCache.Add(entity, itemComp.Size);
            }
        }
        private void CheckSubscribedEntities(ServerStorageComponent storageComp)
        {
            // We have to cache the set of sessions because Unsubscribe modifies the original.
            _sessionCache.Clear();
            _sessionCache.AddRange(storageComp.SubscribedSessions);

            if (_sessionCache.Count == 0)
            {
                return;
            }

            var storagePos = storageComp.Owner.Transform.WorldPosition;
            var storageMap = storageComp.Owner.Transform.MapID;

            foreach (var session in _sessionCache)
            {
                var attachedEntity = session.AttachedEntity;

                // The component manages the set of sessions, so this invalid session should be removed soon.
                if (attachedEntity == null || !attachedEntity.IsValid())
                {
                    continue;
                }

                if (storageMap != attachedEntity.Transform.MapID)
                {
                    continue;
                }

                var distanceSquared = (storagePos - attachedEntity.Transform.WorldPosition).LengthSquared;
                if (distanceSquared > InteractionSystem.InteractionRangeSquared)
                {
                    storageComp.UnsubscribeSession(session);
                }
            }
        }
Example #16
0
        private void AddOpenUiVerb(EntityUid uid, ServerStorageComponent component, GetVerbsEvent <ActivationVerb> args)
        {
            if (!args.CanAccess || !args.CanInteract)
            {
                return;
            }

            if (TryComp <LockComponent>(uid, out var lockComponent) && lockComponent.Locked)
            {
                return;
            }

            // Get the session for the user
            if (!TryComp <ActorComponent>(args.User, out var actor) || actor?.PlayerSession == null)
            {
                return;
            }

            // Does this player currently have the storage UI open?
            bool uiOpen = _uiSystem.SessionHasOpenUi(uid, StorageUiKey.Key, actor.PlayerSession);

            ActivationVerb verb = new();

            verb.Act = () => OpenStorageUI(uid, args.User, component);
            if (uiOpen)
            {
                verb.Text        = Loc.GetString("verb-common-close-ui");
                verb.IconTexture = "/Textures/Interface/VerbIcons/close.svg.192dpi.png";
            }
            else
            {
                verb.Text        = Loc.GetString("verb-common-open-ui");
                verb.IconTexture = "/Textures/Interface/VerbIcons/open.svg.192dpi.png";
            }
            args.Verbs.Add(verb);
        }
Example #17
0
        /// <summary>
        /// Allows a user to pick up entities by clicking them, or pick up all entities in a certain radius
        /// around a click.
        /// </summary>
        /// <returns></returns>
        private async void AfterInteract(EntityUid uid, ServerStorageComponent storageComp, AfterInteractEvent eventArgs)
        {
            if (!eventArgs.CanReach)
            {
                return;
            }

            if (storageComp.CancelToken != null)
            {
                storageComp.CancelToken.Cancel();
                storageComp.CancelToken = null;
                return;
            }

            // Pick up all entities in a radius around the clicked location.
            // The last half of the if is because carpets exist and this is terrible
            if (storageComp.AreaInsert && (eventArgs.Target == null || !HasComp <ItemComponent>(eventArgs.Target.Value)))
            {
                var validStorables = new List <EntityUid>();
                foreach (var entity in _entityLookupSystem.GetEntitiesInRange(eventArgs.ClickLocation, storageComp.AreaInsertRadius, LookupFlags.None))
                {
                    if (entity == eventArgs.User ||
                        !HasComp <ItemComponent>(entity) ||
                        !_interactionSystem.InRangeUnobstructed(eventArgs.User, entity))
                    {
                        continue;
                    }

                    validStorables.Add(entity);
                }

                //If there's only one then let's be generous
                if (validStorables.Count > 1)
                {
                    storageComp.CancelToken = new CancellationTokenSource();
                    var doAfterArgs = new DoAfterEventArgs(eventArgs.User, 0.2f * validStorables.Count, storageComp.CancelToken.Token, uid)
                    {
                        BreakOnStun     = true,
                        BreakOnDamage   = true,
                        BreakOnUserMove = true,
                        NeedHand        = true,
                    };

                    await _doAfterSystem.WaitDoAfter(doAfterArgs);
                }

                // TODO: Make it use the event DoAfter
                var successfullyInserted          = new List <EntityUid>();
                var successfullyInsertedPositions = new List <EntityCoordinates>();
                foreach (var entity in validStorables)
                {
                    // Check again, situation may have changed for some entities, but we'll still pick up any that are valid
                    if (_containerSystem.IsEntityInContainer(entity) ||
                        entity == eventArgs.User ||
                        !HasComp <ItemComponent>(entity))
                    {
                        continue;
                    }

                    if (TryComp <TransformComponent>(uid, out var transformOwner) && TryComp <TransformComponent>(entity, out var transformEnt))
                    {
                        var position = EntityCoordinates.FromMap(transformOwner.Parent?.Owner ?? uid, transformEnt.MapPosition);

                        if (PlayerInsertEntityInWorld(uid, eventArgs.User, entity, storageComp))
                        {
                            successfullyInserted.Add(entity);
                            successfullyInsertedPositions.Add(position);
                        }
                    }
                }

                // If we picked up atleast one thing, play a sound and do a cool animation!
                if (successfullyInserted.Count > 0)
                {
                    if (storageComp.StorageInsertSound is not null)
                    {
                        SoundSystem.Play(storageComp.StorageInsertSound.GetSound(), Filter.Pvs(uid, entityManager: EntityManager), uid, AudioParams.Default);
                    }
                    RaiseNetworkEvent(new AnimateInsertingEntitiesEvent(uid, successfullyInserted, successfullyInsertedPositions));
                }
                return;
            }
            // Pick up the clicked entity
            else if (storageComp.QuickInsert)
            {
                if (eventArgs.Target is not {
                    Valid : true
                } target)
                {
                    return;
                }

                if (_containerSystem.IsEntityInContainer(target) ||
                    target == eventArgs.User ||
                    !HasComp <ItemComponent>(target))
                {
                    return;
                }

                if (TryComp <TransformComponent>(uid, out var transformOwner) && TryComp <TransformComponent>(target, out var transformEnt))
                {
                    var parent = transformOwner.ParentUid;

                    var position = EntityCoordinates.FromMap(
                        parent.IsValid() ? parent : uid,
                        transformEnt.MapPosition);
                    if (PlayerInsertEntityInWorld(uid, eventArgs.User, target, storageComp))
                    {
                        RaiseNetworkEvent(new AnimateInsertingEntitiesEvent(uid,
                                                                            new List <EntityUid> {
                            target
                        },
                                                                            new List <EntityCoordinates> {
                            position
                        }));
                    }
                }
            }
            return;
        }
Example #18
0
 private void OnStorageItemRemoved(EntityUid uid, ServerStorageComponent storageComp, EntRemovedFromContainerMessage args)
 {
     RecalculateStorageUsed(storageComp);
     UpdateStorageUI(uid, storageComp);
 }
        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
            });
        }