diff --git a/Content.IntegrationTests/Pair/TestPair.Cvars.cs b/Content.IntegrationTests/Pair/TestPair.Cvars.cs new file mode 100644 index 0000000000..81df31fc9a --- /dev/null +++ b/Content.IntegrationTests/Pair/TestPair.Cvars.cs @@ -0,0 +1,69 @@ +#nullable enable +using System.Collections.Generic; +using Content.Shared.CCVar; +using Robust.Shared.Configuration; +using Robust.Shared.Utility; + +namespace Content.IntegrationTests.Pair; + +public sealed partial class TestPair +{ + private readonly Dictionary _modifiedClientCvars = new(); + private readonly Dictionary _modifiedServerCvars = new(); + + private void OnServerCvarChanged(CVarChangeInfo args) + { + _modifiedServerCvars.TryAdd(args.Name, args.OldValue); + } + + private void OnClientCvarChanged(CVarChangeInfo args) + { + _modifiedClientCvars.TryAdd(args.Name, args.OldValue); + } + + internal void ClearModifiedCvars() + { + _modifiedClientCvars.Clear(); + _modifiedServerCvars.Clear(); + } + + /// + /// Reverts any cvars that were modified during a test back to their original values. + /// + public async Task RevertModifiedCvars() + { + await Server.WaitPost(() => + { + foreach (var (name, value) in _modifiedServerCvars) + { + if (Server.CfgMan.GetCVar(name).Equals(value)) + continue; + Server.Log.Info($"Resetting cvar {name} to {value}"); + Server.CfgMan.SetCVar(name, value); + } + + // I just love order dependent cvars + if (_modifiedServerCvars.TryGetValue(CCVars.PanicBunkerEnabled.Name, out var panik)) + Server.CfgMan.SetCVar(CCVars.PanicBunkerEnabled.Name, panik); + + }); + + await Client.WaitPost(() => + { + foreach (var (name, value) in _modifiedClientCvars) + { + if (Client.CfgMan.GetCVar(name).Equals(value)) + continue; + + var flags = Client.CfgMan.GetCVarFlags(name); + if (flags.HasFlag(CVar.REPLICATED) && flags.HasFlag(CVar.SERVER)) + continue; + + Client.Log.Info($"Resetting cvar {name} to {value}"); + Client.CfgMan.SetCVar(name, value); + } + }); + + ClearModifiedCvars(); + } +} diff --git a/Content.IntegrationTests/Pair/TestPair.Recycle.cs b/Content.IntegrationTests/Pair/TestPair.Recycle.cs index c0f4b3b745..8d1e425553 100644 --- a/Content.IntegrationTests/Pair/TestPair.Recycle.cs +++ b/Content.IntegrationTests/Pair/TestPair.Recycle.cs @@ -40,6 +40,8 @@ public sealed partial class TestPair : IAsyncDisposable TestMap = null; } + await RevertModifiedCvars(); + var usageTime = Watch.Elapsed; Watch.Restart(); await _testOut.WriteLineAsync($"{nameof(CleanReturnAsync)}: Test borrowed pair {Id} for {usageTime.TotalMilliseconds} ms"); @@ -132,6 +134,7 @@ public sealed partial class TestPair : IAsyncDisposable if (gameTicker.RunLevel != GameRunLevel.PreRoundLobby) { await testOut.WriteLineAsync($"Recycling: {Watch.Elapsed.TotalMilliseconds} ms: Restarting round."); + Server.CfgMan.SetCVar(CCVars.GameDummyTicker, false); Assert.That(gameTicker.DummyTicker, Is.False); Server.CfgMan.SetCVar(CCVars.GameLobbyEnabled, true); await Server.WaitPost(() => gameTicker.RestartRound()); diff --git a/Content.IntegrationTests/Pair/TestPair.cs b/Content.IntegrationTests/Pair/TestPair.cs index 916a94c9c4..7ee5dbd55c 100644 --- a/Content.IntegrationTests/Pair/TestPair.cs +++ b/Content.IntegrationTests/Pair/TestPair.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using Content.Server.GameTicking; using Content.Shared.Players; +using Robust.Shared.Configuration; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Network; @@ -58,6 +59,9 @@ public sealed partial class TestPair (Server, ServerLogHandler) = await PoolManager.GenerateServer(settings, testOut); ActivateContext(testOut); + Client.CfgMan.OnCVarValueChanged += OnClientCvarChanged; + Server.CfgMan.OnCVarValueChanged += OnServerCvarChanged; + if (!settings.NoLoadTestPrototypes) await LoadPrototypes(testPrototypes!); diff --git a/Content.IntegrationTests/PoolManager.cs b/Content.IntegrationTests/PoolManager.cs index 3b49ffcf84..21c93ea8ae 100644 --- a/Content.IntegrationTests/PoolManager.cs +++ b/Content.IntegrationTests/PoolManager.cs @@ -270,6 +270,8 @@ public static partial class PoolManager $"{nameof(GetServerClientPair)}: Retrieving pair {pair.Id} from pool took {poolRetrieveTime.TotalMilliseconds} ms"); await testOut.WriteLineAsync( $"{nameof(GetServerClientPair)}: Returning pair {pair.Id}"); + + pair.ClearModifiedCvars(); pair.Settings = poolSettings; pair.TestHistory.Add(currentTestName); pair.Watch.Restart(); diff --git a/Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs b/Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs index 3a77834b72..ea19a30005 100644 --- a/Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs +++ b/Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs @@ -50,7 +50,6 @@ public sealed class NukeOpsTest var invSys = server.System(); var factionSys = server.System(); - Assert.That(server.CfgMan.GetCVar(CCVars.GridFill), Is.False); server.CfgMan.SetCVar(CCVars.GridFill, true); // Initially in the lobby @@ -200,7 +199,6 @@ public sealed class NukeOpsTest } ticker.SetGamePreset((GamePresetPrototype?)null); - server.CfgMan.SetCVar(CCVars.GridFill, false); await pair.SetAntagPref("NukeopsCommander", false); await pair.CleanReturnAsync(); } diff --git a/Content.Server/Administration/Systems/AdminSystem.cs b/Content.Server/Administration/Systems/AdminSystem.cs index b7ca4e915b..a1a6b33ebc 100644 --- a/Content.Server/Administration/Systems/AdminSystem.cs +++ b/Content.Server/Administration/Systems/AdminSystem.cs @@ -292,6 +292,19 @@ namespace Content.Server.Administration.Systems : _adminManager.ActiveAdmins; var hasAdmins = admins.Any(); + // TODO Fix order dependent Cvars + // Please for the sake of my sanity don't make cvars & order dependent. + // Just make a bool field on the system instead of having some cvars automatically modify other cvars. + // + // I.e., this: + // /sudo cvar game.panic_bunker.enabled true + // /sudo cvar game.panic_bunker.disable_with_admins true + // and this: + // /sudo cvar game.panic_bunker.disable_with_admins true + // /sudo cvar game.panic_bunker.enabled true + // + // should have the same effect, but currently setting the disable_with_admins can modify enabled. + if (hasAdmins && PanicBunker.DisableWithAdmins) { _config.SetCVar(CCVars.PanicBunkerEnabled, false);