using Content.Shared.Hands.Components;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
namespace Content.Shared.Containers.ItemSlots;
public sealed partial class ItemSlotsSystem
{
///
/// Attempt to take an item from a slot if any are set to EjectOnInteract.
///
[SubscribeLocalEvent]
private void OnInteractHand(Entity ent, ref InteractHandEvent args)
{
if (args.Handled)
return;
foreach (var slot in ent.Comp.Slots.Values)
{
if (!slot.EjectOnInteract || slot.Item == null || !CanEject(ent, slot, args.User, popup: args.User))
continue;
args.Handled = true;
TryEjectToHands(ent, slot, args.User, true);
break;
}
}
///
/// Attempt to eject an item from the first valid item slot.
///
[SubscribeLocalEvent]
private void OnUseInHand(Entity ent, ref UseInHandEvent args)
{
if (args.Handled)
return;
foreach (var slot in ent.Comp.Slots.Values)
{
if (!slot.EjectOnUse || slot.Item == null || !CanEject(ent, slot, args.User, popup: args.User))
continue;
args.Handled = true;
TryEjectToHands(ent, slot, args.User, true);
break;
}
}
///
/// Tries to insert a held item into a fitting slot, swapping the current item when the selected slot allows it.
///
///
/// 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.
///
[SubscribeLocalEvent]
private void OnInteractUsing(Entity ent, ref InteractUsingEvent args)
{
if (args.Handled)
return;
if (!TryComp(args.User, out HandsComponent? hands))
return;
if (ent.Comp.Slots.Count == 0)
return;
var slots = new List();
string? whitelistFailPopup = null;
string? lockedFailPopup = null;
foreach (var slot in ent.Comp.Slots.Values)
{
if (!slot.InsertOnInteract)
continue;
if (CanInsert(ent, slot, args.Used, args.User, slot.Swap))
{
slots.Add(slot);
}
else
{
var allowed = CanInsertWhitelist(args.Used, slot);
if (lockedFailPopup == null && slot.LockedFailPopup != null && allowed && slot.Locked)
lockedFailPopup = slot.LockedFailPopup;
if (whitelistFailPopup == null && slot.WhitelistFailPopup != null && !allowed)
whitelistFailPopup = slot.WhitelistFailPopup;
}
}
if (slots.Count == 0)
{
if (lockedFailPopup != null)
_popupSystem.PopupEntity(Loc.GetString(lockedFailPopup), ent, args.User);
else if (whitelistFailPopup != null)
_popupSystem.PopupEntity(Loc.GetString(whitelistFailPopup), ent, args.User);
return;
}
if (!_handsSystem.TryDrop(args.User, args.Used))
return;
slots.Sort(SortEmpty);
foreach (var slot in slots)
{
if (slot.Item != null)
_handsSystem.TryPickupAnyHand(args.User, slot.Item.Value, handsComp: hands);
if (!Insert(ent, slot, args.Used, args.User, excludeUserAudio: true))
return;
if (slot.InsertSuccessPopup.HasValue)
_popupSystem.PopupEntity(Loc.GetString(slot.InsertSuccessPopup), ent, args.User);
args.Handled = true;
return;
}
}
[SubscribeLocalEvent]
private void HandleButtonPressed(Entity ent, ref ItemSlotButtonPressedEvent args)
{
if (!ent.Comp.Slots.TryGetValue(args.SlotId, out var slot))
return;
if (args.TryEject && slot.HasItem && !slot.DisableEject)
TryEjectToHands(ent, slot, args.Actor, true);
else if (args.TryInsert && !slot.HasItem)
TryInsertFromHand(ent, slot, args.Actor);
}
}