Esempio n. 1
0
 /// <summary>
 ///     Ensure item slots have containers.
 /// </summary>
 private void Oninitialize(EntityUid uid, ItemSlotsComponent itemSlots, ComponentInit args)
 {
     foreach (var(id, slot) in itemSlots.Slots)
     {
         slot.ContainerSlot = ContainerHelpers.EnsureContainer <ContainerSlot>(itemSlots.Owner, id);
     }
 }
Esempio n. 2
0
        /// <summary>
        ///     Tries to insert a held item in any fitting item slot. If a valid slot already contains an item, it will
        ///     swap it out and place the old one in the user's hand.
        /// </summary>
        /// <remarks>
        ///     This only handles the event if the user has an applicable entity that can be inserted. This allows for
        ///     other interactions to still happen (e.g., open UI, or toggle-open), despite the user holding an item.
        ///     Maybe this is undesirable.
        /// </remarks>
        private void OnInteractUsing(EntityUid uid, ItemSlotsComponent itemSlots, InteractUsingEvent args)
        {
            if (args.Handled)
            {
                return;
            }

            if (!EntityManager.TryGetComponent(args.User, out SharedHandsComponent hands))
            {
                return;
            }

            foreach (var slot in itemSlots.Slots.Values)
            {
                if (!CanInsert(uid, args.Used, slot, swap: slot.Swap, popup: args.User))
                {
                    continue;
                }

                // Drop the held item onto the floor. Return if the user cannot drop.
                if (!_handsSystem.TryDrop(args.User, args.Used, handsComp: hands))
                {
                    return;
                }

                if (slot.Item != null)
                {
                    _handsSystem.TryPickupAnyHand(args.User, slot.Item.Value, handsComp: hands);
                }

                Insert(uid, slot, args.Used, args.User, excludeUserAudio: args.Predicted);
                args.Handled = true;
                return;
            }
        }
        /// <summary>
        ///     Tries to insert a held item in any fitting item slot. If a valid slot already contains an item, it will
        ///     swap it out and place the old one in the user's hand.
        /// </summary>
        /// <remarks>
        ///     This only handles the event if the user has an applicable entity that can be inserted. This allows for
        ///     other interactions to still happen (e.g., open UI, or toggle-open), despite the user holding an item.
        ///     Maybe this is undesirable.
        /// </remarks>
        private void OnInteractUsing(EntityUid uid, ItemSlotsComponent itemSlots, InteractUsingEvent args)
        {
            if (args.Handled)
            {
                return;
            }

            if (!EntityManager.TryGetComponent(args.User, out SharedHandsComponent hands))
            {
                return;
            }

            foreach (var slot in itemSlots.Slots.Values)
            {
                if (!CanInsert(uid, args.Used, slot, swap: slot.Swap, popup: args.User))
                {
                    continue;
                }

                // Drop the held item onto the floor. Return if the user cannot drop.
                if (!hands.Drop(args.Used))
                {
                    return;
                }

                if (slot.Item != null)
                {
                    hands.TryPutInAnyHand(slot.Item.Value);
                }

                Insert(uid, slot, args.Used, args.User);
                args.Handled = true;
                return;
            }
        }
Esempio n. 4
0
        /// <summary>
        ///     Update the locked state of the managed item slots.
        /// </summary>
        /// <remarks>
        ///     Note that the slot's ContainerSlot performs its own networking, so we don't need to send information
        ///     about the contained entity.
        /// </remarks>
        private void HandleItemSlotsState(EntityUid uid, ItemSlotsComponent component, ref ComponentHandleState args)
        {
            if (args.Current is not ItemSlotsComponentState state)
            {
                return;
            }

            foreach (var(key, slot) in component.Slots)
            {
                if (!state.Slots.ContainsKey(key))
                {
                    RemoveItemSlot(uid, slot, component);
                }
            }

            foreach (var(serverKey, serverSlot) in state.Slots)
            {
                if (component.Slots.TryGetValue(serverKey, out var itemSlot))
                {
                    itemSlot.CopyFrom(serverSlot);
                    itemSlot.ContainerSlot = _containers.EnsureContainer <ContainerSlot>(uid, serverKey);
                }
                else
                {
                    var slot = new ItemSlot(serverSlot);
                    slot.Local = false;
                    AddItemSlot(uid, serverKey, slot);
                }
            }
        }
