From 3fa99b8abf41463cf414c2931321e69467c73848 Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Wed, 21 Jun 2023 14:11:58 +1200 Subject: [PATCH] Slight mind test cleanup (#17521) --- .../Tests/Minds/GhostRoleTests.cs | 33 ++--- .../Tests/Minds/MindEntityDeletionTest.cs | 126 ------------------ ...stTests.cs => MindTests.EntityDeletion.cs} | 117 +++++++++++++--- .../Tests/Minds/MindTests.Helpers.cs | 5 +- .../Tests/Minds/MindTests.ReconnectTests.cs | 6 +- .../Tests/Minds/MindTests.cs | 7 +- Content.Server/Mind/MindSystem.cs | 10 +- 7 files changed, 115 insertions(+), 189 deletions(-) delete mode 100644 Content.IntegrationTests/Tests/Minds/MindEntityDeletionTest.cs rename Content.IntegrationTests/Tests/Minds/{GhostTests.cs => MindTests.EntityDeletion.cs} (67%) diff --git a/Content.IntegrationTests/Tests/Minds/GhostRoleTests.cs b/Content.IntegrationTests/Tests/Minds/GhostRoleTests.cs index bd6ce81d1a..cb6f224628 100644 --- a/Content.IntegrationTests/Tests/Minds/GhostRoleTests.cs +++ b/Content.IntegrationTests/Tests/Minds/GhostRoleTests.cs @@ -1,4 +1,5 @@ #nullable enable +using System.Linq; using System.Threading.Tasks; using Content.Server.Ghost.Roles; using Content.Server.Ghost.Roles.Components; @@ -16,12 +17,7 @@ public sealed class GhostRoleTests { private const string Prototypes = @" - type: entity - id: GhostRoleTestEntity_Player - components: - - type: MindContainer - -- type: entity - id: GhostRoleTestEntity_Role + id: GhostRoleTestEntity components: - type: MindContainer - type: GhostRole @@ -42,36 +38,29 @@ public sealed class GhostRoleTests var entMan = server.ResolveDependency(); var sPlayerMan = server.ResolveDependency(); var conHost = client.ResolveDependency(); - var cPlayerMan = client.ResolveDependency(); var mindSystem = entMan.System(); - - // Get player data - if (cPlayerMan.LocalPlayer?.Session == null) - Assert.Fail("No player"); - - var clientSession = cPlayerMan.LocalPlayer!.Session!; - var session = sPlayerMan.GetSessionByUserId(clientSession.UserId); + var session = sPlayerMan.ServerSessions.Single(); // Spawn player entity & attach EntityUid originalMob = default; await server.WaitPost(() => { - originalMob = entMan.SpawnEntity("GhostRoleTestEntity_Player", MapCoordinates.Nullspace); + originalMob = entMan.SpawnEntity(null, MapCoordinates.Nullspace); mindSystem.TransferTo(session.ContentData()!.Mind!, originalMob, true); }); // Check player got attached. await PoolManager.RunTicksSync(pairTracker.Pair, 10); - Assert.That(cPlayerMan.LocalPlayer.ControlledEntity, Is.EqualTo(originalMob)); + Assert.That(session.AttachedEntity, Is.EqualTo(originalMob)); // Use the ghost command conHost.ExecuteCommand("ghost"); await PoolManager.RunTicksSync(pairTracker.Pair, 10); - Assert.That(cPlayerMan.LocalPlayer.ControlledEntity, Is.Not.EqualTo(originalMob)); + Assert.That(session.AttachedEntity, Is.Not.EqualTo(originalMob)); // Spawn ghost takeover entity. EntityUid ghostRole = default; - await server.WaitPost(() => ghostRole = entMan.SpawnEntity("GhostRoleTestEntity_Role", MapCoordinates.Nullspace)); + await server.WaitPost(() => ghostRole = entMan.SpawnEntity("GhostRoleTestEntity", MapCoordinates.Nullspace)); // Take the ghost role await server.WaitPost(() => @@ -82,13 +71,13 @@ public sealed class GhostRoleTests // Check player got attached to ghost role. await PoolManager.RunTicksSync(pairTracker.Pair, 10); - Assert.That(cPlayerMan.LocalPlayer.ControlledEntity, Is.EqualTo(ghostRole)); + Assert.That(session.AttachedEntity, Is.EqualTo(ghostRole)); // Ghost again. conHost.ExecuteCommand("ghost"); await PoolManager.RunTicksSync(pairTracker.Pair, 10); - Assert.That(cPlayerMan.LocalPlayer.ControlledEntity, Is.Not.EqualTo(originalMob)); - Assert.That(cPlayerMan.LocalPlayer.ControlledEntity, Is.Not.EqualTo(ghostRole)); + Assert.That(session.AttachedEntity, Is.Not.EqualTo(originalMob)); + Assert.That(session.AttachedEntity, Is.Not.EqualTo(ghostRole)); // Next, control the original entity again: await server.WaitPost(() => @@ -96,7 +85,7 @@ public sealed class GhostRoleTests mindSystem.TransferTo(session.ContentData()!.Mind!, originalMob, true); }); await PoolManager.RunTicksSync(pairTracker.Pair, 10); - Assert.That(cPlayerMan.LocalPlayer.ControlledEntity, Is.EqualTo(originalMob)); + Assert.That(session.AttachedEntity, Is.EqualTo(originalMob)); await pairTracker.CleanReturnAsync(); } diff --git a/Content.IntegrationTests/Tests/Minds/MindEntityDeletionTest.cs b/Content.IntegrationTests/Tests/Minds/MindEntityDeletionTest.cs deleted file mode 100644 index 49626d8082..0000000000 --- a/Content.IntegrationTests/Tests/Minds/MindEntityDeletionTest.cs +++ /dev/null @@ -1,126 +0,0 @@ -#nullable enable -using System.Linq; -using System.Threading.Tasks; -using Content.Server.Mind; -using Content.Server.Players; -using NUnit.Framework; -using Robust.Server.GameObjects; -using Robust.Server.Player; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Map; -using Robust.Shared.Maths; - -namespace Content.IntegrationTests.Tests.Minds -{ - // Tests various scenarios of deleting the entity that a player's mind is connected to. - [TestFixture] - public sealed class MindEntityDeletionTest - { - // This test will do the following: - // - spawn a player - // - visit some entity - // - delete the entity being visited - // - assert that player returns to original entity - [Test] - public async Task TestDeleteVisiting() - { - await using var pairTracker = await PoolManager.GetServerClient(); - var server = pairTracker.Pair.Server; - - var entMan = server.ResolveDependency(); - var playerMan = server.ResolveDependency(); - var mapManager = server.ResolveDependency(); - - var mindSystem = entMan.EntitySysManager.GetEntitySystem(); - - EntityUid playerEnt = default; - EntityUid visitEnt = default; - Mind mind = default!; - var map = await PoolManager.CreateTestMap(pairTracker); - - await server.WaitAssertion(() => - { - var player = playerMan.ServerSessions.Single(); - var pos = new MapCoordinates(Vector2.Zero, map.MapId); - - playerEnt = entMan.SpawnEntity(null, pos); - visitEnt = entMan.SpawnEntity(null, pos); - - mind = mindSystem.CreateMind(player.UserId); - mindSystem.TransferTo(mind, playerEnt); - mindSystem.Visit(mind, visitEnt); - - Assert.That(player.AttachedEntity, Is.EqualTo(visitEnt)); - Assert.That(mind.VisitingEntity, Is.EqualTo(visitEnt)); - }); - - await PoolManager.RunTicksSync(pairTracker.Pair, 5); - await server.WaitPost(() => entMan.DeleteEntity(visitEnt)); - await PoolManager.RunTicksSync(pairTracker.Pair, 5); - - Assert.IsNull(mind.VisitingEntity); - Assert.That(entMan.EntityExists(mind.OwnedEntity)); - Assert.That(mind.OwnedEntity, Is.EqualTo(playerEnt)); - - // This used to throw so make sure it doesn't. - await server.WaitPost(() => entMan.DeleteEntity(mind.OwnedEntity!.Value)); - await PoolManager.RunTicksSync(pairTracker.Pair, 5); - - await server.WaitPost(() => mapManager.DeleteMap(map.MapId)); - await pairTracker.CleanReturnAsync(); - } - - // this is a variant of TestGhostOnDelete that just deletes the whole map. - [Test] - public async Task TestGhostOnDeleteMap() - { - await using var pairTracker = await PoolManager.GetServerClient(); - var server = pairTracker.Pair.Server; - var testMap = await PoolManager.CreateTestMap(pairTracker); - var coordinates = testMap.GridCoords; - - var entMan = server.ResolveDependency(); - var mapManager = server.ResolveDependency(); - var playerMan = server.ResolveDependency(); - var player = playerMan.ServerSessions.Single(); - - var mindSystem = entMan.EntitySysManager.GetEntitySystem(); - - var map = await PoolManager.CreateTestMap(pairTracker); - - EntityUid playerEnt = default; - Mind mind = default!; - await server.WaitAssertion(() => - { - playerEnt = entMan.SpawnEntity(null, coordinates); - mind = player.ContentData()!.Mind!; - mindSystem.TransferTo(mind, playerEnt); - - Assert.That(mind.CurrentEntity, Is.EqualTo(playerEnt)); - }); - - await PoolManager.RunTicksSync(pairTracker.Pair, 5); - - await server.WaitPost(() => - { - mapManager.DeleteMap(testMap.MapId); - }); - - await PoolManager.RunTicksSync(pairTracker.Pair, 5); - - await server.WaitAssertion(() => - { - Assert.That(entMan.EntityExists(mind.CurrentEntity!.Value), Is.True); - Assert.That(mind.CurrentEntity, Is.Not.EqualTo(playerEnt)); - }); - - await server.WaitPost(() => - { - mapManager.DeleteMap(map.MapId); - }); - - await pairTracker.CleanReturnAsync(); - } - } -} diff --git a/Content.IntegrationTests/Tests/Minds/GhostTests.cs b/Content.IntegrationTests/Tests/Minds/MindTests.EntityDeletion.cs similarity index 67% rename from Content.IntegrationTests/Tests/Minds/GhostTests.cs rename to Content.IntegrationTests/Tests/Minds/MindTests.EntityDeletion.cs index 5d9ea2b30b..e23ca32756 100644 --- a/Content.IntegrationTests/Tests/Minds/GhostTests.cs +++ b/Content.IntegrationTests/Tests/Minds/MindTests.EntityDeletion.cs @@ -1,9 +1,7 @@ -using System.Linq; +using System.Linq; using System.Threading.Tasks; -using Content.Server.GameTicking; using Content.Server.Ghost.Components; using Content.Server.Mind; -using Content.Server.Mind.Components; using Content.Server.Players; using NUnit.Framework; using Robust.Server.Console; @@ -11,13 +9,101 @@ using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.GameObjects; using Robust.Shared.Map; -using Robust.Shared.Network; namespace Content.IntegrationTests.Tests.Minds; -[TestFixture] -public sealed class GhostTests +// Tests various scenarios where an entity that is associated with a player's mind is deleted. +public sealed partial class MindTests { + // This test will do the following: + // - spawn a player + // - visit some entity + // - delete the entity being visited + // - assert that player returns to original entity + [Test] + public async Task TestDeleteVisiting() + { + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; + + var entMan = server.ResolveDependency(); + var playerMan = server.ResolveDependency(); + + var mindSystem = entMan.EntitySysManager.GetEntitySystem(); + + EntityUid playerEnt = default; + EntityUid visitEnt = default; + Mind mind = default!; + await server.WaitAssertion(() => + { + var player = playerMan.ServerSessions.Single(); + + playerEnt = entMan.SpawnEntity(null, MapCoordinates.Nullspace); + visitEnt = entMan.SpawnEntity(null, MapCoordinates.Nullspace); + + mind = mindSystem.CreateMind(player.UserId); + mindSystem.TransferTo(mind, playerEnt); + mindSystem.Visit(mind, visitEnt); + + Assert.That(player.AttachedEntity, Is.EqualTo(visitEnt)); + Assert.That(mind.VisitingEntity, Is.EqualTo(visitEnt)); + }); + + await PoolManager.RunTicksSync(pairTracker.Pair, 5); + await server.WaitPost(() => entMan.DeleteEntity(visitEnt)); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); + + Assert.IsNull(mind.VisitingEntity); + Assert.That(entMan.EntityExists(mind.OwnedEntity)); + Assert.That(mind.OwnedEntity, Is.EqualTo(playerEnt)); + + // This used to throw so make sure it doesn't. + await server.WaitPost(() => entMan.DeleteEntity(mind.OwnedEntity!.Value)); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); + + await pairTracker.CleanReturnAsync(); + } + + // this is a variant of TestGhostOnDelete that just deletes the whole map. + [Test] + public async Task TestGhostOnDeleteMap() + { + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; + var testMap = await PoolManager.CreateTestMap(pairTracker); + var coordinates = testMap.GridCoords; + + var entMan = server.ResolveDependency(); + var mapManager = server.ResolveDependency(); + var playerMan = server.ResolveDependency(); + var player = playerMan.ServerSessions.Single(); + + var mindSystem = entMan.EntitySysManager.GetEntitySystem(); + + EntityUid playerEnt = default; + Mind mind = default!; + await server.WaitAssertion(() => + { + playerEnt = entMan.SpawnEntity(null, coordinates); + mind = player.ContentData()!.Mind!; + mindSystem.TransferTo(mind, playerEnt); + + Assert.That(mind.CurrentEntity, Is.EqualTo(playerEnt)); + }); + + await PoolManager.RunTicksSync(pairTracker.Pair, 5); + await server.WaitPost(() => mapManager.DeleteMap(testMap.MapId)); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); + + await server.WaitAssertion(() => + { + Assert.That(entMan.EntityExists(mind.CurrentEntity!.Value), Is.True); + Assert.That(mind.CurrentEntity, Is.Not.EqualTo(playerEnt)); + }); + + await pairTracker.CleanReturnAsync(); + } + /// /// Test that a ghost gets created when the player entity is deleted. /// 1. Delete mob @@ -27,7 +113,7 @@ public sealed class GhostTests public async Task TestGhostOnDelete() { // Client is needed to spawn session - await using var pairTracker = await PoolManager.GetServerClient(); + await using var pairTracker = await SetupPair(); var server = pairTracker.Pair.Server; var entMan = server.ResolveDependency(); @@ -35,21 +121,13 @@ public sealed class GhostTests IPlayerSession player = playerMan.ServerSessions.Single(); - await server.WaitAssertion(() => - { - Assert.That(player.AttachedEntity, Is.Not.EqualTo(null)); - entMan.DeleteEntity(player.AttachedEntity!.Value); - }); + Assert.That(!entMan.HasComponent(player.AttachedEntity), "Player was initially a ghost?"); + // Delete entity + await server.WaitPost(() => entMan.DeleteEntity(player.AttachedEntity!.Value)); await PoolManager.RunTicksSync(pairTracker.Pair, 5); - await server.WaitAssertion(() => - { - // Is player a ghost? - Assert.That(player.AttachedEntity, Is.Not.EqualTo(null)); - var entity = player.AttachedEntity!.Value; - Assert.That(entMan.HasComponent(entity)); - }); + Assert.That(entMan.HasComponent(player.AttachedEntity), "Player did not become a ghost"); await pairTracker.CleanReturnAsync(); } @@ -72,7 +150,6 @@ public sealed class GhostTests var entMan = server.ResolveDependency(); var playerMan = server.ResolveDependency(); - var gameTicker = entMan.EntitySysManager.GetEntitySystem(); var mindSystem = entMan.EntitySysManager.GetEntitySystem(); IPlayerSession player = playerMan.ServerSessions.Single(); diff --git a/Content.IntegrationTests/Tests/Minds/MindTests.Helpers.cs b/Content.IntegrationTests/Tests/Minds/MindTests.Helpers.cs index bff534a547..51d451451a 100644 --- a/Content.IntegrationTests/Tests/Minds/MindTests.Helpers.cs +++ b/Content.IntegrationTests/Tests/Minds/MindTests.Helpers.cs @@ -15,7 +15,6 @@ using IPlayerManager = Robust.Server.Player.IPlayerManager; namespace Content.IntegrationTests.Tests.Minds; // This partial class contains misc helper functions for other tests. -[TestFixture] public sealed partial class MindTests { /// @@ -23,7 +22,7 @@ public sealed partial class MindTests /// public async Task SetupPair() { - var pairTracker = await PoolManager.GetServerClient(new PoolSettings{ ExtraPrototypes = Prototypes }); + var pairTracker = await PoolManager.GetServerClient(); var pair = pairTracker.Pair; var entMan = pair.Server.ResolveDependency(); @@ -35,7 +34,7 @@ public sealed partial class MindTests EntityUid entity = default; await pair.Server.WaitPost(() => { - entity = entMan.SpawnEntity("MindTestEntity", MapCoordinates.Nullspace); + entity = entMan.SpawnEntity(null, MapCoordinates.Nullspace); mindSys.TransferTo(mindSys.CreateMind(player.UserId), entity); }); diff --git a/Content.IntegrationTests/Tests/Minds/MindTests.ReconnectTests.cs b/Content.IntegrationTests/Tests/Minds/MindTests.ReconnectTests.cs index 031955b416..b9727a7d23 100644 --- a/Content.IntegrationTests/Tests/Minds/MindTests.ReconnectTests.cs +++ b/Content.IntegrationTests/Tests/Minds/MindTests.ReconnectTests.cs @@ -9,7 +9,6 @@ using Robust.Shared.Map; namespace Content.IntegrationTests.Tests.Minds; -[TestFixture] public sealed partial class MindTests { // This test will do the following: @@ -92,7 +91,6 @@ public sealed partial class MindTests { await using var pairTracker = await SetupPair(); var pair = pairTracker.Pair; - var entMan = pair.Server.ResolveDependency(); var mind = GetMind(pair); @@ -119,10 +117,8 @@ public sealed partial class MindTests { await using var pairTracker = await SetupPair(); var pair = pairTracker.Pair; - var entMan = pair.Server.ResolveDependency(); var mindSys = entMan.System(); - await PoolManager.RunTicksSync(pair, 5); var mind = GetMind(pair); // Make player visit a new mob @@ -130,7 +126,7 @@ public sealed partial class MindTests EntityUid visiting = default; await pair.Server.WaitAssertion(() => { - visiting = entMan.SpawnEntity("MindTestEntity", MapCoordinates.Nullspace); + visiting = entMan.SpawnEntity(null, MapCoordinates.Nullspace); mindSys.Visit(mind, visiting); }); await PoolManager.RunTicksSync(pair, 5); diff --git a/Content.IntegrationTests/Tests/Minds/MindTests.cs b/Content.IntegrationTests/Tests/Minds/MindTests.cs index 57a4a9d510..e1c07850ef 100644 --- a/Content.IntegrationTests/Tests/Minds/MindTests.cs +++ b/Content.IntegrationTests/Tests/Minds/MindTests.cs @@ -32,14 +32,9 @@ public sealed partial class MindTests { private const string Prototypes = @" - type: entity - id: MindTestEntity - components: - - type: MindContainer - -- type: entity - parent: MindTestEntity id: MindTestEntityDamageable components: + - type: MindContainer - type: Damageable damageContainer: Biological - type: Body diff --git a/Content.Server/Mind/MindSystem.cs b/Content.Server/Mind/MindSystem.cs index 18420d3702..044193a6ae 100644 --- a/Content.Server/Mind/MindSystem.cs +++ b/Content.Server/Mind/MindSystem.cs @@ -390,14 +390,10 @@ public sealed class MindSystem : EntitySystem if (entity != null) { - if (!TryComp(entity.Value, out component)) - { - component = AddComp(entity.Value); - } - else if (component.HasMind) - { + component = EnsureComp(entity.Value); + + if (component.HasMind) _gameTicker.OnGhostAttempt(component.Mind, false); - } if (TryComp(entity.Value, out var actor)) {