diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs
index f25273f40394c1..3ced8b2625e6c5 100644
--- a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs
+++ b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs
@@ -60,6 +60,7 @@ public override void Initialize()
}
#region ComponentManagement
+
///
/// Spawn in starting items for any item slots that should have one.
///
@@ -70,7 +71,8 @@ private void OnMapInit(EntityUid uid, ItemSlotsComponent itemSlots, MapInitEvent
if (slot.HasItem || string.IsNullOrEmpty(slot.StartingItem))
continue;
- var item = EntityManager.SpawnEntity(slot.StartingItem, EntityManager.GetComponent(uid).Coordinates);
+ var item = EntityManager.SpawnEntity(slot.StartingItem,
+ EntityManager.GetComponent(uid).Coordinates);
if (slot.ContainerSlot != null)
_containers.Insert(item, slot.ContainerSlot);
}
@@ -99,7 +101,8 @@ public void AddItemSlot(EntityUid uid, string id, ItemSlot slot, ItemSlotsCompon
if (itemSlots.Slots.TryGetValue(id, out var existing))
{
if (existing.Local)
- Log.Error($"Duplicate item slot key. Entity: {EntityManager.GetComponent(uid).EntityName} ({uid}), key: {id}");
+ Log.Error(
+ $"Duplicate item slot key. Entity: {EntityManager.GetComponent(uid).EntityName} ({uid}), key: {id}");
else
// server state takes priority
slot.CopyFrom(existing);
@@ -134,7 +137,10 @@ public void RemoveItemSlot(EntityUid uid, ItemSlot slot, ItemSlotsComponent? ite
Dirty(uid, itemSlots);
}
- public bool TryGetSlot(EntityUid uid, string slotId, [NotNullWhen(true)] out ItemSlot? itemSlot, ItemSlotsComponent? component = null)
+ public bool TryGetSlot(EntityUid uid,
+ string slotId,
+ [NotNullWhen(true)] out ItemSlot? itemSlot,
+ ItemSlotsComponent? component = null)
{
itemSlot = null;
@@ -143,9 +149,11 @@ public bool TryGetSlot(EntityUid uid, string slotId, [NotNullWhen(true)] out Ite
return component.Slots.TryGetValue(slotId, out itemSlot);
}
+
#endregion
#region Interactions
+
///
/// Attempt to take an item from a slot, if any are set to EjectOnInteract.
///
@@ -201,20 +209,50 @@ private void OnInteractUsing(EntityUid uid, ItemSlotsComponent itemSlots, Intera
if (!EntityManager.TryGetComponent(args.User, out HandsComponent? hands))
return;
+ if (itemSlots.Slots.Count == 0)
+ return;
+
+ // If any slot can be inserted into don't show popup.
+ // If any whitelist passes, but slot is locked, then show locked.
+ // If whitelist fails all, show whitelist fail.
+
+ // valid, insertable slots (if any)
var slots = new List();
+
+ string? whitelistFailPopup = null;
+ string? lockedFailPopup = null;
foreach (var slot in itemSlots.Slots.Values)
{
if (!slot.InsertOnInteract)
continue;
- if (!CanInsert(uid, args.Used, args.User, slot, swap: slot.Swap, popup: args.User))
- continue;
+ if (CanInsert(uid, args.Used, args.User, slot, slot.Swap))
+ {
+ slots.Add(slot);
+ }
+ else
+ {
+ var allowed = CanInsertWhitelist(args.Used, slot);
+ if (lockedFailPopup == null && slot.LockedFailPopup != null && allowed && slot.Locked)
+ lockedFailPopup = slot.LockedFailPopup;
- slots.Add(slot);
+ if (whitelistFailPopup == null && slot.WhitelistFailPopup != null)
+ whitelistFailPopup = slot.WhitelistFailPopup;
+ }
}
if (slots.Count == 0)
+ {
+ // it's a bit weird that the popupMessage is stored with the item slots themselves, but in practice
+ // the popup messages will just all be the same, so it's probably fine.
+ //
+ // doing a check to make sure that they're all the same or something is probably frivolous
+ if (lockedFailPopup != null)
+ _popupSystem.PopupClient(Loc.GetString(lockedFailPopup), uid, args.User);
+ else if (whitelistFailPopup != null)
+ _popupSystem.PopupClient(Loc.GetString(whitelistFailPopup), uid, args.User);
return;
+ }
// Drop the held item onto the floor. Return if the user cannot drop.
if (!_handsSystem.TryDrop(args.User, args.Used, handsComp: hands))
@@ -236,23 +274,31 @@ private void OnInteractUsing(EntityUid uid, ItemSlotsComponent itemSlots, Intera
return;
}
}
+
#endregion
#region Insert
+
///
/// Insert an item into a slot. This does not perform checks, so make sure to also use or just use instead.
///
/// If true, will exclude the user when playing sound. Does nothing client-side.
/// Useful for predicted interactions
- private void Insert(EntityUid uid, ItemSlot slot, EntityUid item, EntityUid? user, bool excludeUserAudio = false)
+ private void Insert(EntityUid uid,
+ ItemSlot slot,
+ EntityUid item,
+ EntityUid? user,
+ bool excludeUserAudio = false)
{
bool? inserted = slot.ContainerSlot != null ? _containers.Insert(item, slot.ContainerSlot) : null;
// ContainerSlot automatically raises a directed EntInsertedIntoContainerMessage
// Logging
if (inserted != null && inserted.Value && user != null)
- _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user.Value)} inserted {ToPrettyString(item)} into {slot.ContainerSlot?.ID + " slot of "}{ToPrettyString(uid)}");
+ _adminLogger.Add(LogType.Action,
+ LogImpact.Low,
+ $"{ToPrettyString(user.Value)} inserted {ToPrettyString(item)} into {slot.ContainerSlot?.ID + " slot of "}{ToPrettyString(uid)}");
_audioSystem.PlayPredicted(slot.InsertSound, uid, excludeUserAudio ? user : null);
}
@@ -261,46 +307,53 @@ private void Insert(EntityUid uid, ItemSlot slot, EntityUid item, EntityUid? use
/// Check whether a given item can be inserted into a slot. Unless otherwise specified, this will return
/// false if the slot is already filled.
///
- ///
- /// If a popup entity is given, and if the item slot is set to generate a popup message when it fails to
- /// pass the whitelist or due to slot being locked, then this will generate an appropriate popup.
- ///
- public bool CanInsert(EntityUid uid, EntityUid usedUid, EntityUid? user, ItemSlot slot, bool swap = false, EntityUid? popup = null)
+ public bool CanInsert(EntityUid uid,
+ EntityUid usedUid,
+ EntityUid? user,
+ ItemSlot slot,
+ bool swap = false)
{
if (slot.ContainerSlot == null)
return false;
- if (_whitelistSystem.IsWhitelistFail(slot.Whitelist, usedUid) || _whitelistSystem.IsBlacklistPass(slot.Blacklist, usedUid))
- {
- if (popup.HasValue && slot.WhitelistFailPopup.HasValue)
- _popupSystem.PopupClient(Loc.GetString(slot.WhitelistFailPopup), uid, popup.Value);
+ if (slot.HasItem && (!swap || swap && !CanEject(uid, user, slot)))
return false;
- }
- if (slot.Locked)
- {
- if (popup.HasValue && slot.LockedFailPopup.HasValue)
- _popupSystem.PopupClient(Loc.GetString(slot.LockedFailPopup), uid, popup.Value);
+ if (!CanInsertWhitelist(usedUid, slot))
return false;
- }
- if (slot.HasItem && (!swap || (swap && !CanEject(uid, user, slot))))
+ if (slot.Locked)
return false;
var ev = new ItemSlotInsertAttemptEvent(uid, usedUid, user, slot);
RaiseLocalEvent(uid, ref ev);
RaiseLocalEvent(usedUid, ref ev);
if (ev.Cancelled)
+ {
return false;
+ }
return _containers.CanInsert(usedUid, slot.ContainerSlot, assumeEmpty: swap);
}
+ private bool CanInsertWhitelist(EntityUid usedUid, ItemSlot slot)
+ {
+ if (_whitelistSystem.IsWhitelistFail(slot.Whitelist, usedUid)
+ || _whitelistSystem.IsBlacklistPass(slot.Blacklist, usedUid))
+ return false;
+ return true;
+ }
+
///
/// Tries to insert item into a specific slot.
///
/// False if failed to insert item
- public bool TryInsert(EntityUid uid, string id, EntityUid item, EntityUid? user, ItemSlotsComponent? itemSlots = null, bool excludeUserAudio = false)
+ public bool TryInsert(EntityUid uid,
+ string id,
+ EntityUid item,
+ EntityUid? user,
+ ItemSlotsComponent? itemSlots = null,
+ bool excludeUserAudio = false)
{
if (!Resolve(uid, ref itemSlots))
return false;
@@ -315,7 +368,11 @@ public bool TryInsert(EntityUid uid, string id, EntityUid item, EntityUid? user,
/// Tries to insert item into a specific slot.
///
/// False if failed to insert item
- public bool TryInsert(EntityUid uid, ItemSlot slot, EntityUid item, EntityUid? user, bool excludeUserAudio = false)
+ public bool TryInsert(EntityUid uid,
+ ItemSlot slot,
+ EntityUid item,
+ EntityUid? user,
+ bool excludeUserAudio = false)
{
if (!CanInsert(uid, item, user, slot))
return false;
@@ -329,7 +386,11 @@ public bool TryInsert(EntityUid uid, ItemSlot slot, EntityUid item, EntityUid? u
/// Does not check action blockers.
///
/// False if failed to insert item
- public bool TryInsertFromHand(EntityUid uid, ItemSlot slot, EntityUid user, HandsComponent? hands = null, bool excludeUserAudio = false)
+ public bool TryInsertFromHand(EntityUid uid,
+ ItemSlot slot,
+ EntityUid user,
+ HandsComponent? hands = null,
+ bool excludeUserAudio = false)
{
if (!Resolve(user, ref hands, false))
return false;
@@ -443,6 +504,7 @@ private static int SortEmpty(ItemSlot a, ItemSlot b)
return 1;
}
+
#endregion
#region Eject
@@ -462,7 +524,7 @@ public bool CanEject(EntityUid uid, EntityUid? user, ItemSlot slot, EntityUid? p
return false;
}
- if (slot.ContainerSlot?.ContainedEntity is not {} item)
+ if (slot.ContainerSlot?.ContainedEntity is not { } item)
return false;
var ev = new ItemSlotEjectAttemptEvent(uid, item, user, slot);
@@ -487,7 +549,9 @@ private void Eject(EntityUid uid, ItemSlot slot, EntityUid item, EntityUid? user
// Logging
if (ejected != null && ejected.Value && user != null)
- _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user.Value)} ejected {ToPrettyString(item)} from {slot.ContainerSlot?.ID + " slot of "}{ToPrettyString(uid)}");
+ _adminLogger.Add(LogType.Action,
+ LogImpact.Low,
+ $"{ToPrettyString(user.Value)} ejected {ToPrettyString(item)} from {slot.ContainerSlot?.ID + " slot of "}{ToPrettyString(uid)}");
_audioSystem.PlayPredicted(slot.EjectSound, uid, excludeUserAudio ? user : null);
}
@@ -496,7 +560,11 @@ private void Eject(EntityUid uid, ItemSlot slot, EntityUid item, EntityUid? user
/// Try to eject an item from a slot.
///
/// False if item slot is locked or has no item inserted
- public bool TryEject(EntityUid uid, ItemSlot slot, EntityUid? user, [NotNullWhen(true)] out EntityUid? item, bool excludeUserAudio = false)
+ public bool TryEject(EntityUid uid,
+ ItemSlot slot,
+ EntityUid? user,
+ [NotNullWhen(true)] out EntityUid? item,
+ bool excludeUserAudio = false)
{
item = null;
@@ -518,8 +586,12 @@ public bool TryEject(EntityUid uid, ItemSlot slot, EntityUid? user, [NotNullWhen
/// Try to eject item from a slot.
///
/// False if the id is not valid, the item slot is locked, or it has no item inserted
- public bool TryEject(EntityUid uid, string id, EntityUid? user,
- [NotNullWhen(true)] out EntityUid? item, ItemSlotsComponent? itemSlots = null, bool excludeUserAudio = false)
+ public bool TryEject(EntityUid uid,
+ string id,
+ EntityUid? user,
+ [NotNullWhen(true)] out EntityUid? item,
+ ItemSlotsComponent? itemSlots = null,
+ bool excludeUserAudio = false)
{
item = null;
@@ -550,12 +622,16 @@ public bool TryEjectToHands(EntityUid uid, ItemSlot slot, EntityUid? user, bool
return true;
}
+
#endregion
#region Verbs
- private void AddAlternativeVerbs(EntityUid uid, ItemSlotsComponent itemSlots, GetVerbsEvent args)
+
+ private void AddAlternativeVerbs(EntityUid uid,
+ ItemSlotsComponent itemSlots,
+ GetVerbsEvent args)
{
- if (args.Hands == null || !args.CanAccess ||!args.CanInteract)
+ if (args.Hands == null || !args.CanAccess || !args.CanInteract)
{
return;
}
@@ -649,7 +725,9 @@ private void AddAlternativeVerbs(EntityUid uid, ItemSlotsComponent itemSlots, Ge
}
}
- private void AddInteractionVerbsVerbs(EntityUid uid, ItemSlotsComponent itemSlots, GetVerbsEvent args)
+ private void AddInteractionVerbsVerbs(EntityUid uid,
+ ItemSlotsComponent itemSlots,
+ GetVerbsEvent args)
{
if (args.Hands == null || !args.CanAccess || !args.CanInteract)
return;
@@ -708,7 +786,7 @@ private void AddInteractionVerbsVerbs(EntityUid uid, ItemSlotsComponent itemSlot
new SpriteSpecifier.Texture(
new ResPath("/Textures/Interface/VerbIcons/insert.svg.192dpi.png"));
}
- else if(slot.EjectOnInteract)
+ 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 - " verb.
@@ -727,9 +805,11 @@ private void AddInteractionVerbsVerbs(EntityUid uid, ItemSlotsComponent itemSlot
args.Verbs.Add(insertVerb);
}
}
+
#endregion
#region BUIs
+
private void HandleButtonPressed(EntityUid uid, ItemSlotsComponent component, ItemSlotButtonPressedEvent args)
{
if (!component.Slots.TryGetValue(args.SlotId, out var slot))
@@ -740,6 +820,7 @@ private void HandleButtonPressed(EntityUid uid, ItemSlotsComponent component, It
else if (args.TryInsert && !slot.HasItem)
TryInsertFromHand(uid, slot, args.Actor);
}
+
#endregion
///