]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Popup duplicate stacking (#27978)
authorShadowCommander <10494922+ShadowCommander@users.noreply.github.com>
Wed, 29 May 2024 04:05:40 +0000 (21:05 -0700)
committerGitHub <noreply@github.com>
Wed, 29 May 2024 04:05:40 +0000 (00:05 -0400)
Content.Client/Popups/PopupSystem.cs
Resources/Locale/en-US/popup/popup.ftl [new file with mode: 0644]

index 1ef8dfba2d1d4e354a1e9b216fec2ab3c8a1f0b6..700f6b6d26fc6bde45c6d16ab1a5128ebef77b59 100644 (file)
@@ -1,18 +1,20 @@
 using System.Linq;
+using Content.Shared.Containers;
 using Content.Shared.Examine;
 using Content.Shared.GameTicking;
 using Content.Shared.Popups;
+using JetBrains.Annotations;
 using Robust.Client.Graphics;
 using Robust.Client.Input;
 using Robust.Client.Player;
 using Robust.Client.UserInterface;
+using Robust.Shared.Collections;
 using Robust.Shared.Configuration;
 using Robust.Shared.Map;
 using Robust.Shared.Player;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Replays;
 using Robust.Shared.Timing;
-using Robust.Shared.Utility;
 
 namespace Content.Client.Popups
 {
@@ -29,11 +31,11 @@ namespace Content.Client.Popups
         [Dependency] private readonly ExamineSystemShared _examine = default!;
         [Dependency] private readonly SharedTransformSystem _transform = default!;
 
-        public IReadOnlyList<WorldPopupLabel> WorldLabels => _aliveWorldLabels;
-        public IReadOnlyList<CursorPopupLabel> CursorLabels => _aliveCursorLabels;
+        public IReadOnlyCollection<WorldPopupLabel> WorldLabels => _aliveWorldLabels.Values;
+        public IReadOnlyCollection<CursorPopupLabel> CursorLabels => _aliveCursorLabels.Values;
 
-        private readonly List<WorldPopupLabel> _aliveWorldLabels = new();
-        private readonly List<CursorPopupLabel> _aliveCursorLabels = new();
+        private readonly Dictionary<WorldPopupData, WorldPopupLabel> _aliveWorldLabels = new();
+        private readonly Dictionary<CursorPopupData, CursorPopupLabel> _aliveCursorLabels = new();
 
         public const float MinimumPopupLifetime = 0.7f;
         public const float MaximumPopupLifetime = 5f;
@@ -65,6 +67,15 @@ namespace Content.Client.Popups
                 .RemoveOverlay<PopupOverlay>();
         }
 
+        private void WrapAndRepeatPopup(PopupLabel existingLabel, string popupMessage)
+        {
+            existingLabel.TotalTime = 0;
+            existingLabel.Repeats += 1;
+            existingLabel.Text = Loc.GetString("popup-system-repeated-popup-stacking-wrap",
+                ("popup-message", popupMessage),
+                ("count", existingLabel.Repeats));
+        }
+
         private void PopupMessage(string? message, PopupType type, EntityCoordinates coordinates, EntityUid? entity, bool recordReplay)
         {
             if (message == null)
@@ -78,13 +89,20 @@ namespace Content.Client.Popups
                     _replayRecording.RecordClientMessage(new PopupCoordinatesEvent(message, type, GetNetCoordinates(coordinates)));
             }
 
+            var popupData = new WorldPopupData(message, type, coordinates, entity);
+            if (_aliveWorldLabels.TryGetValue(popupData, out var existingLabel))
+            {
+                WrapAndRepeatPopup(existingLabel, popupData.Message);
+                return;
+            }
+
             var label = new WorldPopupLabel(coordinates)
             {
                 Text = message,
                 Type = type,
             };
 
-            _aliveWorldLabels.Add(label);
+            _aliveWorldLabels.Add(popupData, label);
         }
 
         #region Abstract Method Implementations
@@ -113,13 +131,20 @@ namespace Content.Client.Popups
             if (recordReplay && _replayRecording.IsRecording)
                 _replayRecording.RecordClientMessage(new PopupCursorEvent(message, type));
 