Esempio n. 5
0
 /// <summary>
 ///     Eject items from (some) slots when the entity is destroyed.
 /// </summary>
 private void OnBreak(EntityUid uid, ItemSlotsComponent component, EntityEventArgs args)
 {
     foreach (var slot in component.Slots.Values)
     {
         if (slot.EjectOnBreak && slot.HasItem)
         {
             TryEject(uid, slot, null, out var _);
         }
     }
 }
Esempio n. 6
0
        /// <summary>
        ///     Update the locked state of the managed item slots.
        /// </summary>
        /// <remarks>
        ///     Note that the slot's ContainerSlot performs its own networking, so we don't need to send information
        ///     about the contained entity.
        /// </remarks>
        private void HandleItemSlotsState(EntityUid uid, ItemSlotsComponent component, ref ComponentHandleState args)
        {
            if (args.Current is not ItemSlotsComponentState state)
            {
                return;
            }

            foreach (var(id, locked) in state.SlotLocked)
            {
                component.Slots[id].Locked = locked;
            }
        }
Esempio n. 7
0
        /// <summary>
        ///     Spawn in starting items for any item slots that should have one.
        /// </summary>
        private void OnMapInit(EntityUid uid, ItemSlotsComponent itemSlots, MapInitEvent args)
        {
            foreach (var slot in itemSlots.Slots.Values)
            {
                if (slot.HasItem || string.IsNullOrEmpty(slot.StartingItem))
                {
                    continue;
                }

                var item = EntityManager.SpawnEntity(slot.StartingItem, EntityManager.GetComponent <TransformComponent>(itemSlots.Owner).Coordinates);
                slot.ContainerSlot?.Insert(item);
            }
        }
        private void AddEjectVerbs(EntityUid uid, ItemSlotsComponent itemSlots, GetVerbsEvent <AlternativeVerb> args)
        {
            if (args.Hands == null || !args.CanAccess || !args.CanInteract)
            {
                return;
            }

            foreach (var slot in itemSlots.Slots.Values)
            {
                if (slot.EjectOnInteract)
                {
                    // For this item slot, ejecting/inserting is a primary interaction. Instead of an eject category
                    // alt-click verb, there will be a "Take item" primary interaction verb.
                    continue;
                }

                if (!CanEject(slot))
                {
                    continue;
                }

                if (!_actionBlockerSystem.CanPickup(args.User, slot.Item !.Value))
                {
                    continue;
                }

                var verbSubject = slot.Name != string.Empty
                    ? Loc.GetString(slot.Name)
                    : EntityManager.GetComponent <MetaDataComponent>(slot.Item.Value).EntityName ?? string.Empty;

                AlternativeVerb verb = new();
                verb.IconEntity = slot.Item;
                verb.Act        = () => TryEjectToHands(uid, slot, args.User, excludeUserAudio: true);

                if (slot.EjectVerbText == null)
                {
                    verb.Text     = verbSubject;
                    verb.Category = VerbCategory.Eject;
                }
                else
                {
                    verb.Text = Loc.GetString(slot.EjectVerbText);
                }

                verb.Priority = slot.Priority;
                args.Verbs.Add(verb);
            }
        }
        private void HandleButtonPressed(EntityUid uid, ItemSlotsComponent component, ItemSlotButtonPressedEvent args)
        {
            if (!component.Slots.TryGetValue(args.SlotId, out var slot))
            {
                return;
            }

            if (args.TryEject && slot.HasItem)
            {
                TryEjectToHands(uid, slot, args.Session.AttachedEntity);
            }
            else if (args.TryInsert && !slot.HasItem && args.Session.AttachedEntity is EntityUid user)
            {
                TryInsertFromHand(uid, slot, user);
            }
        }
Esempio n. 10
0
        /// <summary>
        ///     Attempt to eject an item from the first valid item slot.
        /// </summary>
        private void OnUseInHand(EntityUid uid, ItemSlotsComponent itemSlots, UseInHandEvent args)
        {
            if (args.Handled)
            {
                return;
            }

            foreach (var slot in itemSlots.Slots.Values)
            {
                if (slot.Locked || !slot.EjectOnUse || slot.Item == null)
                {
                    continue;
                }

                args.Handled = true;
                TryEjectToHands(uid, slot, args.User);
                break;
            }
        }
