Skip to content

Commit c766e79

Browse files
authored
Bugfix: SharedUserInterfaceSystem stores and applies BUI states in order. (space-wizards#6829)
* store intermediate bui states * exception printout, remove redundant check * Set state on Open * trygetvalue defaults, you dingus * fix string interpolation bug * queue in SetUiState * queue in SetUiState regardless * TryGetValue->GetValueOrDefault
1 parent 2c5cd42 commit c766e79

1 file changed

Lines changed: 17 additions & 23 deletions

File tree

Robust.Shared/GameObjects/Systems/SharedUserInterfaceSystem.cs

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ private enum QueuedUpdate
4848
/// <summary>
4949
/// Defer BUIs during state handling so client doesn't spam a BUI constantly during prediction.
5050
/// </summary>
51-
private readonly List<(BoundUserInterface bui, QueuedUpdate updateType)> _queuedBuis = new();
51+
private readonly List<(BoundUserInterface bui, QueuedUpdate updateType, BoundUserInterfaceState? state)> _queuedBuis = new();
5252

5353
public override void Initialize()
5454
{
@@ -91,9 +91,9 @@ public override void Initialize()
9191
SubscribeLocalEvent<UserInterfaceUserComponent, ComponentShutdown>(OnActorShutdown);
9292
}
9393

94-
private void AddQueued(BoundUserInterface bui, QueuedUpdate type)
94+
private void AddQueued(BoundUserInterface bui, QueuedUpdate type, BoundUserInterfaceState? state = null)
9595
{
96-
_queuedBuis.Add((bui, type));
96+
_queuedBuis.Add((bui, type, state));
9797
}
9898

9999
/// <summary>
@@ -292,7 +292,8 @@ private void OnUserInterfaceStartup(Entity<UserInterfaceComponent> ent, ref Comp
292292
// PlayerAttachedEvent will catch some of these.
293293
foreach (var (key, bui) in ent.Comp.ClientOpenInterfaces)
294294
{
295-
AddQueued(bui, QueuedUpdate.Open);
295+
var state = ent.Comp.States.GetValueOrDefault(key);
296+
AddQueued(bui, QueuedUpdate.Open, state);
296297
}
297298
}
298299

@@ -312,7 +313,7 @@ protected void OnUserInterfaceShutdown(Entity<UserInterfaceComponent> ent, ref C
312313
DebugTools.Assert(!ent.Comp.Actors.ContainsKey(key));
313314
}
314315

315-
DebugTools.Assert(ent.Comp.ClientOpenInterfaces.Values.All(x => _queuedBuis.Contains((x, QueuedUpdate.Close))));
316+
DebugTools.Assert(ent.Comp.ClientOpenInterfaces.Values.All(x => _queuedBuis.Contains((x, QueuedUpdate.Close, null))));
316317
}
317318

318319
private void OnUserInterfaceGetState(Entity<UserInterfaceComponent> ent, ref ComponentGetState args)
@@ -500,7 +501,7 @@ private void OnUserInterfaceHandleState(Entity<UserInterfaceComponent> ent, ref
500501
if (!ent.Comp.ClientOpenInterfaces.TryGetValue(key, out var cBui) || !cBui.IsOpened)
501502
continue;
502503

503-
AddQueued(cBui, QueuedUpdate.ApplyState);
504+
AddQueued(cBui, QueuedUpdate.ApplyState, buiState);
504505
}
505506
}
506507

@@ -528,7 +529,7 @@ private void EnsureClientBui(Entity<UserInterfaceComponent> entity, Enum key, In
528529
// Existing BUI just keep it.
529530
if (entity.Comp.ClientOpenInterfaces.TryGetValue(key, out var existing))
530531
{
531-
_queuedBuis.Remove((existing, QueuedUpdate.Close));
532+
_queuedBuis.Remove((existing, QueuedUpdate.Close, null));
532533
return;
533534
}
534535

@@ -764,11 +765,7 @@ public void SetUiState(Entity<UserInterfaceComponent?> entity, Enum key, BoundUs
764765
// Predict the change on client
765766
if (state != null && _netManager.IsClient && entity.Comp.ClientOpenInterfaces.TryGetValue(key, out var bui))
766767
{
767-
if (bui.State?.Equals(state) != true)
768-
{
769-
bui.UpdateState(state);
770-
bui.Update();
771-
}
768+
AddQueued(bui, QueuedUpdate.ApplyState, state);
772769
}
773770

774771
DirtyField(entity, nameof(UserInterfaceComponent.States));
@@ -1110,7 +1107,7 @@ public override void Update(float frameTime)
11101107
{
11111108
if (_timing.IsFirstTimePredicted)
11121109
{
1113-
foreach (var (bui, updateType) in _queuedBuis)
1110+
foreach (var (bui, updateType, state) in _queuedBuis)
11141111
{
11151112
if (updateType == QueuedUpdate.Open || updateType == QueuedUpdate.ApplyState)
11161113
{
@@ -1123,26 +1120,23 @@ public override void Update(float frameTime)
11231120
bui.Open();
11241121
}
11251122

1126-
if (UIQuery.TryComp(bui.Owner, out var uiComp))
1123+
if (state != null)
11271124
{
1128-
if (uiComp.States.TryGetValue(bui.UiKey, out var buiState))
1129-
{
1130-
bui.State = buiState;
1131-
bui.UpdateState(buiState);
1132-
bui.Update();
1133-
}
1125+
bui.State = state;
1126+
bui.UpdateState(state);
1127+
bui.Update();
11341128
}
11351129
#if EXCEPTION_TOLERANCE
11361130
}
11371131
catch (Exception e)
11381132
{
1133+
var operationType = updateType == QueuedUpdate.Open ? "create" : "update";
11391134
Log.Error(
1140-
$"Caught exception while attempting to create a BUI {bui.UiKey} with type {bui.GetType()} on entity {ToPrettyString(bui.Owner)}. Exception: {e}");
1135+
$"Caught exception while attempting to {operationType} a BUI {bui.UiKey} with type {bui.GetType()} on entity {ToPrettyString(bui.Owner)}. Exception: {e}");
11411136
}
11421137
#endif
11431138
}
1144-
// Close BUI
1145-
else
1139+
else // Close BUI
11461140
{
11471141
if (UIQuery.TryComp(bui.Owner, out var uiComp))
11481142
{

0 commit comments

Comments
 (0)