From 03b1a0771b76e61e45a45d14bc3103af1e8423af Mon Sep 17 00:00:00 2001 From: Whatstone Date: Sun, 2 Aug 2026 08:42:10 -0400 Subject: [PATCH 1/3] Revert "Hotfix: pass last state in SharedUserInterfaceSystem.EnsureClientBui (#6840)" This reverts commit 08b3257ecea1a76deed417945e3fae2cee125afd. --- .../Systems/SharedUserInterfaceSystem.cs | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/Robust.Shared/GameObjects/Systems/SharedUserInterfaceSystem.cs b/Robust.Shared/GameObjects/Systems/SharedUserInterfaceSystem.cs index 0e0688ce988..42605e24821 100644 --- a/Robust.Shared/GameObjects/Systems/SharedUserInterfaceSystem.cs +++ b/Robust.Shared/GameObjects/Systems/SharedUserInterfaceSystem.cs @@ -91,19 +91,6 @@ public override void Initialize() SubscribeLocalEvent(OnActorShutdown); } - /// - /// Enqueues a BUI command to be processed in the next Update call, - /// getting the last available state for the given UserInterfaceComponent at the last state. - /// - private void AddQueued(BoundUserInterface bui, QueuedUpdate type, Entity ent, Enum key) - { - var state = ent.Comp.States.GetValueOrDefault(key); - _queuedBuis.Add((bui, type, state)); - } - - /// - /// Enqueues a BUI command to be processed in the next Update call. - /// private void AddQueued(BoundUserInterface bui, QueuedUpdate type, BoundUserInterfaceState? state = null) { _queuedBuis.Add((bui, type, state)); @@ -305,7 +292,8 @@ private void OnUserInterfaceStartup(Entity ent, ref Comp // PlayerAttachedEvent will catch some of these. foreach (var (key, bui) in ent.Comp.ClientOpenInterfaces) { - AddQueued(bui, QueuedUpdate.Open, ent, key); + var state = ent.Comp.States.GetValueOrDefault(key); + AddQueued(bui, QueuedUpdate.Open, state); } } @@ -566,7 +554,7 @@ private void EnsureClientBui(Entity entity, Enum key, In if (!open) return; - AddQueued(boundUserInterface, QueuedUpdate.Open, entity, key); + AddQueued(boundUserInterface, QueuedUpdate.Open); } /// From e7d5f2e0f2e5a4ce3475a8192cc4a0a7751fb6b0 Mon Sep 17 00:00:00 2001 From: Whatstone Date: Sun, 2 Aug 2026 08:42:23 -0400 Subject: [PATCH 2/3] Revert "Bugfix: SharedUserInterfaceSystem stores and applies BUI states in order. (#6829)" This reverts commit c766e79ef46f6208190fda37d10c3242e2b90282. --- .../Systems/SharedUserInterfaceSystem.cs | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/Robust.Shared/GameObjects/Systems/SharedUserInterfaceSystem.cs b/Robust.Shared/GameObjects/Systems/SharedUserInterfaceSystem.cs index 42605e24821..a476fa08fe4 100644 --- a/Robust.Shared/GameObjects/Systems/SharedUserInterfaceSystem.cs +++ b/Robust.Shared/GameObjects/Systems/SharedUserInterfaceSystem.cs @@ -48,7 +48,7 @@ private enum QueuedUpdate /// /// Defer BUIs during state handling so client doesn't spam a BUI constantly during prediction. /// - private readonly List<(BoundUserInterface bui, QueuedUpdate updateType, BoundUserInterfaceState? state)> _queuedBuis = new(); + private readonly List<(BoundUserInterface bui, QueuedUpdate updateType)> _queuedBuis = new(); public override void Initialize() { @@ -91,9 +91,9 @@ public override void Initialize() SubscribeLocalEvent(OnActorShutdown); } - private void AddQueued(BoundUserInterface bui, QueuedUpdate type, BoundUserInterfaceState? state = null) + private void AddQueued(BoundUserInterface bui, QueuedUpdate type) { - _queuedBuis.Add((bui, type, state)); + _queuedBuis.Add((bui, type)); } /// @@ -292,8 +292,7 @@ private void OnUserInterfaceStartup(Entity ent, ref Comp // PlayerAttachedEvent will catch some of these. foreach (var (key, bui) in ent.Comp.ClientOpenInterfaces) { - var state = ent.Comp.States.GetValueOrDefault(key); - AddQueued(bui, QueuedUpdate.Open, state); + AddQueued(bui, QueuedUpdate.Open); } } @@ -313,7 +312,7 @@ protected void OnUserInterfaceShutdown(Entity ent, ref C DebugTools.Assert(!ent.Comp.Actors.ContainsKey(key)); } - DebugTools.Assert(ent.Comp.ClientOpenInterfaces.Values.All(x => _queuedBuis.Contains((x, QueuedUpdate.Close, null)))); + DebugTools.Assert(ent.Comp.ClientOpenInterfaces.Values.All(x => _queuedBuis.Contains((x, QueuedUpdate.Close)))); } private void OnUserInterfaceGetState(Entity ent, ref ComponentGetState args) @@ -501,7 +500,7 @@ private void OnUserInterfaceHandleState(Entity ent, ref if (!ent.Comp.ClientOpenInterfaces.TryGetValue(key, out var cBui) || !cBui.IsOpened) continue; - AddQueued(cBui, QueuedUpdate.ApplyState, buiState); + AddQueued(cBui, QueuedUpdate.ApplyState); } } @@ -529,7 +528,7 @@ private void EnsureClientBui(Entity entity, Enum key, In // Existing BUI just keep it. if (entity.Comp.ClientOpenInterfaces.TryGetValue(key, out var existing)) { - _queuedBuis.Remove((existing, QueuedUpdate.Close, null)); + _queuedBuis.Remove((existing, QueuedUpdate.Close)); return; } @@ -765,7 +764,11 @@ public void SetUiState(Entity entity, Enum key, BoundUs // Predict the change on client if (state != null && _netManager.IsClient && entity.Comp.ClientOpenInterfaces.TryGetValue(key, out var bui)) { - AddQueued(bui, QueuedUpdate.ApplyState, state); + if (bui.State?.Equals(state) != true) + { + bui.UpdateState(state); + bui.Update(); + } } DirtyField(entity, nameof(UserInterfaceComponent.States)); @@ -1107,7 +1110,7 @@ public override void Update(float frameTime) { if (_timing.IsFirstTimePredicted) { - foreach (var (bui, updateType, state) in _queuedBuis) + foreach (var (bui, updateType) in _queuedBuis) { if (updateType == QueuedUpdate.Open || updateType == QueuedUpdate.ApplyState) { @@ -1120,23 +1123,26 @@ public override void Update(float frameTime) bui.Open(); } - if (state != null) + if (UIQuery.TryComp(bui.Owner, out var uiComp)) { - bui.State = state; - bui.UpdateState(state); - bui.Update(); + if (uiComp.States.TryGetValue(bui.UiKey, out var buiState)) + { + bui.State = buiState; + bui.UpdateState(buiState); + bui.Update(); + } } #if EXCEPTION_TOLERANCE } catch (Exception e) { - var operationType = updateType == QueuedUpdate.Open ? "create" : "update"; Log.Error( - $"Caught exception while attempting to {operationType} a BUI {bui.UiKey} with type {bui.GetType()} on entity {ToPrettyString(bui.Owner)}. Exception: {e}"); + $"Caught exception while attempting to create a BUI {bui.UiKey} with type {bui.GetType()} on entity {ToPrettyString(bui.Owner)}. Exception: {e}"); } #endif } - else // Close BUI + // Close BUI + else { if (UIQuery.TryComp(bui.Owner, out var uiComp)) { From ca17af59a2455e365c6f37c0fc6acdf3a9980a70 Mon Sep 17 00:00:00 2001 From: Whatstone Date: Sun, 2 Aug 2026 08:42:41 -0400 Subject: [PATCH 3/3] Revert "Defer UI operations until UI system runs frame update (#6789)" This reverts commit f44d7e00c3baa672787fa7d8c0bae21240d7f194. --- .../Systems/SharedUserInterfaceSystem.cs | 42 +++++++------------ 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/Robust.Shared/GameObjects/Systems/SharedUserInterfaceSystem.cs b/Robust.Shared/GameObjects/Systems/SharedUserInterfaceSystem.cs index a476fa08fe4..d1a4d829669 100644 --- a/Robust.Shared/GameObjects/Systems/SharedUserInterfaceSystem.cs +++ b/Robust.Shared/GameObjects/Systems/SharedUserInterfaceSystem.cs @@ -34,21 +34,10 @@ public abstract partial class SharedUserInterfaceSystem : EntitySystem private ActorRangeCheckJob _rangeJob; - /// Update type to apply - private enum QueuedUpdate - { - /// Upen a UI - Open, - /// Apply new state to the UI - ApplyState, - /// Close the UI - Close - }; - /// /// Defer BUIs during state handling so client doesn't spam a BUI constantly during prediction. /// - private readonly List<(BoundUserInterface bui, QueuedUpdate updateType)> _queuedBuis = new(); + private readonly List<(BoundUserInterface Bui, bool value)> _queuedBuis = new(); public override void Initialize() { @@ -91,9 +80,9 @@ public override void Initialize() SubscribeLocalEvent(OnActorShutdown); } - private void AddQueued(BoundUserInterface bui, QueuedUpdate type) + private void AddQueued(BoundUserInterface bui, bool value) { - _queuedBuis.Add((bui, type)); + _queuedBuis.Add((bui, value)); } /// @@ -250,7 +239,7 @@ private void CloseUiInternal(Entity ent, Enum key, Enti if (ent.Comp.ClientOpenInterfaces.TryGetValue(key, out var cBui)) { - AddQueued(cBui, QueuedUpdate.Close); + AddQueued(cBui, false); } if (ent.Comp.Actors.Count == 0) @@ -292,7 +281,7 @@ private void OnUserInterfaceStartup(Entity ent, ref Comp // PlayerAttachedEvent will catch some of these. foreach (var (key, bui) in ent.Comp.ClientOpenInterfaces) { - AddQueued(bui, QueuedUpdate.Open); + AddQueued(bui, true); } } @@ -312,7 +301,7 @@ protected void OnUserInterfaceShutdown(Entity ent, ref C DebugTools.Assert(!ent.Comp.Actors.ContainsKey(key)); } - DebugTools.Assert(ent.Comp.ClientOpenInterfaces.Values.All(x => _queuedBuis.Contains((x, QueuedUpdate.Close)))); + DebugTools.Assert(ent.Comp.ClientOpenInterfaces.Values.All(x => _queuedBuis.Contains((x, false)))); } private void OnUserInterfaceGetState(Entity ent, ref ComponentGetState args) @@ -473,7 +462,7 @@ private void OnUserInterfaceHandleState(Entity ent, ref } var bui = ent.Comp.ClientOpenInterfaces[key]; - AddQueued(bui, QueuedUpdate.Close); + AddQueued(bui, false); } } @@ -500,7 +489,9 @@ private void OnUserInterfaceHandleState(Entity ent, ref if (!ent.Comp.ClientOpenInterfaces.TryGetValue(key, out var cBui) || !cBui.IsOpened) continue; - AddQueued(cBui, QueuedUpdate.ApplyState); + cBui.State = buiState; + cBui.UpdateState(buiState); + cBui.Update(); } } @@ -528,7 +519,7 @@ private void EnsureClientBui(Entity entity, Enum key, In // Existing BUI just keep it. if (entity.Comp.ClientOpenInterfaces.TryGetValue(key, out var existing)) { - _queuedBuis.Remove((existing, QueuedUpdate.Close)); + _queuedBuis.Remove((existing, false)); return; } @@ -553,7 +544,7 @@ private void EnsureClientBui(Entity entity, Enum key, In if (!open) return; - AddQueued(boundUserInterface, QueuedUpdate.Open); + AddQueued(boundUserInterface, true); } /// @@ -1110,18 +1101,15 @@ public override void Update(float frameTime) { if (_timing.IsFirstTimePredicted) { - foreach (var (bui, updateType) in _queuedBuis) + foreach (var (bui, open) in _queuedBuis) { - if (updateType == QueuedUpdate.Open || updateType == QueuedUpdate.ApplyState) + if (open) { #if EXCEPTION_TOLERANCE try { #endif - if (updateType == QueuedUpdate.Open) - { - bui.Open(); - } + bui.Open(); if (UIQuery.TryComp(bui.Owner, out var uiComp)) {