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; }