diff --git a/Content.Client/Actions/UI/ActionSlot.cs b/Content.Client/Actions/UI/ActionSlot.cs
index 73d96fe4ed..05b2ea955a 100644
--- a/Content.Client/Actions/UI/ActionSlot.cs
+++ b/Content.Client/Actions/UI/ActionSlot.cs
@@ -28,6 +28,8 @@ namespace Content.Client.Actions.UI
private static readonly string EnabledColor = "#7b7e9e";
private static readonly string DisabledColor = "#950000";
+ private bool _spriteViewDirty = false;
+
///
/// Current action in this slot.
///
@@ -40,6 +42,7 @@ namespace Content.Client.Actions.UI
public byte SlotIndex { get; }
private readonly IGameTiming _gameTiming;
+ private readonly IEntityManager _entMan;
private readonly RichTextLabel _number;
private readonly TextureRect _bigActionIcon;
private readonly TextureRect _smallActionIcon;
@@ -56,11 +59,12 @@ namespace Content.Client.Actions.UI
/// Creates an action slot for the specified number
///
/// slot index this corresponds to, 0-9 (0 labeled as 1, 8, labeled "9", 9 labeled as "0".
- public ActionSlot(ActionsUI actionsUI, ActionMenu actionMenu, byte slotIndex)
+ public ActionSlot(ActionsUI actionsUI, ActionMenu actionMenu, byte slotIndex, IGameTiming timing, IEntityManager entMan)
{
_actionsUI = actionsUI;
_actionMenu = actionMenu;
- _gameTiming = IoCManager.Resolve();
+ _gameTiming = timing;
+ _entMan = entMan;
SlotIndex = slotIndex;
MouseFilter = MouseFilterMode.Stop;
@@ -422,7 +426,17 @@ namespace Content.Client.Actions.UI
private void UpdateItemIcon()
{
- if (Action?.EntityIcon == null || !IoCManager.Resolve().TryGetComponent(Action.EntityIcon.Value, out SpriteComponent sprite))
+ if (Action?.EntityIcon != null && !_entMan.EntityExists(Action.EntityIcon))
+ {
+ // This is almost certainly because a player received/processed their own actions component state before
+ // being send the entity in their inventory that enabled this action.
+
+ // Defer updating icons to the next FrameUpdate().
+ _spriteViewDirty = true;
+ return;
+ }
+
+ if (Action?.EntityIcon == null || !_entMan.TryGetComponent(Action.EntityIcon.Value, out SpriteComponent sprite))
{
_bigItemSpriteView.Visible = false;
_bigItemSpriteView.Sprite = null;
@@ -502,6 +516,13 @@ namespace Content.Client.Actions.UI
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
+
+ if (_spriteViewDirty)
+ {
+ _spriteViewDirty = false;
+ UpdateIcons();
+ }
+
if (Action == null || Action.Cooldown == null || !Action.Enabled)
{
_cooldownGraphic.Visible = false;
diff --git a/Content.Client/Actions/UI/ActionsUI.cs b/Content.Client/Actions/UI/ActionsUI.cs
index 612ca306d6..9cd0369221 100644
--- a/Content.Client/Actions/UI/ActionsUI.cs
+++ b/Content.Client/Actions/UI/ActionsUI.cs
@@ -26,6 +26,8 @@ namespace Content.Client.Actions.UI
private const float CustomTooltipDelay = 0.4f;
internal readonly ActionsSystem System;
private readonly IGameHud _gameHud;
+ private readonly IEntityManager _entMan;
+ private readonly IGameTiming _timing;
///
/// The action component of the currently attached entity.
@@ -79,6 +81,8 @@ namespace Content.Client.Actions.UI
System = system;
Component = component;
_gameHud = IoCManager.Resolve();
+ _timing = IoCManager.Resolve();
+ _entMan = IoCManager.Resolve();
_menu = new ActionMenu(this);
LayoutContainer.SetGrowHorizontal(this, LayoutContainer.GrowDirection.End);
@@ -205,7 +209,7 @@ namespace Content.Client.Actions.UI
for (byte i = 0; i < ActionsSystem.Slots; i++)
{
- var slot = new ActionSlot(this, _menu, i);
+ var slot = new ActionSlot(this, _menu, i, _timing, _entMan);
_slotContainer.AddChild(slot);
_slots[i] = slot;
}