]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Adding sorting to chem master (#34763)
authorDora <27211909+catdotjs@users.noreply.github.com>
Thu, 27 Feb 2025 11:19:52 +0000 (13:19 +0200)
committerGitHub <noreply@github.com>
Thu, 27 Feb 2025 11:19:52 +0000 (12:19 +0100)
* Adding sorting to chem master

* Chem Master can now sort based on following categories
 - Alphabetical
 - Quantity
 - Time Added to Machine

* Sorting is disabled by default and persist in the machine for everyone

* Removed some pointless code from Chem Master's UI

* Changed None and Time Added's text to reflect what they do better

* Minor adjustments to the code requested by maintainers

Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs
Content.Client/Chemistry/UI/ChemMasterWindow.xaml
Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs
Content.Server/Chemistry/Components/ChemMasterComponent.cs
Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs
Content.Shared/Chemistry/SharedChemMaster.cs
Resources/Locale/en-US/chemistry/components/chem-master-component.ftl

index 3ef7f0ae73ed19f95dbc689fedf84d35e243df1b..a669a8da4c179ba1ba76e0acfa26be6b0cc18fbc 100644 (file)
@@ -46,6 +46,8 @@ namespace Content.Client.Chemistry.UI
             _window.CreateBottleButton.OnPressed += _ => SendMessage(
                 new ChemMasterOutputToBottleMessage(
                     (uint) _window.BottleDosage.Value, _window.LabelLine));
+            _window.BufferSortButton.OnPressed += _ => SendMessage(
+                    new ChemMasterSortingTypeCycleMessage());
 
             for (uint i = 0; i < _window.PillTypeButtons.Length; i++)
             {
index b1f4f5917f419a392cc1e2b4afc31d12452835d3..aca316f6b353e040380672c97041a27338a1dd5b 100644 (file)
@@ -34,6 +34,7 @@
                 <Label Text="{Loc 'chem-master-window-buffer-text'}" />
                 <Control HorizontalExpand="True" />
                 <Button MinSize="80 0" Name="BufferTransferButton" Access="Public" Text="{Loc 'chem-master-window-transfer-button'}" ToggleMode="True" StyleClasses="OpenRight" />
+                <Button MinSize="80 0" Name="BufferSortButton" Access="Public" Text="{Loc 'chem-master-window-sort-type-none'}" StyleClasses="OpenBoth" />
                 <Button MinSize="80 0" Name="BufferDiscardButton" Access="Public" Text="{Loc 'chem-master-window-discard-button'}" ToggleMode="True" StyleClasses="OpenLeft" />
             </BoxContainer>
 
index 20c61f10cb821a629e2be687f0b5b3aea9d25236..807ec4c1e7c4979760b3a8a3d8312cdb07390a84 100644 (file)
@@ -140,17 +140,17 @@ namespace Content.Client.Chemistry.UI
 
             // Ensure the Panel Info is updated, including UI elements for Buffer Volume, Output Container and so on
             UpdatePanelInfo(castState);
-    
+
             BufferCurrentVolume.Text = $" {castState.BufferCurrentVolume?.Int() ?? 0}u";
-    
+
             InputEjectButton.Disabled = castState.InputContainerInfo is null;
             OutputEjectButton.Disabled = castState.OutputContainerInfo is null;
             CreateBottleButton.Disabled = castState.OutputContainerInfo?.Reagents == null;
             CreatePillButton.Disabled = castState.OutputContainerInfo?.Entities == null;
-            
+
             UpdateDosageFields(castState);
         }
-        
+
         //assign default values for pill and bottle fields.
         private void UpdateDosageFields(ChemMasterBoundUserInterfaceState castState)
         {
@@ -162,8 +162,9 @@ namespace Content.Client.Chemistry.UI
             var bufferVolume = castState.BufferCurrentVolume?.Int() ?? 0;
 
             PillDosage.Value = (int)Math.Min(bufferVolume, castState.PillDosageLimit);
-            
+
             PillTypeButtons[castState.SelectedPillType].Pressed = true;
+
             PillNumber.IsValid = x => x >= 0 && x <= pillNumberMax;
             PillDosage.IsValid = x => x > 0 && x <= castState.PillDosageLimit;
             BottleDosage.IsValid = x => x >= 0 && x <= bottleAmountMax;
@@ -213,6 +214,17 @@ namespace Content.Client.Chemistry.UI
 
             BufferInfo.Children.Clear();
 
+            // This has to happen here due to people possibly
+            // setting sorting before putting any chemicals
+            BufferSortButton.Text = state.SortingType switch
+            {
+                ChemMasterSortingType.Alphabetical => Loc.GetString("chem-master-window-sort-type-alphabetical"),
+                ChemMasterSortingType.Quantity => Loc.GetString("chem-master-window-sort-type-quantity"),
+                ChemMasterSortingType.Latest => Loc.GetString("chem-master-window-sort-type-latest"),
+                _ => Loc.GetString("chem-master-window-sort-type-none")
+            };
+
+
             if (!state.BufferReagents.Any())
             {
                 BufferInfo.Children.Add(new Label { Text = Loc.GetString("chem-master-window-buffer-empty-text") });
@@ -235,19 +247,48 @@ namespace Content.Client.Chemistry.UI
             };
             bufferHBox.AddChild(bufferVol);
 
-            // initialises rowCount to allow for striped rows
-
-            var rowCount = 0;
+            // This sets up the needed data for sorting later in a list
+            // Its done this way to not repeat having to use same code twice (once for sorting
+            // and once for displaying)
+            var reagentList = new List<(ReagentId reagentId, string name, Color color, FixedPoint2 quantity)>();
             foreach (var (reagent, quantity) in state.BufferReagents)
             {
                 var reagentId = reagent;
                 _prototypeManager.TryIndex(reagentId.Prototype, out ReagentPrototype? proto);
                 var name = proto?.LocalizedName ?? Loc.GetString("chem-master-window-unknown-reagent-text");
                 var reagentColor = proto?.SubstanceColor ?? default(Color);
-                BufferInfo.Children.Add(BuildReagentRow(reagentColor, rowCount++, name, reagentId, quantity, true, true));
+                reagentList.Add(new (reagentId, name, reagentColor, quantity));
+            }
+
+            // We sort here since we need sorted list to be filled first.
+            // You can easily add any new params you need to it.
+            switch (state.SortingType)
+            {
+                case ChemMasterSortingType.Alphabetical:
+                    reagentList = reagentList.OrderBy(x => x.name).ToList();
+                    break;
+
+                case ChemMasterSortingType.Quantity:
+                    reagentList = reagentList.OrderByDescending(x => x.quantity).ToList();
+                    break;
+                case ChemMasterSortingType.Latest:
+                    reagentList = Enumerable.Reverse(reagentList).ToList();
+                    break;
+
+                case ChemMasterSortingType.None:
+                default:
+                    // This case is pointless but it is there for readability
+                    break;
+            }
+
+            // initialises rowCount to allow for striped rows
+            var rowCount = 0;
+            foreach (var reagent in reagentList)
+            {
+                BufferInfo.Children.Add(BuildReagentRow(reagent.color, rowCount++, reagent.name, reagent.reagentId, reagent.quantity, true, true));
             }
         }
-        
+
         private void BuildContainerUI(Control control, ContainerInfo? info, bool addReagentButtons)
         {
             control.Children.Clear();
@@ -295,7 +336,7 @@ namespace Content.Client.Chemistry.UI
                     _prototypeManager.TryIndex(reagent.Reagent.Prototype, out ReagentPrototype? proto);
                     var name = proto?.LocalizedName ?? Loc.GetString("chem-master-window-unknown-reagent-text");
                     var reagentColor = proto?.SubstanceColor ?? default(Color);
-        
+
                     control.Children.Add(BuildReagentRow(reagentColor, rowCount++, name, reagent.Reagent, reagent.Quantity, false, addReagentButtons));
                 }
             }
