diff --git a/Content.IntegrationTests/Tests/MindEntityDeletionTest.cs b/Content.IntegrationTests/Tests/MindEntityDeletionTest.cs new file mode 100644 index 0000000000..acbe780035 --- /dev/null +++ b/Content.IntegrationTests/Tests/MindEntityDeletionTest.cs @@ -0,0 +1,161 @@ +using System.Linq; +using System.Threading.Tasks; +using Content.Server.Mobs; +using Content.Server.Players; +using NUnit.Framework; +using Robust.Server.Interfaces.GameObjects; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Map; +using Robust.Shared.Maths; + +namespace Content.IntegrationTests.Tests +{ + // Tests various scenarios of deleting the entity that a player's mind is connected to. + [TestFixture] + public class MindEntityDeletionTest : ContentIntegrationTest + { + [Test] + public async Task TestDeleteVisiting() + { + var (_, server) = await StartConnectedServerDummyTickerClientPair(); + + IEntity playerEnt = null; + IEntity visitEnt = null; + Mind mind = null; + server.Assert(() => + { + var player = IoCManager.Resolve().GetAllPlayers().Single(); + + var mapMan = IoCManager.Resolve(); + var entMgr = IoCManager.Resolve(); + + mapMan.CreateNewMapEntity(MapId.Nullspace); + + playerEnt = entMgr.SpawnEntity(null, MapCoordinates.Nullspace); + visitEnt = entMgr.SpawnEntity(null, MapCoordinates.Nullspace); + + mind = new Mind(player.SessionId); + player.ContentData().Mind = mind; + + mind.TransferTo(playerEnt); + mind.Visit(visitEnt); + + Assert.That(player.AttachedEntity, Is.EqualTo(visitEnt)); + Assert.That(mind.VisitingEntity, Is.EqualTo(visitEnt)); + }); + + server.RunTicks(1); + + server.Assert(() => + { + visitEnt.Delete(); + + Assert.That(mind.VisitingEntity, Is.Null); + + // This used to throw so make sure it doesn't. + playerEnt.Delete(); + }); + + await server.WaitIdleAsync(); + } + + [Test] + public async Task TestGhostOnDelete() + { + // Has to be a non-dummy ticker so we have a proper map. + var (_, server) = await StartConnectedServerClientPair(); + + IEntity playerEnt = null; + Mind mind = null; + server.Assert(() => + { + var player = IoCManager.Resolve().GetAllPlayers().Single(); + + var mapMan = IoCManager.Resolve(); + var entMgr = IoCManager.Resolve(); + + mapMan.CreateNewMapEntity(MapId.Nullspace); + + playerEnt = entMgr.SpawnEntity(null, MapCoordinates.Nullspace); + + mind = new Mind(player.SessionId); + player.ContentData().Mind = mind; + + mind.TransferTo(playerEnt); + + Assert.That(mind.CurrentEntity, Is.EqualTo(playerEnt)); + }); + + server.RunTicks(1); + + server.Post(() => + { + playerEnt.Delete(); + }); + + server.RunTicks(1); + + server.Assert(() => + { + Assert.That(mind.CurrentEntity.IsValid(), Is.True); + }); + + await server.WaitIdleAsync(); + } + + [Test] + public async Task TestGhostOnDeleteMap() + { + // Has to be a non-dummy ticker so we have a proper map. + var (_, server) = await StartConnectedServerClientPair(); + + IEntity playerEnt = null; + Mind mind = null; + MapId map = default; + server.Assert(() => + { + var player = IoCManager.Resolve().GetAllPlayers().Single(); + + var mapMan = IoCManager.Resolve(); + + map = mapMan.CreateMap(); + var grid = mapMan.CreateGrid(map); + + var entMgr = IoCManager.Resolve(); + + mapMan.CreateNewMapEntity(MapId.Nullspace); + + playerEnt = entMgr.SpawnEntity(null, new GridCoordinates(Vector2.Zero, grid.Index)); + + mind = new Mind(player.SessionId); + player.ContentData().Mind = mind; + + mind.TransferTo(playerEnt); + + Assert.That(mind.CurrentEntity, Is.EqualTo(playerEnt)); + }); + + server.RunTicks(1); + + server.Post(() => + { + var mapMan = IoCManager.Resolve(); + + mapMan.DeleteMap(map); + }); + + server.RunTicks(1); + + server.Assert(() => + { + Assert.That(mind.CurrentEntity.IsValid(), Is.True); + Assert.That(mind.CurrentEntity, Is.Not.EqualTo(playerEnt)); + }); + + await server.WaitIdleAsync(); + } + } +}