FailAndStartPresetTest.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #nullable enable
  2. using Content.Server.GameTicking;
  3. using Content.Server.GameTicking.Presets;
  4. using Content.Shared.CCVar;
  5. using Content.Shared.GameTicking;
  6. using Content.Shared.GameTicking.Components;
  7. using Robust.Shared.GameObjects;
  8. namespace Content.IntegrationTests.Tests.GameRules;
  9. [TestFixture]
  10. public sealed class FailAndStartPresetTest
  11. {
  12. [TestPrototypes]
  13. private const string Prototypes = @"
  14. - type: gamePreset
  15. id: TestPreset
  16. alias:
  17. - nukeops
  18. name: Test Preset
  19. description: """"
  20. showInVote: false
  21. rules:
  22. - TestRule
  23. - type: gamePreset
  24. id: TestPresetTenPlayers
  25. alias:
  26. - nukeops
  27. name: Test Preset 10 players
  28. description: """"
  29. showInVote: false
  30. rules:
  31. - TestRuleTenPlayers
  32. - type: entity
  33. id: TestRule
  34. parent: BaseGameRule
  35. categories: [ GameRules ]
  36. components:
  37. - type: GameRule
  38. minPlayers: 0
  39. - type: TestRule
  40. - type: entity
  41. id: TestRuleTenPlayers
  42. parent: BaseGameRule
  43. categories: [ GameRules ]
  44. components:
  45. - type: GameRule
  46. minPlayers: 10
  47. - type: TestRule
  48. ";
  49. /// <summary>
  50. /// Test that a nuke ops gamemode can start after failing to start once.
  51. /// </summary>
  52. [Test]
  53. public async Task FailAndStartTest()
  54. {
  55. await using var pair = await PoolManager.GetServerClient(new PoolSettings
  56. {
  57. Dirty = true,
  58. DummyTicker = false,
  59. Connected = true,
  60. InLobby = true
  61. });
  62. var server = pair.Server;
  63. var client = pair.Client;
  64. var entMan = server.EntMan;
  65. var ticker = server.System<GameTicker>();
  66. server.System<TestRuleSystem>().Run = true;
  67. Assert.That(server.CfgMan.GetCVar(CCVars.GridFill), Is.False);
  68. Assert.That(server.CfgMan.GetCVar(CCVars.GameLobbyFallbackEnabled), Is.True);
  69. Assert.That(server.CfgMan.GetCVar(CCVars.GameLobbyDefaultPreset), Is.EqualTo("secret"));
  70. server.CfgMan.SetCVar(CCVars.GridFill, true);
  71. server.CfgMan.SetCVar(CCVars.GameLobbyFallbackEnabled, false);
  72. server.CfgMan.SetCVar(CCVars.GameLobbyDefaultPreset, "TestPreset");
  73. // Initially in the lobby
  74. Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.PreRoundLobby));
  75. Assert.That(client.AttachedEntity, Is.Null);
  76. Assert.That(ticker.PlayerGameStatuses[client.User!.Value], Is.EqualTo(PlayerGameStatus.NotReadyToPlay));
  77. // Try to start nukeops without readying up
  78. await pair.WaitCommand("setgamepreset TestPresetTenPlayers");
  79. await pair.WaitCommand("startround");
  80. await pair.RunTicksSync(10);
  81. // Game should not have started
  82. Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.PreRoundLobby));
  83. Assert.That(ticker.PlayerGameStatuses[client.User!.Value], Is.EqualTo(PlayerGameStatus.NotReadyToPlay));
  84. Assert.That(!client.EntMan.EntityExists(client.AttachedEntity));
  85. var player = pair.Player!.AttachedEntity;
  86. Assert.That(!entMan.EntityExists(player));
  87. // Ready up and start nukeops
  88. await pair.WaitClientCommand("toggleready True");
  89. Assert.That(ticker.PlayerGameStatuses[client.User!.Value], Is.EqualTo(PlayerGameStatus.ReadyToPlay));
  90. await pair.WaitCommand("setgamepreset TestPreset");
  91. await pair.WaitCommand("startround");
  92. await pair.RunTicksSync(10);
  93. // Game should have started
  94. Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.InRound));
  95. Assert.That(ticker.PlayerGameStatuses[client.User!.Value], Is.EqualTo(PlayerGameStatus.JoinedGame));
  96. Assert.That(client.EntMan.EntityExists(client.AttachedEntity));
  97. player = pair.Player!.AttachedEntity!.Value;
  98. Assert.That(entMan.EntityExists(player));
  99. ticker.SetGamePreset((GamePresetPrototype?) null);
  100. server.CfgMan.SetCVar(CCVars.GridFill, false);
  101. server.CfgMan.SetCVar(CCVars.GameLobbyFallbackEnabled, true);
  102. server.CfgMan.SetCVar(CCVars.GameLobbyDefaultPreset, "secret");
  103. server.System<TestRuleSystem>().Run = false;
  104. await pair.CleanReturnAsync();
  105. }
  106. }
  107. public sealed class TestRuleSystem : EntitySystem
  108. {
  109. public bool Run;
  110. public override void Initialize()
  111. {
  112. SubscribeLocalEvent<RoundStartAttemptEvent>(OnRoundStartAttempt);
  113. }
  114. private void OnRoundStartAttempt(RoundStartAttemptEvent args)
  115. {
  116. if (!Run)
  117. return;
  118. if (args.Forced || args.Cancelled)
  119. return;
  120. var query = EntityQueryEnumerator<TestRuleComponent, GameRuleComponent>();
  121. while (query.MoveNext(out _, out _, out var gameRule))
  122. {
  123. var minPlayers = gameRule.MinPlayers;
  124. if (!gameRule.CancelPresetOnTooFewPlayers)
  125. continue;
  126. if (args.Players.Length >= minPlayers)
  127. continue;
  128. args.Cancel();
  129. }
  130. }
  131. }
  132. [RegisterComponent]
  133. public sealed partial class TestRuleComponent : Component;