@@ -315,7 +356,7 @@ namespace Content.Client.Chemistry.UI
             }
             //this calls the separated button builder, and stores the return to render after labels
             var reagentButtonConstructors = CreateReagentTransferButtons(reagent, isBuffer, addReagentButtons);
-            
+
             // Create the row layout with the color panel
             var rowContainer = new BoxContainer
             {
@@ -358,7 +399,7 @@ namespace Content.Client.Chemistry.UI
                 Children = { rowContainer }
             };
         }
-        
+
         public string LabelLine
         {
             get => LabelLineEdit.Text;
index 9578755ba766196a139168c948a4e9d1d40c956e..0309d07ed9d82ec04c981e2cbe3e40bd2a9bbf92 100644 (file)
@@ -18,6 +18,9 @@ namespace Content.Server.Chemistry.Components
         [DataField("mode"), ViewVariables(VVAccess.ReadWrite)]
         public ChemMasterMode Mode = ChemMasterMode.Transfer;
 
+        [DataField]
+        public ChemMasterSortingType SortingType = ChemMasterSortingType.None;
+
         [DataField("pillDosageLimit", required: true), ViewVariables(VVAccess.ReadWrite)]
         public uint PillDosageLimit;
 
index c733c7215ee66456c029ebe94a13f806acb9bc38..dd97bfa8f65d8fbf2284c0039d4bb00bad0cbb94 100644 (file)
@@ -53,6 +53,7 @@ namespace Content.Server.Chemistry.EntitySystems
             SubscribeLocalEvent<ChemMasterComponent, BoundUIOpenedEvent>(SubscribeUpdateUiState);
 
             SubscribeLocalEvent<ChemMasterComponent, ChemMasterSetModeMessage>(OnSetModeMessage);
+            SubscribeLocalEvent<ChemMasterComponent, ChemMasterSortingTypeCycleMessage>(OnCycleSortingTypeMessage);
             SubscribeLocalEvent<ChemMasterComponent, ChemMasterSetPillTypeMessage>(OnSetPillTypeMessage);
             SubscribeLocalEvent<ChemMasterComponent, ChemMasterReagentAmountButtonMessage>(OnReagentButtonMessage);
             SubscribeLocalEvent<ChemMasterComponent, ChemMasterCreatePillsMessage>(OnCreatePillsMessage);
@@ -76,7 +77,7 @@ namespace Content.Server.Chemistry.EntitySystems
             var bufferCurrentVolume = bufferSolution.Volume;
 
             var state = new ChemMasterBoundUserInterfaceState(
-                chemMaster.Mode, BuildInputContainerInfo(inputContainer), BuildOutputContainerInfo(outputContainer),
+                chemMaster.Mode, chemMaster.SortingType, BuildInputContainerInfo(inputContainer), BuildOutputContainerInfo(outputContainer),
                 bufferReagents, bufferCurrentVolume, chemMaster.PillType, chemMaster.PillDosageLimit, updateLabel);
 
             _userInterfaceSystem.SetUiState(owner, ChemMasterUiKey.Key, state);
@@ -93,6 +94,15 @@ namespace Content.Server.Chemistry.EntitySystems
             ClickSound(chemMaster);
         }
 
