TraitorRuleTest.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. using System.Linq;
  2. using Content.Server.Antag.Components;
  3. using Content.Server.GameTicking;
  4. using Content.Server.GameTicking.Rules;
  5. using Content.Server.GameTicking.Rules.Components;
  6. using Content.Server.Mind;
  7. using Content.Server.Roles;
  8. using Content.Shared.GameTicking;
  9. using Content.Shared.GameTicking.Components;
  10. using Content.Shared.Mind;
  11. using Content.Shared.NPC.Systems;
  12. using Content.Shared.Objectives.Components;
  13. using Robust.Shared.GameObjects;
  14. using Robust.Shared.Prototypes;
  15. namespace Content.IntegrationTests.Tests.GameRules;
  16. [TestFixture]
  17. public sealed class TraitorRuleTest
  18. {
  19. private const string TraitorGameRuleProtoId = "Traitor";
  20. private const string TraitorAntagRoleName = "Traitor";
  21. [Test]
  22. public async Task TestTraitorObjectives()
  23. {
  24. await using var pair = await PoolManager.GetServerClient(new PoolSettings()
  25. {
  26. Dirty = true,
  27. DummyTicker = false,
  28. Connected = true,
  29. InLobby = true,
  30. });
  31. var server = pair.Server;
  32. var client = pair.Client;
  33. var entMan = server.EntMan;
  34. var protoMan = server.ProtoMan;
  35. var compFact = server.ResolveDependency<IComponentFactory>();
  36. var ticker = server.System<GameTicker>();
  37. var mindSys = server.System<MindSystem>();
  38. var roleSys = server.System<RoleSystem>();
  39. var factionSys = server.System<NpcFactionSystem>();
  40. var traitorRuleSys = server.System<TraitorRuleSystem>();
  41. // Look up the minimum player count and max total objective difficulty for the game rule
  42. var minPlayers = 1;
  43. var maxDifficulty = 0f;
  44. await server.WaitAssertion(() =>
  45. {
  46. Assert.That(protoMan.TryIndex<EntityPrototype>(TraitorGameRuleProtoId, out var gameRuleEnt),
  47. $"Failed to lookup traitor game rule entity prototype with ID \"{TraitorGameRuleProtoId}\"!");
  48. Assert.That(gameRuleEnt.TryGetComponent<GameRuleComponent>(out var gameRule, compFact),
  49. $"Game rule entity {TraitorGameRuleProtoId} does not have a GameRuleComponent!");
  50. Assert.That(gameRuleEnt.TryGetComponent<AntagRandomObjectivesComponent>(out var randomObjectives, compFact),
  51. $"Game rule entity {TraitorGameRuleProtoId} does not have an AntagRandomObjectivesComponent!");
  52. minPlayers = gameRule.MinPlayers;
  53. maxDifficulty = randomObjectives.MaxDifficulty;
  54. });
  55. // Initially in the lobby
  56. Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.PreRoundLobby));
  57. Assert.That(client.AttachedEntity, Is.Null);
  58. Assert.That(ticker.PlayerGameStatuses[client.User!.Value], Is.EqualTo(PlayerGameStatus.NotReadyToPlay));
  59. // Add enough dummy players for the game rule
  60. var dummies = await pair.Server.AddDummySessions(minPlayers);
  61. await pair.RunTicksSync(5);
  62. // Initially, the players have no attached entities
  63. Assert.That(pair.Player?.AttachedEntity, Is.Null);
  64. Assert.That(dummies.All(x => x.AttachedEntity == null));
  65. // Opt-in the player for the traitor role
  66. await pair.SetAntagPreference(TraitorAntagRoleName, true);
  67. // Add the game rule
  68. TraitorRuleComponent traitorRule = null;
  69. await server.WaitPost(() =>
  70. {
  71. var gameRuleEnt = ticker.AddGameRule(TraitorGameRuleProtoId);
  72. Assert.That(entMan.TryGetComponent<TraitorRuleComponent>(gameRuleEnt, out traitorRule));
  73. // Ready up
  74. ticker.ToggleReadyAll(true);
  75. Assert.That(ticker.PlayerGameStatuses.Values.All(x => x == PlayerGameStatus.ReadyToPlay));
  76. // Start the round
  77. ticker.StartRound();
  78. // Force traitor mode to start (skip the delay)
  79. ticker.StartGameRule(gameRuleEnt);
  80. });
  81. await pair.RunTicksSync(10);
  82. // Game should have started
  83. Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.InRound));
  84. Assert.That(ticker.PlayerGameStatuses.Values.All(x => x == PlayerGameStatus.JoinedGame));
  85. Assert.That(client.EntMan.EntityExists(client.AttachedEntity));
  86. // Check the player and dummies are spawned
  87. var dummyEnts = dummies.Select(x => x.AttachedEntity ?? default).ToArray();
  88. var player = pair.Player!.AttachedEntity!.Value;
  89. Assert.That(entMan.EntityExists(player));
  90. Assert.That(dummyEnts.All(entMan.EntityExists));
  91. // Make sure the player is a traitor.
  92. var mind = mindSys.GetMind(player)!.Value;
  93. Assert.That(roleSys.MindIsAntagonist(mind));
  94. Assert.That(factionSys.IsMember(player, "Syndicate"), Is.True);
  95. Assert.That(factionSys.IsMember(player, "NanoTrasen"), Is.False);
  96. Assert.That(traitorRule.TotalTraitors, Is.EqualTo(1));
  97. Assert.That(traitorRule.TraitorMinds[0], Is.EqualTo(mind));
  98. // Check total objective difficulty
  99. Assert.That(entMan.TryGetComponent<MindComponent>(mind, out var mindComp));
  100. var totalDifficulty = mindComp.Objectives.Sum(o => entMan.GetComponent<ObjectiveComponent>(o).Difficulty);
  101. Assert.That(totalDifficulty, Is.AtMost(maxDifficulty),
  102. $"MaxDifficulty exceeded! Objectives: {string.Join(", ", mindComp.Objectives.Select(o => FormatObjective(o, entMan)))}");
  103. Assert.That(mindComp.Objectives, Is.Not.Empty,
  104. $"No objectives assigned!");
  105. await pair.CleanReturnAsync();
  106. }
  107. private static string FormatObjective(Entity<ObjectiveComponent> entity, IEntityManager entMan)
  108. {
  109. var meta = entMan.GetComponent<MetaDataComponent>(entity);
  110. var objective = entMan.GetComponent<ObjectiveComponent>(entity);
  111. return $"{meta.EntityName} ({objective.Difficulty})";
  112. }
  113. }