]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Simplify hands UI code (#42534)
authorpathetic meowmeow <uhhadd@gmail.com>
Thu, 22 Jan 2026 21:31:45 +0000 (16:31 -0500)
committerGitHub <noreply@github.com>
Thu, 22 Jan 2026 21:31:45 +0000 (21:31 +0000)
* Simplify hands UI code

* i remembered about SortedHands in the component

* minor cleanup

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
Content.Client/UserInterface/Systems/Hands/Controls/HandsContainer.cs
Content.Client/UserInterface/Systems/Hands/HandsUIController.cs
Content.Client/UserInterface/Systems/Hotbar/HotbarUIController.cs
Content.Client/UserInterface/Systems/Hotbar/Widgets/HotbarGui.xaml.cs
Content.Client/UserInterface/Systems/Inventory/Controls/ItemSlotUIContainer.cs
Content.Client/UserInterface/Systems/Inventory/Controls/ItemStatusPanel.xaml.cs
Content.Client/UserInterface/Systems/Inventory/InventoryUIController.cs
Content.Shared/Hands/Components/HandsComponent.cs
Content.Shared/Hands/EntitySystems/SharedHandsSystem.cs

index d2f24abd6c57d6444498570d60d79dbcf3b528b9..e6c83a1262d0fca51a377039326ad1a6964a7aba 100644 (file)
@@ -1,5 +1,7 @@
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Content.Client.UserInterface.Systems.Inventory.Controls;
+using Content.Shared.Hands.Components;
 using Robust.Client.UserInterface.Controls;
 
 namespace Content.Client.UserInterface.Systems.Hands.Controls;
@@ -7,10 +9,10 @@ namespace Content.Client.UserInterface.Systems.Hands.Controls;
 public sealed class HandsContainer : ItemSlotUIContainer<HandButton>
 {
     private readonly GridContainer _grid;
-    public int ColumnLimit { get => _grid.Columns; set => _grid.Columns = value; }
-    public int MaxButtonCount { get; set; } = 0;
+    private readonly List<HandButton> _orderedButtons = new();
+    public HandsComponent? PlayerHandsComponent;
 
-    public int MaxButtonsPerRow { get; set;  }= 6;
+    public int ColumnLimit { get; set; } = 6;
 
     /// <summary>
     ///     Indexer. This is used to reference a HandsContainer from the
@@ -24,57 +26,32 @@ public sealed class HandsContainer : ItemSlotUIContainer<HandButton>
         _grid.ExpandBackwards = true;
     }
 
-    public override HandButton? AddButton(HandButton newButton)
+    protected override void AddButton(HandButton newButton)
     {
-        if (MaxButtonCount > 0)
-        {
-            if (ButtonCount >= MaxButtonCount)
-                return null;
+        _orderedButtons.Add(newButton);
 
-            _grid.AddChild(newButton);
-        }
-        else
+        _grid.RemoveAllChildren();
+        var enumerable = PlayerHandsComponent?.SortedHands is { } sortedHands
+            ? _orderedButtons.OrderBy(it => sortedHands.IndexOf(it.SlotName))
+            : _orderedButtons.OrderBy(it => it.HandLocation);
+        foreach (var button in enumerable)
         {
-            _grid.AddChild(newButton);
+            _grid.AddChild(button);
         }
 
-        _grid.Columns = Math.Min(_grid.ChildCount, MaxButtonsPerRow);
-        return base.AddButton(newButton);
+        _grid.Columns = Math.Min(_grid.ChildCount, ColumnLimit);
     }
 
-    public override void RemoveButton(string handName)
+    protected override void RemoveButton(HandButton button)
     {
-        var button = GetButton(handName);
-        if (button == null)
-            return;
-        base.RemoveButton(button);
+        _orderedButtons.Remove(button);
         _grid.RemoveChild(button);
     }
 
-    public bool TryGetLastButton(out HandButton? control)
+    public override void ClearButtons()
     {
-        if (Buttons.Count == 0)
-        {
-            control = null;
-            return false;
-        }
-
-        control = Buttons.Values.Last();
-        return true;
-    }
-
-    public bool TryRemoveLastHand(out HandButton? control)
-    {
-        var success = TryGetLastButton(out control);
-        if (control != null)
-            RemoveButton(control);
-        return success;
-    }
-
-    public void Clear()
-    {
-        ClearButtons();
-        _grid.RemoveAllChildren();
+        base.ClearButtons();
+        _orderedButtons.Clear();
     }
 
     public IEnumerable<HandButton> GetButtons()
@@ -85,8 +62,4 @@ public sealed class HandsContainer : ItemSlotUIContainer<HandButton>
                 yield return hand;
         }
     }