+            var popupData = new CursorPopupData(message, type);
+            if (_aliveCursorLabels.TryGetValue(popupData, out var existingLabel))
+            {
+                WrapAndRepeatPopup(existingLabel, popupData.Message);
+                return;
+            }
+
             var label = new CursorPopupLabel(_inputManager.MouseScreenPosition)
             {
                 Text = message,
                 Type = type,
             };
 
-            _aliveCursorLabels.Add(label);
+            _aliveCursorLabels.Add(popupData, label);
         }
 
         public override void PopupCursor(string? message, PopupType type = PopupType.Small)
@@ -249,27 +274,37 @@ namespace Content.Client.Popups
             if (_aliveWorldLabels.Count == 0 && _aliveCursorLabels.Count == 0)
                 return;
 
-            for (var i = 0; i < _aliveWorldLabels.Count; i++)
+            if (_aliveWorldLabels.Count > 0)
             {
-                var label = _aliveWorldLabels[i];
-                label.TotalTime += frameTime;
-
-                if (label.TotalTime > GetPopupLifetime(label) || Deleted(label.InitialPos.EntityId))
+                var aliveWorldToRemove = new ValueList<WorldPopupData>();
+                foreach (var (data, label) in _aliveWorldLabels)
+                {
+                    label.TotalTime += frameTime;
+                    if (label.TotalTime > GetPopupLifetime(label) || Deleted(label.InitialPos.EntityId))
+                    {
+                        aliveWorldToRemove.Add(data);
+                    }
+                }
+                foreach (var data in aliveWorldToRemove)
                 {
-                    _aliveWorldLabels.RemoveSwap(i);
-                    i--;
+                    _aliveWorldLabels.Remove(data);
                 }
             }
 
-            for (var i = 0; i < _aliveCursorLabels.Count; i++)
+            if (_aliveCursorLabels.Count > 0)
             {
-                var label = _aliveCursorLabels[i];
-                label.TotalTime += frameTime;
-
-                if (label.TotalTime > GetPopupLifetime(label))
+                var aliveCursorToRemove = new ValueList<CursorPopupData>();
+                foreach (var (data, label) in _aliveCursorLabels)
+                {
+                    label.TotalTime += frameTime;
+                    if (label.TotalTime > GetPopupLifetime(label))
+                    {
+                        aliveCursorToRemove.Add(data);
+                    }
+                }
+                foreach (var data in aliveCursorToRemove)
                 {
-                    _aliveCursorLabels.RemoveSwap(i);
-                    i--;
+                    _aliveCursorLabels.Remove(data);
                 }
             }
         }
@@ -279,29 +314,32 @@ namespace Content.Client.Popups
             public PopupType Type = PopupType.Small;
             public string Text { get; set; } = string.Empty;
             public float TotalTime { get; set; }
+            public int Repeats = 1;
         }
 
-        public sealed class CursorPopupLabel : PopupLabel
-        {
-            public ScreenCoordinates InitialPos;
-
-            public CursorPopupLabel(ScreenCoordinates screenCoords)
-            {
-                InitialPos = screenCoords;
-            }
-        }
-
-        public sealed class WorldPopupLabel : PopupLabel
+        public sealed class WorldPopupLabel(EntityCoordinates coordinates) : PopupLabel
         {
             /// <summary>
             /// The original EntityCoordinates of the label.
             /// </summary>
-            public EntityCoordinates InitialPos;
+            public EntityCoordinates InitialPos = coordinates;
+        }
 
-            public WorldPopupLabel(EntityCoordinates coordinates)
-            {
-                InitialPos = coordinates;
-            }
+        public sealed class CursorPopupLabel(ScreenCoordinates screenCoords) : PopupLabel
+        {
+            public ScreenCoordinates InitialPos = screenCoords;
         }
+
+        [UsedImplicitly]
+        private record struct WorldPopupData(
+            string Message,
+            PopupType Type,
+            EntityCoordinates Coordinates,
+            EntityUid? Entity);
+
+        [UsedImplicitly]
+        private record struct CursorPopupData(
+            string Message,
+            PopupType Type);
     }
 }
diff --git a/Resources/Locale/en-US/popup/popup.ftl b/Resources/Locale/en-US/popup/popup.ftl
new file mode 100644 (file)
index 0000000..4bc677c
--- /dev/null
@@ -0,0 +1 @@
+popup-system-repeated-popup-stacking-wrap = {$popup-message} x{$count}