diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyOptionsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyOptionsLogic.cs index 7cd0c3fe15..9ff5f49688 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyOptionsLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyOptionsLogic.cs @@ -101,18 +101,25 @@ namespace OpenRA.Mods.Common.Widgets.Logic } var checkbox = checkboxColumns.Dequeue(); - var optionValue = new CachedTransform( - gs => gs.LobbyOptions[option.Id]); + var optionEnabled = new PredictedCachedTransform( + gs => gs.LobbyOptions[option.Id].IsEnabled); + + var optionLocked = new CachedTransform( + gs => gs.LobbyOptions[option.Id].IsLocked); checkbox.GetText = () => option.Name; if (option.Description != null) checkbox.GetTooltipText = () => option.Description; checkbox.IsVisible = () => true; - checkbox.IsChecked = () => optionValue.Update(orderManager.LobbyInfo.GlobalSettings).IsEnabled; - checkbox.IsDisabled = () => configurationDisabled() || optionValue.Update(orderManager.LobbyInfo.GlobalSettings).IsLocked; - checkbox.OnClick = () => orderManager.IssueOrder(Order.Command( - $"option {option.Id} {!optionValue.Update(orderManager.LobbyInfo.GlobalSettings).IsEnabled}")); + checkbox.IsChecked = () => optionEnabled.Update(orderManager.LobbyInfo.GlobalSettings); + checkbox.IsDisabled = () => configurationDisabled() || optionLocked.Update(orderManager.LobbyInfo.GlobalSettings); + checkbox.OnClick = () => + { + var state = !optionEnabled.Update(orderManager.LobbyInfo.GlobalSettings); + orderManager.IssueOrder(Order.Command($"option {option.Id} {state}")); + optionEnabled.Predict(state); + }; } foreach (var option in allOptions.Where(o => !(o is LobbyBooleanOption))) diff --git a/OpenRA.Mods.Common/Widgets/WidgetUtils.cs b/OpenRA.Mods.Common/Widgets/WidgetUtils.cs index 0bc4e8e512..7bd15944b1 100644 --- a/OpenRA.Mods.Common/Widgets/WidgetUtils.cs +++ b/OpenRA.Mods.Common/Widgets/WidgetUtils.cs @@ -419,4 +419,40 @@ namespace OpenRA.Mods.Common.Widgets return lastOutput; } } + + public class PredictedCachedTransform + { + readonly Func transform; + + bool initialized; + T lastInput; + U lastOutput; + + bool predicted; + U prediction; + + public PredictedCachedTransform(Func transform) + { + this.transform = transform; + } + + public void Predict(U value) + { + predicted = true; + prediction = value; + } + + public U Update(T input) + { + if ((predicted || initialized) && ((input == null && lastInput == null) || (input != null && input.Equals(lastInput)))) + return predicted ? prediction : lastOutput; + + predicted = false; + initialized = true; + lastInput = input; + lastOutput = transform(input); + + return lastOutput; + } + } }