Files
tbd-station-14/Content.IntegrationTests/Tests/Minds/GhostRoleTests.cs
ShadowCommander a985c5e83e Fix ghosts getting spawned in nullspace (#27617)
* Add tests for ghost spawn position

* Make ghosts spawn immediately

* Format mind system

* Move ghost spawning to GhostSystem

* Spawn ghost on grid or map

This fixes the ghosts being attached the parent entity instead of the grid.

* Move logging out of the ghost system

* Make round start observer spawn using GhostSystem

* Move GameTicker ghost spawning to GhostSystem

Moved the more robust character name selection code over.
Moved the TimeOfDeath code over.
Added canReturn logic.

* Add overrides and default for ghost spawn coordinates

* Add warning log to ghost spawn fail

* Clean up test

* Dont spawn ghost on map delete

* Minor changes to the role test

* Fix role test failing to spawn ghost

It was failing the map check due to using Nullspace

* Fix ghost tests when running in parallel

Not sure what happened, but it seems to be because they were running simultaneously and overwriting values.

* Clean up ghost tests

* Test that map deletion does not spawn ghosts

* Spawn ghost on the next available map

* Disallow spawning on deleted maps

* Fix map deletion ghost test

* Cleanup
2024-05-11 11:03:40 -04:00

130 lines
5.1 KiB
C#

#nullable enable
using System.Linq;
using Content.IntegrationTests.Pair;
using Content.Server.Ghost.Roles;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Players;
using Content.Shared.Ghost;
using Content.Shared.Mind;
using Content.Shared.Players;
using Robust.Shared.Console;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
namespace Content.IntegrationTests.Tests.Minds;
[TestFixture]
public sealed class GhostRoleTests
{
[TestPrototypes]
private const string Prototypes = @"
- type: entity
id: GhostRoleTestEntity
components:
- type: MindContainer
- type: GhostRole
- type: GhostTakeoverAvailable
";
/// <summary>
/// This is a simple test that just checks if a player can take a ghost role and then regain control of their
/// original entity without encountering errors.
/// </summary>
[Test]
public async Task TakeRoleAndReturn()
{
await using var pair = await PoolManager.GetServerClient(new PoolSettings
{
Dirty = true,
DummyTicker = false,
Connected = true
});
var server = pair.Server;
var client = pair.Client;
var mapData = await pair.CreateTestMap();
var entMan = server.ResolveDependency<IEntityManager>();
var sPlayerMan = server.ResolveDependency<Robust.Server.Player.IPlayerManager>();
var conHost = client.ResolveDependency<IConsoleHost>();
var mindSystem = entMan.System<SharedMindSystem>();
var session = sPlayerMan.Sessions.Single();
var originalMindId = session.ContentData()!.Mind!.Value;
// Spawn player entity & attach
EntityUid originalMob = default;
await server.WaitPost(() =>
{
originalMob = entMan.SpawnEntity(null, mapData.GridCoords);
mindSystem.TransferTo(originalMindId, originalMob, true);
});
// Check player got attached.
await pair.RunTicksSync(10);
Assert.That(session.AttachedEntity, Is.EqualTo(originalMob));
var originalMind = entMan.GetComponent<MindComponent>(originalMindId);
Assert.That(originalMind.OwnedEntity, Is.EqualTo(originalMob));
Assert.That(originalMind.VisitingEntity, Is.Null);
// Use the ghost command
conHost.ExecuteCommand("ghost");
await pair.RunTicksSync(10);
var ghost = session.AttachedEntity;
Assert.That(entMan.HasComponent<GhostComponent>(ghost));
Assert.That(ghost, Is.Not.EqualTo(originalMob));
Assert.That(session.ContentData()?.Mind, Is.EqualTo(originalMindId));
Assert.That(originalMind.OwnedEntity, Is.EqualTo(originalMob), $"Original mob: {originalMob}, Ghost: {ghost}");
Assert.That(originalMind.VisitingEntity, Is.EqualTo(ghost));
// Spawn ghost takeover entity.
EntityUid ghostRole = default;
await server.WaitPost(() => ghostRole = entMan.SpawnEntity("GhostRoleTestEntity", mapData.GridCoords));
// Take the ghost role
await server.WaitPost(() =>
{
var id = entMan.GetComponent<GhostRoleComponent>(ghostRole).Identifier;
entMan.EntitySysManager.GetEntitySystem<GhostRoleSystem>().Takeover(session, id);
});
// Check player got attached to ghost role.
await pair.RunTicksSync(10);
var newMindId = session.ContentData()!.Mind!.Value;
var newMind = entMan.GetComponent<MindComponent>(newMindId);
Assert.That(newMindId, Is.Not.EqualTo(originalMindId));
Assert.That(session.AttachedEntity, Is.EqualTo(ghostRole));
Assert.That(newMind.OwnedEntity, Is.EqualTo(ghostRole));
Assert.That(newMind.VisitingEntity, Is.Null);
// Original mind should be unaffected, but the ghost will have deleted itself.
Assert.That(originalMind.OwnedEntity, Is.EqualTo(originalMob));
Assert.That(originalMind.VisitingEntity, Is.Null);
Assert.That(entMan.Deleted(ghost));
// Ghost again.
conHost.ExecuteCommand("ghost");
await pair.RunTicksSync(10);
var otherGhost = session.AttachedEntity;
Assert.That(entMan.HasComponent<GhostComponent>(otherGhost));
Assert.That(otherGhost, Is.Not.EqualTo(originalMob));
Assert.That(otherGhost, Is.Not.EqualTo(ghostRole));
Assert.That(session.ContentData()?.Mind, Is.EqualTo(newMindId));
Assert.That(newMind.OwnedEntity, Is.EqualTo(ghostRole));
Assert.That(newMind.VisitingEntity, Is.EqualTo(session.AttachedEntity));
// Next, control the original entity again:
await server.WaitPost(() => mindSystem.SetUserId(originalMindId, session.UserId));
await pair.RunTicksSync(10);
Assert.That(session.AttachedEntity, Is.EqualTo(originalMob));
Assert.That(originalMind.OwnedEntity, Is.EqualTo(originalMob));
Assert.That(originalMind.VisitingEntity, Is.Null);
// the ghost-role mind is unaffected, though the ghost will have deleted itself
Assert.That(newMind.OwnedEntity, Is.EqualTo(ghostRole));
Assert.That(newMind.VisitingEntity, Is.Null);
Assert.That(entMan.Deleted(otherGhost));
await pair.CleanReturnAsync();
}
}