GhostTests.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using System.Numerics;
  2. using Content.IntegrationTests.Pair;
  3. using Content.Shared.Ghost;
  4. using Content.Shared.Mind;
  5. using Content.Shared.Players;
  6. using Robust.Server.GameObjects;
  7. using Robust.Shared.GameObjects;
  8. using Robust.Shared.Map;
  9. using Robust.Shared.Player;
  10. using Robust.UnitTesting;
  11. namespace Content.IntegrationTests.Tests.Minds;
  12. [TestFixture]
  13. public sealed class GhostTests
  14. {
  15. private struct GhostTestData
  16. {
  17. public IEntityManager SEntMan;
  18. public Robust.Server.Player.IPlayerManager SPlayerMan;
  19. public Server.Mind.MindSystem SMindSys;
  20. public SharedTransformSystem STransformSys = default!;
  21. public TestPair Pair = default!;
  22. public readonly TestMapData MapData => Pair.TestMap!;
  23. public readonly RobustIntegrationTest.ServerIntegrationInstance Server => Pair.Server;
  24. public readonly RobustIntegrationTest.ClientIntegrationInstance Client => Pair.Client;
  25. /// <summary>
  26. /// Initial player coordinates. Note that this does not necessarily correspond to the position of the
  27. /// <see cref="Player"/> entity.
  28. /// </summary>
  29. public NetCoordinates PlayerCoords = default!;
  30. public NetEntity Player = default!;
  31. public EntityUid SPlayerEnt = default!;
  32. public ICommonSession ClientSession = default!;
  33. public ICommonSession ServerSession = default!;
  34. public GhostTestData()
  35. {
  36. }
  37. }
  38. private async Task<GhostTestData> SetupData()
  39. {
  40. var data = new GhostTestData
  41. {
  42. // Client is needed to create a session for the ghost system. Creating a dummy session was too difficult.
  43. Pair = await PoolManager.GetServerClient(new PoolSettings
  44. {
  45. DummyTicker = false,
  46. Connected = true,
  47. Dirty = true
  48. })
  49. };
  50. data.SEntMan = data.Pair.Server.ResolveDependency<IServerEntityManager>();
  51. data.SPlayerMan = data.Pair.Server.ResolveDependency<Robust.Server.Player.IPlayerManager>();
  52. data.SMindSys = data.SEntMan.System<Server.Mind.MindSystem>();
  53. data.STransformSys = data.SEntMan.System<SharedTransformSystem>();
  54. // Setup map.
  55. await data.Pair.CreateTestMap();
  56. var test = data.MapData.GridCoords.Offset(new Vector2(0.5f, 0.5f));
  57. data.PlayerCoords = data.SEntMan.GetNetCoordinates(data.STransformSys.WithEntityId(data.MapData.GridCoords.Offset(new Vector2(0.5f, 0.5f)), data.MapData.MapUid));
  58. if (data.Client.Session == null)
  59. Assert.Fail("No player");
  60. data.ClientSession = data.Client.Session!;
  61. data.ServerSession = data.SPlayerMan.GetSessionById(data.ClientSession.UserId);
  62. Entity<MindComponent> mind = default!;
  63. await data.Pair.Server.WaitPost(() =>
  64. {
  65. data.Player = data.SEntMan.GetNetEntity(data.SEntMan.SpawnEntity(null, data.SEntMan.GetCoordinates(data.PlayerCoords)));
  66. mind = data.SMindSys.CreateMind(data.ServerSession.UserId, "DummyPlayerEntity");
  67. data.SPlayerEnt = data.SEntMan.GetEntity(data.Player);
  68. data.SMindSys.TransferTo(mind, data.SPlayerEnt, mind: mind.Comp);
  69. data.Server.PlayerMan.SetAttachedEntity(data.ServerSession, data.SPlayerEnt);
  70. });
  71. await data.Pair.RunTicksSync(5);
  72. Assert.Multiple(() =>
  73. {
  74. Assert.That(data.ServerSession.ContentData()?.Mind, Is.EqualTo(mind.Owner));
  75. Assert.That(data.ServerSession.AttachedEntity, Is.EqualTo(data.SPlayerEnt));
  76. Assert.That(data.ServerSession.AttachedEntity, Is.EqualTo(mind.Comp.CurrentEntity),
  77. "Player is not attached to the mind's current entity.");
  78. Assert.That(data.SEntMan.EntityExists(mind.Comp.OwnedEntity),
  79. "The mind's current entity does not exist");
  80. Assert.That(mind.Comp.VisitingEntity == null || data.SEntMan.EntityExists(mind.Comp.VisitingEntity),
  81. "The minds visited entity does not exist.");
  82. });
  83. Assert.That(data.SPlayerEnt, Is.Not.EqualTo(null));
  84. return data;
  85. }
  86. /// <summary>
  87. /// Test that a ghost gets created when the player entity is deleted.
  88. /// 1. Delete mob
  89. /// 2. Assert is ghost
  90. /// </summary>
  91. [Test]
  92. public async Task TestGridGhostOnDelete()
  93. {
  94. var data = await SetupData();
  95. var oldPosition = data.SEntMan.GetComponent<TransformComponent>(data.SPlayerEnt).Coordinates;
  96. Assert.That(!data.SEntMan.HasComponent<GhostComponent>(data.SPlayerEnt), "Player was initially a ghost?");
  97. // Delete entity
  98. await data.Server.WaitPost(() => data.SEntMan.DeleteEntity(data.SPlayerEnt));
  99. await data.Pair.RunTicksSync(5);
  100. var ghost = data.ServerSession.AttachedEntity!.Value;
  101. Assert.That(data.SEntMan.HasComponent<GhostComponent>(ghost), "Player did not become a ghost");
  102. // Ensure the position is the same
  103. var ghostPosition = data.SEntMan.GetComponent<TransformComponent>(ghost).Coordinates;
  104. Assert.That(ghostPosition, Is.EqualTo(oldPosition));
  105. await data.Pair.CleanReturnAsync();
  106. }
  107. /// <summary>
  108. /// Test that a ghost gets created when the player entity is queue deleted.
  109. /// 1. Delete mob
  110. /// 2. Assert is ghost
  111. /// </summary>
  112. [Test]
  113. public async Task TestGridGhostOnQueueDelete()
  114. {
  115. var data = await SetupData();
  116. var oldPosition = data.SEntMan.GetComponent<TransformComponent>(data.SPlayerEnt).Coordinates;
  117. Assert.That(!data.SEntMan.HasComponent<GhostComponent>(data.SPlayerEnt), "Player was initially a ghost?");
  118. // Delete entity
  119. await data.Server.WaitPost(() => data.SEntMan.QueueDeleteEntity(data.SPlayerEnt));
  120. await data.Pair.RunTicksSync(5);
  121. var ghost = data.ServerSession.AttachedEntity!.Value;
  122. Assert.That(data.SEntMan.HasComponent<GhostComponent>(ghost), "Player did not become a ghost");
  123. // Ensure the position is the same
  124. var ghostPosition = data.SEntMan.GetComponent<TransformComponent>(ghost).Coordinates;
  125. Assert.That(ghostPosition, Is.EqualTo(oldPosition));
  126. await data.Pair.CleanReturnAsync();
  127. }
  128. [Test]
  129. public async Task TestGhostGridNotTerminating()
  130. {
  131. var data = await SetupData();
  132. Assert.DoesNotThrowAsync(async () =>
  133. {
  134. // Delete the grid
  135. await data.Server.WaitPost(() => data.SEntMan.DeleteEntity(data.MapData.Grid.Owner));
  136. });
  137. await data.Pair.RunTicksSync(5);
  138. await data.Pair.CleanReturnAsync();
  139. }
  140. }