+        private void OnCycleSortingTypeMessage(Entity<ChemMasterComponent> chemMaster, ref ChemMasterSortingTypeCycleMessage message)
+        {
+            chemMaster.Comp.SortingType++;
+            if (chemMaster.Comp.SortingType > ChemMasterSortingType.Latest)
+                chemMaster.Comp.SortingType = ChemMasterSortingType.None;
+            UpdateUiState(chemMaster);
+            ClickSound(chemMaster);
+        }
+
         private void OnSetPillTypeMessage(Entity<ChemMasterComponent> chemMaster, ref ChemMasterSetPillTypeMessage message)
         {
             // Ensure valid pill type. There are 20 pills selectable, 0-19.
index 762131d7612284662db4827b8e6a207ae7e72706..67bd9a0d6395134f6dbd6a38f3b716dc81534082 100644 (file)
@@ -89,6 +89,18 @@ namespace Content.Shared.Chemistry
         Discard,
     }
 
+    public enum ChemMasterSortingType : byte
+    {
+        None = 0,
+        Alphabetical = 1,
+        Quantity = 2,
+        Latest = 3,
+    }
+
+    [Serializable, NetSerializable]
+    public sealed class ChemMasterSortingTypeCycleMessage : BoundUserInterfaceMessage;
+
+
     public enum ChemMasterReagentAmount
     {
         U1 = 1,
@@ -160,6 +172,8 @@ namespace Content.Shared.Chemistry
 
         public readonly ChemMasterMode Mode;
 
+        public readonly ChemMasterSortingType SortingType;
+
         public readonly FixedPoint2? BufferCurrentVolume;
         public readonly uint SelectedPillType;
 
@@ -168,7 +182,7 @@ namespace Content.Shared.Chemistry
         public readonly bool UpdateLabel;
 
         public ChemMasterBoundUserInterfaceState(
-            ChemMasterMode mode, ContainerInfo? inputContainerInfo, ContainerInfo? outputContainerInfo,
+            ChemMasterMode mode, ChemMasterSortingType sortingType, ContainerInfo? inputContainerInfo, ContainerInfo? outputContainerInfo,
             IReadOnlyList<ReagentQuantity> bufferReagents, FixedPoint2 bufferCurrentVolume,
             uint selectedPillType, uint pillDosageLimit, bool updateLabel)
         {
@@ -176,6 +190,7 @@ namespace Content.Shared.Chemistry
             OutputContainerInfo = outputContainerInfo;
             BufferReagents = bufferReagents;
             Mode = mode;
+            SortingType = sortingType;
             BufferCurrentVolume = bufferCurrentVolume;
             SelectedPillType = selectedPillType;
             PillDosageLimit = pillDosageLimit;
index 51110f12c4cd682953a2d16eda0e3706a1350f76..c000811e77d606ce422c0d34bc8e353b60843ad7 100644 (file)
@@ -29,3 +29,7 @@ chem-master-window-dose-label = Dose (u):
 chem-master-window-create-button = Create
 chem-master-window-bottles-label = Bottles:
 chem-master-window-unknown-reagent-text = Unknown reagent
+chem-master-window-sort-type-none = Sort by: Oldest First
+chem-master-window-sort-type-alphabetical = Sort by: Alphabetical
+chem-master-window-sort-type-quantity = Sort by: Quantity
+chem-master-window-sort-type-latest = Sort by: Recent First