MindTests.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. #nullable enable
  2. using System.Linq;
  3. using Content.Server.Ghost.Roles;
  4. using Content.Server.Ghost.Roles.Components;
  5. using Content.Server.Mind.Commands;
  6. using Content.Server.Roles;
  7. using Content.Shared.Damage;
  8. using Content.Shared.Damage.Prototypes;
  9. using Content.Shared.FixedPoint;
  10. using Content.Shared.Mind;
  11. using Content.Shared.Mind.Components;
  12. using Content.Shared.Players;
  13. using Content.Shared.Roles;
  14. using Content.Shared.Roles.Jobs;
  15. using Robust.Server.Console;
  16. using Robust.Server.GameObjects;
  17. using Robust.Server.Player;
  18. using Robust.Shared.GameObjects;
  19. using Robust.Shared.Map;
  20. using Robust.Shared.Prototypes;
  21. namespace Content.IntegrationTests.Tests.Minds;
  22. [TestFixture]
  23. public sealed partial class MindTests
  24. {
  25. [TestPrototypes]
  26. private const string Prototypes = @"
  27. - type: entity
  28. id: MindTestEntityDamageable
  29. components:
  30. - type: MindContainer
  31. - type: Damageable
  32. damageContainer: Biological
  33. - type: Body
  34. prototype: Human
  35. requiredLegs: 2
  36. - type: MobState
  37. - type: MobThresholds
  38. thresholds:
  39. 0: Alive
  40. 200: Dead
  41. - type: Destructible
  42. thresholds:
  43. - trigger:
  44. !type:DamageTypeTrigger
  45. damageType: Blunt
  46. damage: 400
  47. behaviors:
  48. - !type:GibBehavior { }
  49. ";
  50. [Test]
  51. public async Task TestCreateAndTransferMindToNewEntity()
  52. {
  53. await using var pair = await PoolManager.GetServerClient();
  54. var server = pair.Server;
  55. var entMan = server.ResolveDependency<IServerEntityManager>();
  56. await server.WaitAssertion(() =>
  57. {
  58. var mindSystem = entMan.EntitySysManager.GetEntitySystem<SharedMindSystem>();
  59. var entity = entMan.SpawnEntity(null, new MapCoordinates());
  60. var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
  61. var mind = mindSystem.CreateMind(null);
  62. Assert.That(mind.Comp.UserId, Is.EqualTo(null));
  63. mindSystem.TransferTo(mind, entity, mind: mind);
  64. Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind.Owner));
  65. });
  66. await pair.CleanReturnAsync();
  67. }
  68. [Test]
  69. public async Task TestReplaceMind()
  70. {
  71. await using var pair = await PoolManager.GetServerClient();
  72. var server = pair.Server;
  73. var entMan = server.ResolveDependency<IServerEntityManager>();
  74. await server.WaitAssertion(() =>
  75. {
  76. var mindSystem = entMan.EntitySysManager.GetEntitySystem<SharedMindSystem>();
  77. var entity = entMan.SpawnEntity(null, new MapCoordinates());
  78. var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
  79. var mindId = mindSystem.CreateMind(null).Owner;
  80. mindSystem.TransferTo(mindId, entity);
  81. Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId));
  82. var mind2 = mindSystem.CreateMind(null).Owner;
  83. mindSystem.TransferTo(mind2, entity);
  84. Assert.Multiple(() =>
  85. {
  86. Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind2));
  87. var mind = entMan.GetComponent<MindComponent>(mindId);
  88. Assert.That(mind.OwnedEntity, Is.Not.EqualTo(entity));
  89. });
  90. });
  91. await pair.CleanReturnAsync();
  92. }
  93. [Test]
  94. public async Task TestEntityDeadWhenGibbed()
  95. {
  96. await using var pair = await PoolManager.GetServerClient();
  97. var server = pair.Server;
  98. var entMan = server.ResolveDependency<IServerEntityManager>();
  99. var protoMan = server.ResolveDependency<IPrototypeManager>();
  100. EntityUid entity = default!;
  101. MindContainerComponent mindContainerComp = default!;
  102. EntityUid mindId = default!;
  103. var mindSystem = entMan.EntitySysManager.GetEntitySystem<SharedMindSystem>();
  104. var damageableSystem = entMan.EntitySysManager.GetEntitySystem<DamageableSystem>();
  105. await server.WaitAssertion(() =>
  106. {
  107. entity = entMan.SpawnEntity("MindTestEntityDamageable", new MapCoordinates());
  108. mindContainerComp = entMan.EnsureComponent<MindContainerComponent>(entity);
  109. mindId = mindSystem.CreateMind(null);
  110. mindSystem.TransferTo(mindId, entity);
  111. Assert.Multiple(() =>
  112. {
  113. Assert.That(mindSystem.GetMind(entity, mindContainerComp), Is.EqualTo(mindId));
  114. var mind = entMan.GetComponent<MindComponent>(mindId);
  115. Assert.That(!mindSystem.IsCharacterDeadPhysically(mind));
  116. });
  117. });
  118. await pair.RunTicksSync(5);
  119. await server.WaitAssertion(() =>
  120. {
  121. var damageable = entMan.GetComponent<DamageableComponent>(entity);
  122. if (!protoMan.TryIndex<DamageTypePrototype>("Blunt", out var prototype))
  123. {
  124. return;
  125. }
  126. damageableSystem.SetDamage(entity, damageable, new DamageSpecifier(prototype, FixedPoint2.New(401)));
  127. Assert.That(mindSystem.GetMind(entity, mindContainerComp), Is.EqualTo(mindId));
  128. });
  129. await pair.RunTicksSync(5);
  130. await server.WaitAssertion(() =>
  131. {
  132. var mind = entMan.GetComponent<MindComponent>(mindId);
  133. Assert.That(mindSystem.IsCharacterDeadPhysically(mind));
  134. });
  135. await pair.CleanReturnAsync();
  136. }
  137. [Test]
  138. public async Task TestMindTransfersToOtherEntity()
  139. {
  140. await using var pair = await PoolManager.GetServerClient();
  141. var server = pair.Server;
  142. var entMan = server.ResolveDependency<IServerEntityManager>();
  143. await server.WaitAssertion(() =>
  144. {
  145. var mindSystem = entMan.EntitySysManager.GetEntitySystem<SharedMindSystem>();
  146. var entity = entMan.SpawnEntity(null, new MapCoordinates());
  147. var targetEntity = entMan.SpawnEntity(null, new MapCoordinates());
  148. var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
  149. entMan.EnsureComponent<MindContainerComponent>(targetEntity);
  150. var mind = mindSystem.CreateMind(null).Owner;
  151. mindSystem.TransferTo(mind, entity);
  152. Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind));
  153. mindSystem.TransferTo(mind, targetEntity);
  154. Assert.Multiple(() =>
  155. {
  156. Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(null));
  157. Assert.That(mindSystem.GetMind(targetEntity), Is.EqualTo(mind));
  158. });
  159. });
  160. await pair.CleanReturnAsync();
  161. }
  162. [Test]
  163. public async Task TestOwningPlayerCanBeChanged()
  164. {
  165. await using var pair = await PoolManager.GetServerClient(new PoolSettings
  166. {
  167. Connected = true,
  168. DummyTicker = false
  169. });
  170. var server = pair.Server;
  171. var entMan = server.ResolveDependency<IServerEntityManager>();
  172. await pair.RunTicksSync(5);
  173. var mindSystem = entMan.EntitySysManager.GetEntitySystem<SharedMindSystem>();
  174. var originalMind = GetMind(pair);
  175. var userId = originalMind.Comp.UserId;
  176. EntityUid mindId = default!;
  177. MindComponent mind = default!;
  178. await server.WaitAssertion(() =>
  179. {
  180. var entity = entMan.SpawnEntity(null, new MapCoordinates());
  181. var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
  182. entMan.DirtyEntity(entity);
  183. mindId = mindSystem.CreateMind(null);
  184. mind = entMan.GetComponent<MindComponent>(mindId);
  185. mindSystem.TransferTo(mindId, entity);
  186. Assert.Multiple(() =>
  187. {
  188. Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId));
  189. Assert.That(mindComp.HasMind);
  190. });
  191. });
  192. await pair.RunTicksSync(5);
  193. await server.WaitAssertion(() =>
  194. {
  195. mindSystem.SetUserId(mindId, userId);
  196. Assert.Multiple(() =>
  197. {
  198. Assert.That(mind.UserId, Is.EqualTo(userId));
  199. Assert.That(originalMind.Comp.UserId, Is.EqualTo(null));
  200. });
  201. mindSystem.SetUserId(originalMind.Id, userId);
  202. Assert.Multiple(() =>
  203. {
  204. Assert.That(mind.UserId, Is.EqualTo(null));
  205. Assert.That(originalMind.Comp.UserId, Is.EqualTo(userId));
  206. });
  207. });
  208. await pair.RunTicksSync(5);
  209. await pair.CleanReturnAsync();
  210. }
  211. [Test]
  212. public async Task TestAddRemoveHasRoles()
  213. {
  214. await using var pair = await PoolManager.GetServerClient();
  215. var server = pair.Server;
  216. var entMan = server.ResolveDependency<IServerEntityManager>();
  217. await server.WaitAssertion(() =>
  218. {
  219. var mindSystem = entMan.EntitySysManager.GetEntitySystem<SharedMindSystem>();
  220. var roleSystem = entMan.EntitySysManager.GetEntitySystem<SharedRoleSystem>();
  221. var entity = entMan.SpawnEntity(null, new MapCoordinates());
  222. var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
  223. var mindId = mindSystem.CreateMind(null).Owner;
  224. var mind = entMan.EnsureComponent<MindComponent>(mindId);
  225. Assert.That(mind.UserId, Is.EqualTo(null));
  226. mindSystem.TransferTo(mindId, entity);
  227. Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId));
  228. Assert.Multiple(() =>
  229. {
  230. Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId), Is.False);
  231. Assert.That(roleSystem.MindHasRole<JobRoleComponent>(mindId), Is.False);
  232. });
  233. var traitorRole = "MindRoleTraitor";
  234. roleSystem.MindAddRole(mindId, traitorRole);
  235. Assert.Multiple(() =>
  236. {
  237. Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId));
  238. Assert.That(roleSystem.MindHasRole<JobRoleComponent>(mindId), Is.False);
  239. });
  240. var jobRole = "";
  241. roleSystem.MindAddJobRole(mindId, jobPrototype:jobRole);
  242. Assert.Multiple(() =>
  243. {
  244. Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId));
  245. Assert.That(roleSystem.MindHasRole<JobRoleComponent>(mindId));
  246. });
  247. roleSystem.MindRemoveRole<TraitorRoleComponent>(mindId);
  248. Assert.Multiple(() =>
  249. {
  250. Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId), Is.False);
  251. Assert.That(roleSystem.MindHasRole<JobRoleComponent>(mindId));
  252. });
  253. roleSystem.MindRemoveRole<JobRoleComponent>(mindId);
  254. Assert.Multiple(() =>
  255. {
  256. Assert.That(roleSystem.MindHasRole<TraitorRoleComponent>(mindId), Is.False);
  257. Assert.That(roleSystem.MindHasRole<JobRoleComponent>(mindId), Is.False);
  258. });
  259. });
  260. await pair.CleanReturnAsync();
  261. }
  262. [Test]
  263. public async Task TestPlayerCanGhost()
  264. {
  265. // Client is needed to spawn session
  266. await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true, DummyTicker = false });
  267. var server = pair.Server;
  268. var entMan = server.ResolveDependency<IServerEntityManager>();
  269. var playerMan = server.ResolveDependency<IPlayerManager>();
  270. var mindSystem = entMan.EntitySysManager.GetEntitySystem<SharedMindSystem>();
  271. EntityUid entity = default!;
  272. EntityUid mindId = default!;
  273. MindComponent mind = default!;
  274. var player = playerMan.Sessions.Single();
  275. await server.WaitAssertion(() =>
  276. {
  277. entity = entMan.SpawnEntity(null, new MapCoordinates());
  278. var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
  279. mindId = mindSystem.CreateMind(player.UserId, "Mindy McThinker");
  280. mind = entMan.GetComponent<MindComponent>(mindId);
  281. Assert.That(mind.UserId, Is.EqualTo(player.UserId));
  282. mindSystem.TransferTo(mindId, entity);
  283. Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId));
  284. });
  285. await pair.RunTicksSync(5);
  286. await server.WaitAssertion(() =>
  287. {
  288. entMan.DeleteEntity(entity);
  289. });
  290. await pair.RunTicksSync(5);
  291. EntityUid mob = default!;
  292. EntityUid mobMindId = default!;
  293. MindComponent mobMind = default!;
  294. await server.WaitAssertion(() =>
  295. {
  296. Assert.That(mind.OwnedEntity, Is.Not.Null);
  297. mob = entMan.SpawnEntity(null, new MapCoordinates());
  298. MakeSentientCommand.MakeSentient(mob, entMan);
  299. mobMindId = mindSystem.CreateMind(player.UserId, "Mindy McThinker the Second");
  300. mobMind = entMan.GetComponent<MindComponent>(mobMindId);
  301. mindSystem.SetUserId(mobMindId, player.UserId);
  302. mindSystem.TransferTo(mobMindId, mob);
  303. });
  304. await pair.RunTicksSync(5);
  305. await server.WaitAssertion(() =>
  306. {
  307. var mId = player.ContentData()?.Mind!.Value;
  308. Assert.That(mId, Is.Not.Null);
  309. Assert.That(mId, Is.Not.EqualTo(default(EntityUid)));
  310. var m = entMan.GetComponent<MindComponent>(mId!.Value);
  311. Assert.Multiple(() =>
  312. {
  313. Assert.That(m!.OwnedEntity, Is.EqualTo(mob));
  314. Assert.That(mId, Is.Not.EqualTo(mindId));
  315. });
  316. });
  317. await pair.CleanReturnAsync();
  318. }
  319. [Test]
  320. public async Task TestGhostDoesNotInfiniteLoop()
  321. {
  322. await using var pair = await PoolManager.GetServerClient(new PoolSettings
  323. {
  324. DummyTicker = false,
  325. Connected = true,
  326. Dirty = true
  327. });
  328. var server = pair.Server;
  329. var entMan = server.ResolveDependency<IServerEntityManager>();
  330. var playerMan = server.ResolveDependency<IPlayerManager>();
  331. var serverConsole = server.ResolveDependency<IServerConsoleHost>();
  332. //EntityUid entity = default!;
  333. EntityUid ghostRole = default!;
  334. EntityUid ghost = default!;
  335. EntityUid mindId = default!;
  336. MindComponent mind = default!;
  337. var player = playerMan.Sessions.Single();
  338. await server.WaitAssertion(() =>
  339. {
  340. // entity = entMan.SpawnEntity(null, new MapCoordinates());
  341. // var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
  342. // mind = mindSystem.CreateMind(player.UserId, "Mindy McThinker");
  343. //
  344. // Assert.That(mind.UserId, Is.EqualTo(player.UserId));
  345. //
  346. // mindSystem.TransferTo(mind, entity);
  347. // Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind));
  348. var data = player.ContentData();
  349. Assert.That(data?.Mind, Is.Not.EqualTo(null));
  350. mindId = data!.Mind!.Value;
  351. mind = entMan.GetComponent<MindComponent>(mindId);
  352. Assert.That(mind.OwnedEntity, Is.Not.Null);
  353. ghostRole = entMan.SpawnEntity("GhostRoleTestEntity", MapCoordinates.Nullspace);
  354. });
  355. await pair.RunTicksSync(20);
  356. await server.WaitAssertion(() =>
  357. {
  358. serverConsole.ExecuteCommand(player, "aghost");
  359. });
  360. await pair.RunTicksSync(20);
  361. await server.WaitAssertion(() =>
  362. {
  363. var id = entMan.GetComponent<GhostRoleComponent>(ghostRole).Identifier;
  364. entMan.EntitySysManager.GetEntitySystem<GhostRoleSystem>().Takeover(player, id);
  365. });
  366. await pair.RunTicksSync(20);
  367. await server.WaitAssertion(() =>
  368. {
  369. var data = entMan.GetComponent<MindComponent>(player.ContentData()!.Mind!.Value);
  370. Assert.That(data.OwnedEntity, Is.EqualTo(ghostRole));
  371. serverConsole.ExecuteCommand(player, "aghost");
  372. Assert.That(player.AttachedEntity, Is.Not.Null);
  373. ghost = player.AttachedEntity!.Value;
  374. });
  375. await pair.RunTicksSync(20);
  376. await server.WaitAssertion(() =>
  377. {
  378. Assert.That(player.AttachedEntity, Is.Not.Null);
  379. Assert.That(player.AttachedEntity!.Value, Is.EqualTo(ghost));
  380. });
  381. await pair.CleanReturnAsync();
  382. }
  383. }