-
-    public bool IsFull => (MaxButtonCount != 0 && ButtonCount >= MaxButtonCount);
-
-    public int ButtonCount => _grid.ChildCount;
 }
index a20f4b35f83138a7097a199fc0d566d2a46693b6..122e0b2f088349c414465e795456fdde37db3b93 100644 (file)
@@ -7,7 +7,6 @@ using Content.Shared.Hands.Components;
 using Content.Shared.Input;
 using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Timing;
-using JetBrains.Annotations;
 using Robust.Client.Player;
 using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.Controllers;
@@ -26,9 +25,6 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
     [UISystemDependency] private readonly HandsSystem _handsSystem = default!;
     [UISystemDependency] private readonly UseDelaySystem _useDelay = default!;
 
-    private readonly List<HandsContainer> _handsContainers = new();
-    private readonly Dictionary<string, int> _handContainerIndices = new();
-    private readonly Dictionary<string, HandButton> _handLookup = new();
     private HandsComponent? _playerHandsComponent;
     private HandButton? _activeHand;
 
@@ -40,8 +36,6 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
     private HandButton? _statusHandLeft;
     private HandButton? _statusHandRight;
 
-    private int _backupSuffix; //this is used when autogenerating container names if they don't have names
-
     private HotbarGui? HandsGui => UIManager.GetActiveUIWidgetOrNull<HotbarGui>();
 
     public void OnSystemLoaded(HandsSystem system)
