#nullable enable using System.Linq; using Content.Server.Ghost.Roles; using Content.Server.Ghost.Roles.Components; using Content.Server.Mind; using Content.Shared.Damage; using Content.Shared.Damage.Components; using Content.Shared.Damage.Prototypes; using Content.Shared.Damage.Systems; using Content.Shared.FixedPoint; using Content.Shared.Mind; using Content.Shared.Mind.Components; using Content.Shared.Players; using Content.Shared.Roles; using Content.Shared.Roles.Components; using Robust.Server.Console; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.GameObjects; using Robust.Shared.Map; using Robust.Shared.Prototypes; namespace Content.IntegrationTests.Tests.Minds; [TestFixture] public sealed partial class MindTests { private static readonly ProtoId BluntDamageType = "Blunt"; [TestPrototypes] private const string Prototypes = @" - type: entity id: MindTestEntityDamageable components: - type: MindContainer - type: Damageable damageContainer: Biological - type: Body prototype: Human requiredLegs: 2 - type: MobState - type: MobThresholds thresholds: 0: Alive 200: Dead - type: Destructible thresholds: - trigger: !type:DamageTypeTrigger damageType: Blunt damage: 400 behaviors: - !type:GibBehavior { } "; [Test] public async Task TestCreateAndTransferMindToNewEntity() { await using var pair = await PoolManager.GetServerClient(); var server = pair.Server; var entMan = server.ResolveDependency(); await server.WaitAssertion(() => { var mindSystem = entMan.EntitySysManager.GetEntitySystem(); var entity = entMan.SpawnEntity(null, new MapCoordinates()); var mindComp = entMan.EnsureComponent(entity); var mind = mindSystem.CreateMind(null); Assert.That(mind.Comp.UserId, Is.EqualTo(null)); mindSystem.TransferTo(mind, entity, mind: mind); Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind.Owner)); }); await pair.CleanReturnAsync(); } [Test] public async Task TestReplaceMind() { await using var pair = await PoolManager.GetServerClient(); var server = pair.Server; var entMan = server.ResolveDependency(); await server.WaitAssertion(() => { var mindSystem = entMan.EntitySysManager.GetEntitySystem(); var entity = entMan.SpawnEntity(null, new MapCoordinates()); var mindComp = entMan.EnsureComponent(entity); var mindId = mindSystem.CreateMind(null).Owner; mindSystem.TransferTo(mindId, entity); Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId)); var mind2 = mindSystem.CreateMind(null).Owner; mindSystem.TransferTo(mind2, entity); Assert.Multiple(() => { Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind2)); var mind = entMan.GetComponent(mindId); Assert.That(mind.OwnedEntity, Is.Not.EqualTo(entity)); }); }); await pair.CleanReturnAsync(); } [Test] public async Task TestEntityDeadWhenGibbed() { await using var pair = await PoolManager.GetServerClient(); var server = pair.Server; var entMan = server.ResolveDependency(); var protoMan = server.ResolveDependency(); EntityUid entity = default!; MindContainerComponent mindContainerComp = default!; EntityUid mindId = default!; var mindSystem = entMan.EntitySysManager.GetEntitySystem(); var damageableSystem = entMan.EntitySysManager.GetEntitySystem(); await server.WaitAssertion(() => { entity = entMan.SpawnEntity("MindTestEntityDamageable", new MapCoordinates()); mindContainerComp = entMan.EnsureComponent(entity); mindId = mindSystem.CreateMind(null); mindSystem.TransferTo(mindId, entity); Assert.Multiple(() => { Assert.That(mindSystem.GetMind(entity, mindContainerComp), Is.EqualTo(mindId)); var mind = entMan.GetComponent(mindId); Assert.That(!mindSystem.IsCharacterDeadPhysically(mind)); }); }); await pair.RunTicksSync(5); await server.WaitAssertion(() => { var damageable = entMan.GetComponent(entity); var prototype = protoMan.Index(BluntDamageType); damageableSystem.SetDamage((entity, damageable), new DamageSpecifier(prototype, FixedPoint2.New(401))); Assert.That(mindSystem.GetMind(entity, mindContainerComp), Is.EqualTo(mindId)); }); await pair.RunTicksSync(5); await server.WaitAssertion(() => { var mind = entMan.GetComponent(mindId); Assert.That(mindSystem.IsCharacterDeadPhysically(mind)); }); await pair.CleanReturnAsync(); } [Test] public async Task TestMindTransfersToOtherEntity() { await using var pair = await PoolManager.GetServerClient(); var server = pair.Server; var entMan = server.ResolveDependency(); await server.WaitAssertion(() => { var mindSystem = entMan.EntitySysManager.GetEntitySystem(); var entity = entMan.SpawnEntity(null, new MapCoordinates()); var targetEntity = entMan.SpawnEntity(null, new MapCoordinates()); var mindComp = entMan.EnsureComponent(entity); entMan.EnsureComponent(targetEntity); var mind = mindSystem.CreateMind(null).Owner; mindSystem.TransferTo(mind, entity); Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind)); mindSystem.TransferTo(mind, targetEntity); Assert.Multiple(() => { Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(null)); Assert.That(mindSystem.GetMind(targetEntity), Is.EqualTo(mind)); }); }); await pair.CleanReturnAsync(); } [Test] public async Task TestOwningPlayerCanBeChanged() { await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true, DummyTicker = false }); var server = pair.Server; var entMan = server.ResolveDependency(); await pair.RunTicksSync(5); var mindSystem = entMan.EntitySysManager.GetEntitySystem(); var originalMind = GetMind(pair); var userId = originalMind.Comp.UserId; EntityUid mindId = default!; MindComponent mind = default!; await server.WaitAssertion(() => { var entity = entMan.SpawnEntity(null, new MapCoordinates()); var mindComp = entMan.EnsureComponent(entity); entMan.DirtyEntity(entity); mindId = mindSystem.CreateMind(null); mind = entMan.GetComponent(mindId); mindSystem.TransferTo(mindId, entity); Assert.Multiple(() => { Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId)); Assert.That(mindComp.HasMind); }); }); await pair.RunTicksSync(5); await server.WaitAssertion(() => { mindSystem.SetUserId(mindId, userId); Assert.Multiple(() => { Assert.That(mind.UserId, Is.EqualTo(userId)); Assert.That(originalMind.Comp.UserId, Is.EqualTo(null)); }); mindSystem.SetUserId(originalMind.Id, userId); Assert.Multiple(() => { Assert.That(mind.UserId, Is.EqualTo(null)); Assert.That(originalMind.Comp.UserId, Is.EqualTo(userId)); }); }); await pair.RunTicksSync(5); await pair.CleanReturnAsync(); } [Test] public async Task TestAddRemoveHasRoles() { await using var pair = await PoolManager.GetServerClient(); var server = pair.Server; var entMan = server.ResolveDependency(); await server.WaitAssertion(() => { var mindSystem = entMan.EntitySysManager.GetEntitySystem(); var roleSystem = entMan.EntitySysManager.GetEntitySystem(); var entity = entMan.SpawnEntity(null, new MapCoordinates()); var mindComp = entMan.EnsureComponent(entity); var mindId = mindSystem.CreateMind(null).Owner; var mind = entMan.EnsureComponent(mindId); Assert.That(mind.UserId, Is.EqualTo(null)); mindSystem.TransferTo(mindId, entity); Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId)); Assert.Multiple(() => { Assert.That(roleSystem.MindHasRole(mindId), Is.False); Assert.That(roleSystem.MindHasRole(mindId), Is.False); }); var traitorRole = "MindRoleTraitor"; roleSystem.MindAddRole(mindId, traitorRole); Assert.Multiple(() => { Assert.That(roleSystem.MindHasRole(mindId)); Assert.That(roleSystem.MindHasRole(mindId), Is.False); }); var jobRole = ""; roleSystem.MindAddJobRole(mindId, jobPrototype:jobRole); Assert.Multiple(() => { Assert.That(roleSystem.MindHasRole(mindId)); Assert.That(roleSystem.MindHasRole(mindId)); }); roleSystem.MindRemoveRole(mindId); Assert.Multiple(() => { Assert.That(roleSystem.MindHasRole(mindId), Is.False); Assert.That(roleSystem.MindHasRole(mindId)); }); roleSystem.MindRemoveRole(mindId); Assert.Multiple(() => { Assert.That(roleSystem.MindHasRole(mindId), Is.False); Assert.That(roleSystem.MindHasRole(mindId), Is.False); }); }); await pair.CleanReturnAsync(); } [Test] public async Task TestPlayerCanGhost() { // Client is needed to spawn session await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true, DummyTicker = false }); var server = pair.Server; var entMan = server.ResolveDependency(); var playerMan = server.ResolveDependency(); var mindSystem = entMan.EntitySysManager.GetEntitySystem(); EntityUid entity = default!; EntityUid mindId = default!; MindComponent mind = default!; var player = playerMan.Sessions.Single(); await server.WaitAssertion(() => { entity = entMan.SpawnEntity(null, new MapCoordinates()); var mindComp = entMan.EnsureComponent(entity); mindId = mindSystem.CreateMind(player.UserId, "Mindy McThinker"); mind = entMan.GetComponent(mindId); Assert.That(mind.UserId, Is.EqualTo(player.UserId)); mindSystem.TransferTo(mindId, entity); Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mindId)); }); await pair.RunTicksSync(5); await server.WaitAssertion(() => { entMan.DeleteEntity(entity); }); await pair.RunTicksSync(5); EntityUid mob = default!; EntityUid mobMindId = default!; MindComponent mobMind = default!; await server.WaitAssertion(() => { Assert.That(mind.OwnedEntity, Is.Not.Null); mob = entMan.SpawnEntity(null, new MapCoordinates()); mindSystem.MakeSentient(mob); mobMindId = mindSystem.CreateMind(player.UserId, "Mindy McThinker the Second"); mobMind = entMan.GetComponent(mobMindId); mindSystem.SetUserId(mobMindId, player.UserId); mindSystem.TransferTo(mobMindId, mob); }); await pair.RunTicksSync(5); await server.WaitAssertion(() => { var mId = player.ContentData()?.Mind!.Value; Assert.That(mId, Is.Not.Null); Assert.That(mId, Is.Not.EqualTo(default(EntityUid))); var m = entMan.GetComponent(mId!.Value); Assert.Multiple(() => { Assert.That(m!.OwnedEntity, Is.EqualTo(mob)); Assert.That(mId, Is.Not.EqualTo(mindId)); }); }); await pair.CleanReturnAsync(); } [Test] public async Task TestGhostDoesNotInfiniteLoop() { await using var pair = await PoolManager.GetServerClient(new PoolSettings { DummyTicker = false, Connected = true, Dirty = true }); var server = pair.Server; var entMan = server.ResolveDependency(); var playerMan = server.ResolveDependency(); var serverConsole = server.ResolveDependency(); //EntityUid entity = default!; EntityUid ghostRole = default!; EntityUid ghost = default!; EntityUid mindId = default!; MindComponent mind = default!; var player = playerMan.Sessions.Single(); await server.WaitAssertion(() => { // entity = entMan.SpawnEntity(null, new MapCoordinates()); // var mindComp = entMan.EnsureComponent(entity); // mind = mindSystem.CreateMind(player.UserId, "Mindy McThinker"); // // Assert.That(mind.UserId, Is.EqualTo(player.UserId)); // // mindSystem.TransferTo(mind, entity); // Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind)); var data = player.ContentData(); Assert.That(data?.Mind, Is.Not.EqualTo(null)); mindId = data!.Mind!.Value; mind = entMan.GetComponent(mindId); Assert.That(mind.OwnedEntity, Is.Not.Null); ghostRole = entMan.SpawnEntity("GhostRoleTestEntity", MapCoordinates.Nullspace); }); await pair.RunTicksSync(20); await server.WaitAssertion(() => { serverConsole.ExecuteCommand(player, "aghost"); }); await pair.RunTicksSync(20); await server.WaitAssertion(() => { var id = entMan.GetComponent(ghostRole).Identifier; entMan.EntitySysManager.GetEntitySystem().Takeover(player, id); }); await pair.RunTicksSync(20); await server.WaitAssertion(() => { var data = entMan.GetComponent(player.ContentData()!.Mind!.Value); Assert.That(data.OwnedEntity, Is.EqualTo(ghostRole)); serverConsole.ExecuteCommand(player, "aghost"); Assert.That(player.AttachedEntity, Is.Not.Null); ghost = player.AttachedEntity!.Value; }); await pair.RunTicksSync(20); await server.WaitAssertion(() => { Assert.That(player.AttachedEntity, Is.Not.Null); Assert.That(player.AttachedEntity!.Value, Is.EqualTo(ghost)); }); await pair.CleanReturnAsync(); } }