* 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
130 lines
5.1 KiB
C#
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();
|
|
}
|
|
}
|