@@ -119,25 +113,16 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
 
     private void UnloadPlayerHands()
     {
-        if (HandsGui != null)
-            HandsGui.Visible = false;
-
-        _handContainerIndices.Clear();
-        _handLookup.Clear();
+        HandsGui?.Visible = false;
+        HandsGui?.HandContainer.ClearButtons();
         _playerHandsComponent = null;
-
-        foreach (var container in _handsContainers)
-        {
-            container.Clear();
-        }
     }
 
     private void LoadPlayerHands(Entity<HandsComponent> handsComp)
     {
         DebugTools.Assert(_playerHandsComponent == null);
-        if (HandsGui != null)
-            HandsGui.Visible = true;
-
+        HandsGui?.Visible = true;
+        HandsGui?.HandContainer.PlayerHandsComponent = handsComp;
         _playerHandsComponent = handsComp;
         foreach (var (name, hand) in handsComp.Comp.Hands)
         {
@@ -182,29 +167,18 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
 
     private void HandBlocked(string handName)
     {
-        if (!_handLookup.TryGetValue(handName, out var hand))
-        {
+        if (HandsGui?.HandContainer.TryGetButton(handName, out var hand) != true)
             return;
-        }
 
-        hand.Blocked = true;
+        hand!.Blocked = true;
     }
 
     private void HandUnblocked(string handName)
     {
-        if (!_handLookup.TryGetValue(handName, out var hand))
-        {
+        if (HandsGui?.HandContainer.TryGetButton(handName, out var hand) != true)
             return;
-        }
 
-        hand.Blocked = false;
-    }
-
-    private int GetHandContainerIndex(string containerName)
-    {
-        if (!_handContainerIndices.TryGetValue(containerName, out var result))
-            return -1;
-        return result;
+        hand!.Blocked = false;
     }
 
     private void OnItemAdded(string name, EntityUid entity)
@@ -243,7 +217,7 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
             _handsSystem.TryGetHand((playerEntity, _playerHandsComponent), name, out var handData))
         {
             UpdateHandStatus(hand, null, handData);
-            if (handData?.EmptyRepresentative is { } representative)
+            if (handData.Value.EmptyRepresentative is { } representative)
             {
                 SetRepresentative(hand, representative);
                 return;
@@ -253,30 +227,6 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
         hand.SetEntity(null);
     }
 
-    private HandsContainer GetFirstAvailableContainer()
-    {
-        if (_handsContainers.Count == 0)
-            throw new Exception("Could not find an attached hand hud container");
-        foreach (var container in _handsContainers)
-        {
-            if (container.IsFull)
-                continue;
-            return container;
-        }
-
-        throw new Exception("All attached hand hud containers were full!");
-    }
-
-    public bool TryGetHandContainer(string containerName, out HandsContainer? container)
-    {
-        container = null;
-        var containerIndex = GetHandContainerIndex(containerName);
-        if (containerIndex == -1)
-            return false;
-        container = _handsContainers[containerIndex];
-        return true;
-    }
-
     //propagate hand activation to the hand system.
     private void StorageActivate(GUIBoundKeyEventArgs args, SlotControl handControl)
     {
@@ -293,24 +243,23 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
             return;
         }
 
-        if (!_handLookup.TryGetValue(handName, out var handControl) || handControl == _activeHand)
+        if (HandsGui?.HandContainer.TryGetButton(handName, out var handControl) != true || handControl == _activeHand)
             return;
 
         if (_activeHand != null)
             _activeHand.Highlight = false;
 
-        handControl.Highlight = true;
+        handControl!.Highlight = true;
         _activeHand = handControl;
 
-        if (HandsGui != null &&
-            _playerHandsComponent != null &&
+        if (_playerHandsComponent != null &&
             _player.LocalSession?.AttachedEntity is { } playerEntity &&
             _handsSystem.TryGetHand((playerEntity, _playerHandsComponent), handName, out var hand))
         {
             var heldEnt = _handsSystem.GetHeldItem((playerEntity, _playerHandsComponent), handName);
 
-            var foldedLocation = hand.Value.Location.GetUILocation();
-            if (foldedLocation == HandUILocation.Left)
+            var foldedLocation = hand.Value.Location;
+            if (foldedLocation == HandLocation.Left)
             {
                 _statusHandLeft = handControl;
                 HandsGui.UpdatePanelEntityLeft(heldEnt, hand.Value);
@@ -328,8 +277,7 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
 
     private HandButton? GetHand(string handName)
     {
-        _handLookup.TryGetValue(handName, out var handControl);
-        return handControl;
+        return HandsGui?.HandContainer.GetButton(handName);
     }
 
     private HandButton AddHand(string handName, Hand hand)
@@ -338,17 +286,7 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
         button.StoragePressed += StorageActivate;
         button.Pressed += HandPressed;
 
-        if (!_handLookup.TryAdd(handName, button))
-            return _handLookup[handName];
-
-        if (HandsGui != null)
-        {
-            HandsGui.HandContainer.AddButton(button);
-        }
-        else
-        {
-            GetFirstAvailableContainer().AddButton(button);
-        }
+        HandsGui?.HandContainer.TryAddButton(button);
 
         if (hand.EmptyRepresentative is { } representative)
         {
@@ -359,7 +297,7 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
         // If we don't have a status for this hand type yet, set it.
         // This means we have status filled by default in most scenarios,
         // otherwise the user'd need to switch hands to "activate" the hands the first time.
-        if (hand.Location.GetUILocation() == HandUILocation.Left)
+        if (hand.Location == HandLocation.Left)
             _statusHandLeft ??= button;
         else
             _statusHandRight ??= button;
@@ -378,62 +316,17 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
         _handsSystem.ReloadHandButtons();
     }
 
-    /// <summary>
-    ///     Swap hands from one container to the other.
-    /// </summary>
-    /// <param name="other"></param>
-    /// <param name="source"></param>
-    public void SwapHands(HandsContainer other, HandsContainer? source = null)
-    {
-        if (HandsGui == null && source == null)
-        {
-            throw new ArgumentException("Cannot swap hands if no source hand container exists!");
-        }
-
-        source ??= HandsGui!.HandContainer;
-
-        var transfer = new List<Control>();
-        foreach (var child in source.Children)
-        {
-            if (child is not HandButton)
-            {
-                continue;
-            }
-
-            transfer.Add(child);
-        }
-
-        foreach (var control in transfer)
-        {
-            source.RemoveChild(control);
-            other.AddChild(control);
-        }
-    }
-
     private void RemoveHand(string handName)
     {
-        RemoveHand(handName, out _);
-    }
-
-    [PublicAPI]
-    private bool RemoveHand(string handName, out HandButton? handButton)
-    {
-        if (!_handLookup.TryGetValue(handName, out handButton))
-            return false;
-        if (handButton.Parent is HandsContainer handContainer)
-        {
-            handContainer.RemoveButton(handButton);
-        }
+        if (HandsGui?.HandContainer.TryRemoveButton(handName, out var handButton) != true)
+            return;
 
         if (_statusHandLeft == handButton)
             _statusHandLeft = null;
         if (_statusHandRight == handButton)
             _statusHandRight = null;
 
-        _handLookup.Remove(handName);
-        handButton.Orphan();
         UpdateVisibleStatusPanels();
-        return true;
     }
 
     private void UpdateVisibleStatusPanels()
@@ -441,9 +334,12 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
         var leftVisible = false;
         var rightVisible = false;
 
-        foreach (var hand in _handLookup.Values)
+        if (HandsGui is null)
+            return;
+
+        foreach (var hand in HandsGui.HandContainer.GetButtons())
         {
-            if (hand.HandLocation.GetUILocation() == HandUILocation.Left)
+            if (hand.HandLocation == HandLocation.Left)
             {
                 leftVisible = true;
             }
@@ -453,73 +349,34 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
             }
         }
 
-        HandsGui?.UpdateStatusVisibility(leftVisible, rightVisible);
-    }
-
-    public string RegisterHandContainer(HandsContainer handContainer)
-    {
-        var name = "HandContainer_" + _backupSuffix;
-
-        if (handContainer.Indexer == null)
-        {
-            handContainer.Indexer = name;
-            _backupSuffix++;
-        }
-        else
-        {
-            name = handContainer.Indexer;
-        }
-
-        _handContainerIndices.Add(name, _handsContainers.Count);
-        _handsContainers.Add(handContainer);
-        return name;
-    }
-
-    public bool RemoveHandContainer(string handContainerName)
-    {
-        var index = GetHandContainerIndex(handContainerName);
-        if (index == -1)
-            return false;
-        _handContainerIndices.Remove(handContainerName);
-        _handsContainers.RemoveAt(index);
-        return true;
-    }
-
-    public bool RemoveHandContainer(string handContainerName, out HandsContainer? container)
-    {
-        var success = _handContainerIndices.TryGetValue(handContainerName, out var index);
-        container = _handsContainers[index];
-        _handContainerIndices.Remove(handContainerName);
-        _handsContainers.RemoveAt(index);
-        return success;
+        HandsGui.UpdateStatusVisibility(leftVisible, rightVisible);
     }
 
     public void OnStateEntered(GameplayState state)
     {
-        if (HandsGui != null)
-            HandsGui.Visible = _playerHandsComponent != null;
+        HandsGui?.Visible = _playerHandsComponent != null;
     }
 
     public override void FrameUpdate(FrameEventArgs args)
     {
         base.FrameUpdate(args);
 
+        if (HandsGui is not { } handsGui)
+            return;
+
         // TODO this should be event based but 2 systems modify the same component differently for some reason
-        foreach (var container in _handsContainers)
+        foreach (var hand in handsGui.HandContainer.GetButtons())
         {
-            foreach (var hand in container.GetButtons())
-            {
-
-                if (!_entities.TryGetComponent(hand.Entity, out UseDelayComponent? useDelay))
-                {
-                    hand.CooldownDisplay.Visible = false;
-                    continue;
-                }
-                var delay = _useDelay.GetLastEndingDelay((hand.Entity.Value, useDelay));
 
-                hand.CooldownDisplay.Visible = true;
-                hand.CooldownDisplay.FromTime(delay.StartTime, delay.EndTime);
+            if (!_entities.TryGetComponent(hand.Entity, out UseDelayComponent? useDelay))
+            {
+                hand.CooldownDisplay.Visible = false;
+                continue;
             }
+            var delay = _useDelay.GetLastEndingDelay((hand.Entity.Value, useDelay));
+
+            hand.CooldownDisplay.Visible = true;
+            hand.CooldownDisplay.FromTime(delay.StartTime, delay.EndTime);
         }
     }
 
index b89115da86b9756afffb32efbbe32135d5fa619b..c567fb55fc6edde087a73f08343b34d592414ea8 100644 (file)
@@ -36,7 +36,6 @@ public sealed class HotbarUIController : UIController
         _inventory = UIManager.GetUIController<InventoryUIController>();
         _hands = UIManager.GetUIController<HandsUIController>();
         _storage = UIManager.GetUIController<StorageUIController>();
-        _hands.RegisterHandContainer(handsContainer);
     }
 
     public void ReloadHotbar()
index f6802de28fb259d61f80dad42a18fc657ea5cd95..81dfffb062f565eef80ee34d035025cb61556e73 100644 (file)
@@ -11,8 +11,8 @@ public sealed partial class HotbarGui : UIWidget
     public HotbarGui()
     {
         RobustXamlLoader.Load(this);
-        StatusPanelRight.SetSide(HandUILocation.Right);
-        StatusPanelLeft.SetSide(HandUILocation.Left);
+        StatusPanelRight.SetSide(HandLocation.Right);
+        StatusPanelLeft.SetSide(HandLocation.Left);
         var hotbarController = UserInterfaceManager.GetUIController<HotbarUIController>();
 
         hotbarController.Setup(HandContainer);
@@ -29,10 +29,10 @@ public sealed partial class HotbarGui : UIWidget
         StatusPanelRight.Update(entity, hand);
     }
 
-    public void SetHighlightHand(HandUILocation? hand)
+    public void SetHighlightHand(HandLocation? hand)
     {
-        StatusPanelLeft.UpdateHighlight(hand is HandUILocation.Left);
-        StatusPanelRight.UpdateHighlight(hand is HandUILocation.Right);
+        StatusPanelLeft.UpdateHighlight(hand is HandLocation.Left);
+        StatusPanelRight.UpdateHighlight(hand is HandLocation.Right);
     }
 
     public void UpdateStatusVisibility(bool left, bool right)
index df45ceabf627cfd2db3aade345e03e5558b5a2e5..8094a77b6be3119e009f3dd99b100ba17301eb4f 100644 (file)
@@ -14,54 +14,36 @@ public interface IItemslotUIContainer
 [Virtual]
 public abstract class ItemSlotUIContainer<T> : GridContainer, IItemslotUIContainer where T : SlotControl
 {
-    protected readonly Dictionary<string, T> Buttons = new();
+    private readonly Dictionary<string, T> _buttons = new();
 
-    private int? _maxColumns;
+    public int? MaxColumns { get; set; }
 
-    public int? MaxColumns
+    public virtual void ClearButtons()
     {
-        get => _maxColumns;
-        set => _maxColumns = value;
-    }
-
-    public virtual bool TryAddButton(T newButton, out T button)
-    {
-        var tempButton = AddButton(newButton);
-        if (tempButton == null)
-        {
-            button = newButton;
-            return false;
-        }
-
-        button = newButton;
-        return true;
-    }
-
-    public void ClearButtons()
-    {
-        foreach (var button in Buttons.Values)
+        foreach (var button in _buttons.Values)
         {
-            button.Dispose();
+            button.Orphan();
         }
 
-        Buttons.Clear();
+        _buttons.Clear();
     }
 
     public bool TryRegisterButton(SlotControl control, string newSlotName)
     {
         if (newSlotName == "")
             return false;
-        if (!(control is T slotButton))
+        if (control is not T slotButton)
             return false;
-        if (Buttons.TryGetValue(newSlotName, out var foundButton))
+
+        if (_buttons.TryGetValue(newSlotName, out var foundButton))
         {
             if (control == foundButton)
                 return true; //if the slotName is already set do nothing
             throw new Exception("Could not update button to slot:" + newSlotName + " slot already assigned!");
         }
 
-        Buttons.Remove(slotButton.SlotName);
-        AddButton(slotButton);
+        _buttons.Remove(slotButton.SlotName);
+        TryAddButton(slotButton);
         return true;
     }
 
@@ -69,69 +51,54 @@ public abstract class ItemSlotUIContainer<T> : GridContainer, IItemslotUIContain
     {
         if (control is not T newButton)
             return false;
-        return AddButton(newButton) != null;
-    }
-
-    public virtual T? AddButton(T newButton)
-    {
-        if (!Children.Contains(newButton) && newButton.Parent == null && newButton.SlotName != "")
-            AddChild(newButton);
-        Columns = _maxColumns ?? ChildCount;
-        return AddButtonToDict(newButton);
+        return TryAddButton(newButton) != null;
     }
 
-    protected virtual T? AddButtonToDict(T newButton)
+    public T? TryAddButton(T newButton)
     {
         if (newButton.SlotName == "")
         {
-            Logger.Warning("Could not add button " + newButton.Name + "No slotname");
+            Log.Warning($"{newButton.Name} because it has no slot name");
+            return null;
         }
 
-        return !Buttons.TryAdd(newButton.SlotName, newButton) ? null : newButton;
-    }
+        if (Children.Contains(newButton) || newButton.Parent != null)
+            return null;
 
-    public virtual void RemoveButton(string slotName)
-    {
-        if (!Buttons.TryGetValue(slotName, out var button))
-            return;
-        RemoveButton(button);
-    }
+        if (!_buttons.TryAdd(newButton.SlotName, newButton))
+            return null;
 
-    public virtual void RemoveButtons(params string[] slotNames)
-    {
-        foreach (var slotName in slotNames)
-        {
-            RemoveButton(slotName);
-        }
+        AddButton(newButton);
+        return newButton;
     }
 
-    public virtual void RemoveButtons(params T?[] buttons)
+    protected virtual void AddButton(T newButton)
     {
-        foreach (var button in buttons)
-        {
-            if (button != null)
-                RemoveButton(button);
-        }
+        AddChild(newButton);
+        Columns = MaxColumns ?? ChildCount;
     }
 
-    protected virtual void RemoveButtonFromDict(T button)
+    public bool TryRemoveButton(string slotName, [NotNullWhen(true)] out T? button)
     {
-        Buttons.Remove(button.SlotName);
+        if (!_buttons.TryGetValue(slotName, out button))
+            return false;
+
+        _buttons.Remove(button.SlotName);
+        RemoveButton(button);
+        return true;
     }
 
-    public virtual void RemoveButton(T button)
+    protected virtual void RemoveButton(T button)
     {
-        RemoveButtonFromDict(button);
         Children.Remove(button);
-        button.Dispose();
     }
 
-    public virtual T? GetButton(string slotName)
+    public T? GetButton(string slotName)
     {
-        return !Buttons.TryGetValue(slotName, out var button) ? null : button;
+        return _buttons.GetValueOrDefault(slotName);
     }
 
-    public virtual bool TryGetButton(string slotName, [NotNullWhen(true)] out T? button)
+    public bool TryGetButton(string slotName, [NotNullWhen(true)] out T? button)
     {
         return (button = GetButton(slotName)) != null;
     }
index dcc6221e46d9ba559988cea1dad4a5a957fbb468..d5502028c6b4f238deac7bc460e7d541184c73c9 100644 (file)
@@ -20,7 +20,7 @@ public sealed partial class ItemStatusPanel : Control
     [ViewVariables] private Hand? _hand;
 
     // Tracked so we can re-run SetSide() if the theme changes.
-    private HandUILocation _side;
+    private HandLocation _side;
 
     public ItemStatusPanel()
     {
@@ -28,7 +28,7 @@ public sealed partial class ItemStatusPanel : Control
         IoCManager.InjectDependencies(this);
     }
 
-    public void SetSide(HandUILocation location)
+    public void SetSide(HandLocation location)
     {
         // AN IMPORTANT REMINDER ABOUT THIS CODE:
         // In the UI, the RIGHT hand is on the LEFT on the screen.
@@ -43,14 +43,14 @@ public sealed partial class ItemStatusPanel : Control
 
         switch (location)
         {
-            case HandUILocation.Right:
+            case HandLocation.Right or HandLocation.Middle:
                 texture = Theme.ResolveTexture("item_status_right");
                 textureHighlight = Theme.ResolveTexture("item_status_right_highlight");
                 cutOut = StyleBox.Margin.Left;
                 flat = StyleBox.Margin.Right;
                 contentMargin = MarginFromThemeColor("_itemstatus_content_margin_right");
                 break;
-            case HandUILocation.Left:
+            case HandLocation.Left:
                 texture = Theme.ResolveTexture("item_status_left");
                 textureHighlight = Theme.ResolveTexture("item_status_left_highlight");
                 cutOut = StyleBox.Margin.Right;
index ec6293811f334d4df559d2174e85d340f1189655..1fa379e525fe99f34f376178c13af0d7e5d4f999 100644 (file)
@@ -147,7 +147,7 @@ public sealed class InventoryUIController : UIController, IOnStateEntered<Gamepl
             if (!container.TryGetButton(data.SlotName, out var button))
             {
                 button = CreateSlotButton(data);
-                container.AddButton(button);
+                container.TryAddButton(button);
             }
 
             var showStorage = _entities.HasComponent<StorageComponent>(data.HeldEntity);
@@ -373,7 +373,7 @@ public sealed class InventoryUIController : UIController, IOnStateEntered<Gamepl
             return;
 
         var button = CreateSlotButton(data);
-        slotGroup.AddButton(button);
+        slotGroup.TryAddButton(button);
     }
 
     private void RemoveSlot(SlotData data)
@@ -381,7 +381,7 @@ public sealed class InventoryUIController : UIController, IOnStateEntered<Gamepl
         if (!_slotGroups.TryGetValue(data.SlotGroup, out var slotGroup))
             return;
 
-        slotGroup.RemoveButton(data.SlotName);
+        slotGroup.TryRemoveButton(data.SlotName, out _);
     }
 
     public void ReloadSlots()
index 30422210d42670c455f21beca4152127111a619b..128817a741ff0287cc57123395049a3b5a698612 100644 (file)
@@ -169,43 +169,9 @@ public sealed class HandsComponentState : ComponentState
 /// <summary>
 ///     What side of the body this hand is on.
 /// </summary>
-/// <seealso cref="HandUILocation"/>
-/// <seealso cref="HandLocationExt"/>
 public enum HandLocation : byte
 {
-    Left,
+    Right,
     Middle,
-    Right
-}
-
-/// <summary>
-/// What side of the UI a hand is on.
-/// </summary>
-/// <seealso cref="HandLocationExt"/>
-/// <seealso cref="HandLocation"/>
-public enum HandUILocation : byte
-{
-    Left,
-    Right
-}
-
-/// <summary>
-/// Helper functions for working with <see cref="HandLocation"/>.
-/// </summary>
-public static class HandLocationExt
-{
-    /// <summary>
-    /// Convert a <see cref="HandLocation"/> into the appropriate <see cref="HandUILocation"/>.
-    /// This maps "middle" hands to <see cref="HandUILocation.Right"/>.
-    /// </summary>
-    public static HandUILocation GetUILocation(this HandLocation location)
-    {
-        return location switch
-        {
-            HandLocation.Left => HandUILocation.Left,
-            HandLocation.Middle => HandUILocation.Right,
-            HandLocation.Right => HandUILocation.Right,
-            _ => throw new ArgumentOutOfRangeException(nameof(location), location, null)
-        };
-    }
+    Left
 }
index 2060ee892fde3617bc8dc69ed34e6d800e4b9b24..75d2b3ba013a594cf9bad72042e5de4ed63c68ab 100644 (file)
@@ -90,6 +90,8 @@ public abstract partial class SharedHandsSystem
 
         ent.Comp.Hands.Add(handName, hand);
         ent.Comp.SortedHands.Add(handName);
+        // we use LINQ + ToList instead of the list sort because it's a stable sort vs the list sort
+        ent.Comp.SortedHands = ent.Comp.SortedHands.OrderBy(handId => ent.Comp.Hands[handId].Location).ToList();
         Dirty(ent);
 
         OnPlayerAddHand?.Invoke((ent, ent.Comp), handName, hand.Location);