Esempio n. 11
0
        private void AddEjectVerbs(EntityUid uid, ItemSlotsComponent itemSlots, GetAlternativeVerbsEvent args)
        {
            if (args.Hands == null || !args.CanAccess || !args.CanInteract ||
                !_actionBlockerSystem.CanPickup(args.User))
            {
                return;
            }

            foreach (var slot in itemSlots.Slots.Values)
            {
                if (slot.Locked || !slot.HasItem)
                {
                    continue;
                }

                if (slot.EjectOnInteract)
                {
                    // For this item slot, ejecting/inserting is a primary interaction. Instead of an eject category
                    // alt-click verb, there will be a "Take item" primary interaction verb.
                    continue;
                }

                var verbSubject = slot.Name != string.Empty
                    ? Loc.GetString(slot.Name)
                    : EntityManager.GetComponent <MetaDataComponent>(slot.Item !.Value).EntityName ?? string.Empty;

                Verb verb = new();
                verb.Act = () => TryEjectToHands(uid, slot, args.User);

                if (slot.EjectVerbText == null)
                {
                    verb.Text     = verbSubject;
                    verb.Category = VerbCategory.Eject;
                }
                else
                {
                    verb.Text        = Loc.GetString(slot.EjectVerbText);
                    verb.IconTexture = "/Textures/Interface/VerbIcons/eject.svg.192dpi.png";
                }

                args.Verbs.Add(verb);
            }
        }
Esempio n. 12
0
 private void GetItemSlotsState(EntityUid uid, ItemSlotsComponent component, ref ComponentGetState args)
 {
     args.State = new ItemSlotsComponentState(component.Slots);
 }
Esempio n. 13
0
        private void AddInteractionVerbsVerbs(EntityUid uid, ItemSlotsComponent itemSlots, GetVerbsEvent <InteractionVerb> args)
        {
            if (args.Hands == null || !args.CanAccess || !args.CanInteract)
            {
                return;
            }

            // If there are any slots that eject on left-click, add a "Take <item>" verb.
            foreach (var slot in itemSlots.Slots.Values)
            {
                if (!slot.EjectOnInteract || !CanEject(slot))
                {
                    continue;
                }

                if (!_actionBlockerSystem.CanPickup(args.User, slot.Item !.Value))
                {
                    continue;
                }

                var verbSubject = slot.Name != string.Empty
                    ? Loc.GetString(slot.Name)
                    : EntityManager.GetComponent <MetaDataComponent>(slot.Item !.Value).EntityName ?? string.Empty;

                InteractionVerb takeVerb = new();
                takeVerb.IconEntity = slot.Item;
                takeVerb.Act        = () => TryEjectToHands(uid, slot, args.User, excludeUserAudio: true);

                if (slot.EjectVerbText == null)
                {
                    takeVerb.Text = Loc.GetString("take-item-verb-text", ("subject", verbSubject));
                }
                else
                {
                    takeVerb.Text = Loc.GetString(slot.EjectVerbText);
                }

                args.Verbs.Add(takeVerb);
            }

            // Next, add the insert-item verbs
            if (args.Using == null || !_actionBlockerSystem.CanDrop(args.User))
            {
                return;
            }

            foreach (var slot in itemSlots.Slots.Values)
            {
                if (!CanInsert(uid, args.Using.Value, slot))
                {
                    continue;
                }

                var verbSubject = slot.Name != string.Empty
                    ? Loc.GetString(slot.Name)
                    : Name(args.Using.Value) ?? string.Empty;

                InteractionVerb insertVerb = new();
                insertVerb.IconEntity = args.Using;
                insertVerb.Act        = () => Insert(uid, slot, args.Using.Value, args.User, excludeUserAudio: true);

                if (slot.InsertVerbText != null)
                {
                    insertVerb.Text        = Loc.GetString(slot.InsertVerbText);
                    insertVerb.IconTexture = "/Textures/Interface/VerbIcons/insert.svg.192dpi.png";
                }
                else if (slot.EjectOnInteract)
                {
                    // Inserting/ejecting is a primary interaction for this entity. Instead of using the insert
                    // category, we will use a single "Place <item>" verb.
                    insertVerb.Text        = Loc.GetString("place-item-verb-text", ("subject", verbSubject));
                    insertVerb.IconTexture = "/Textures/Interface/VerbIcons/drop.svg.192dpi.png";
                }
                else
                {
                    insertVerb.Category = VerbCategory.Insert;
                    insertVerb.Text     = verbSubject;
                }

                args.Verbs.Add(insertVerb);
            }
        }
Esempio n. 14
0
 /// <summary>
 ///     Lock an item slot. This stops items from being inserted into or ejected from this slot.
 /// </summary>
 public void SetLock(ItemSlotsComponent itemSlots, ItemSlot slot, bool locked)
 {
     slot.Locked = locked;
     itemSlots.Dirty();
 }