From 4d71b1b81e767d029084ac414f4ed665d1c26983 Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Mon, 27 Mar 2023 10:24:00 +1300 Subject: [PATCH] Revert "Mind ecs" (#14881) --- .../{Minds => }/MindEntityDeletionTest.cs | 35 +- .../Tests/Minds/MindTests.cs | 295 --------- .../AME/Components/AMEControllerComponent.cs | 10 +- .../Administration/Commands/AGhost.cs | 9 +- .../Administration/Commands/ControlMob.cs | 6 +- .../Administration/Commands/SetMindCommand.cs | 18 +- .../Systems/AdminVerbSystem.Antags.cs | 4 +- .../Administration/Systems/AdminVerbSystem.cs | 13 +- Content.Server/Body/Systems/BodySystem.cs | 12 +- Content.Server/Body/Systems/BrainSystem.cs | 12 +- Content.Server/Bql/QuerySelectors.cs | 13 +- .../CharacterInfo/CharacterInfoSystem.cs | 4 +- .../Chat/Commands/SuicideCommand.cs | 2 +- Content.Server/Chat/Managers/ChatManager.cs | 10 +- Content.Server/Chat/Managers/IChatManager.cs | 2 +- Content.Server/Chat/Systems/ChatSystem.cs | 4 +- .../Chemistry/ReagentEffects/MakeSentient.cs | 8 +- .../Cloning/CloningConsoleSystem.cs | 4 +- Content.Server/Cloning/CloningSystem.cs | 10 +- Content.Server/Drone/DroneSystem.cs | 4 +- .../ExplosionSystem.Processing.cs | 4 +- .../GameTicking/GameTicker.GamePreset.cs | 10 +- .../GameTicking/GameTicker.Player.cs | 1 - .../GameTicking/GameTicker.RoundFlow.cs | 5 +- .../GameTicking/GameTicker.Spawning.cs | 19 +- .../GameTicking/Rules/NukeopsRuleSystem.cs | 34 +- .../GameTicking/Rules/PiratesRuleSystem.cs | 11 +- .../GameTicking/Rules/SuspicionRuleSystem.cs | 17 +- .../Rules/TraitorDeathMatchRuleSystem.cs | 4 +- .../GameTicking/Rules/TraitorRuleSystem.cs | 8 +- .../GameTicking/Rules/ZombieRuleSystem.cs | 6 +- Content.Server/Ghost/GhostSystem.cs | 10 +- .../GhostRoleMobSpawnerComponent.cs | 2 +- .../GhostTakeoverAvailableComponent.cs | 2 +- Content.Server/Ghost/Roles/GhostRoleSystem.cs | 14 +- .../Ghost/Roles/MakeGhostRoleCommand.cs | 2 +- .../BiomassReclaimerSystem.cs | 2 +- .../Mind/Commands/MakeSentientCommand.cs | 2 +- .../Mind/Commands/MindInfoCommand.cs | 2 +- Content.Server/Mind/Commands/RenameCommand.cs | 2 +- ...ContainerComponent.cs => MindComponent.cs} | 6 +- .../Mind/Components/VisitingMindComponent.cs | 10 +- Content.Server/Mind/Mind.cs | 383 +++++++++++- Content.Server/Mind/MindSystem.cs | 565 +++--------------- Content.Server/Mind/MindTrackerSystem.cs | 4 +- .../Mind/TransferMindOnGibSystem.cs | 5 +- .../Commands/AddObjectiveCommand.cs | 7 +- .../Commands/RemoveObjectiveCommand.cs | 6 +- .../Objectives/Conditions/DieCondition.cs | 11 +- .../Conditions/EscapeShuttleCondition.cs | 4 +- .../Conditions/KillPersonCondition.cs | 11 +- .../Conditions/KillRandomPersonCondition.cs | 2 +- .../Conditions/RandomTraitorAliveCondition.cs | 11 +- .../Requirements/TraitorRequirement.cs | 7 +- Content.Server/PAI/PAISystem.cs | 10 +- Content.Server/PDA/PDASystem.cs | 15 +- .../ParticleAcceleratorControlBoxComponent.cs | 18 +- Content.Server/Players/PlayerData.cs | 11 +- .../Polymorph/Systems/PolymorphSystem.cs | 12 +- .../Revenant/EntitySystems/EssenceSystem.cs | 2 +- Content.Server/Roles/AddRoleCommand.cs | 6 +- Content.Server/Roles/Job.cs | 6 +- Content.Server/Roles/RemoveRoleCommand.cs | 5 +- .../EntitySystems/BluespaceLockerSystem.cs | 4 +- .../Store/Conditions/BuyerAntagCondition.cs | 2 +- .../Store/Conditions/BuyerJobCondition.cs | 2 +- .../Suspicion/Roles/SuspicionInnocentRole.cs | 5 +- .../Suspicion/Roles/SuspicionTraitorRole.cs | 6 +- .../Suspicion/SuspicionRoleComponent.cs | 4 +- Content.Server/Teleportation/PortalSystem.cs | 2 +- Content.Server/Traitor/TraitorRole.cs | 6 +- .../TraitorDeathMatchRedemptionSystem.cs | 2 +- .../Zombies/ZombifyOnDeathSystem.cs | 10 +- .../en-US/mind/components/mind-component.ftl | 9 +- Resources/Maps/barratry.yml | 2 +- .../Entities/Mobs/NPCs/revenant.yml | 2 +- .../Prototypes/Entities/Mobs/Player/diona.yml | 2 +- .../Prototypes/Entities/Mobs/Player/dwarf.yml | 2 +- .../Entities/Mobs/Player/familiars.yml | 4 +- .../Prototypes/Entities/Mobs/Player/human.yml | 2 +- .../Entities/Mobs/Player/observer.yml | 2 +- .../Entities/Mobs/Player/reptilian.yml | 2 +- .../Entities/Mobs/Player/skeleton.yml | 2 +- .../Prototypes/Entities/Mobs/Player/slime.yml | 2 +- .../Prototypes/Entities/Mobs/Player/vox.yml | 3 +- 85 files changed, 680 insertions(+), 1146 deletions(-) rename Content.IntegrationTests/Tests/{Minds => }/MindEntityDeletionTest.cs (88%) delete mode 100644 Content.IntegrationTests/Tests/Minds/MindTests.cs rename Content.Server/Mind/Components/{MindContainerComponent.cs => MindComponent.cs} (88%) diff --git a/Content.IntegrationTests/Tests/Minds/MindEntityDeletionTest.cs b/Content.IntegrationTests/Tests/MindEntityDeletionTest.cs similarity index 88% rename from Content.IntegrationTests/Tests/Minds/MindEntityDeletionTest.cs rename to Content.IntegrationTests/Tests/MindEntityDeletionTest.cs index 3f50ffcb0d..93c5fe41f1 100644 --- a/Content.IntegrationTests/Tests/Minds/MindEntityDeletionTest.cs +++ b/Content.IntegrationTests/Tests/MindEntityDeletionTest.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Threading.Tasks; using Content.Server.Mind; +using Content.Shared.Coordinates; using NUnit.Framework; using Robust.Server.GameObjects; using Robust.Server.Player; @@ -9,7 +10,7 @@ using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; -namespace Content.IntegrationTests.Tests.Minds +namespace Content.IntegrationTests.Tests { // Tests various scenarios of deleting the entity that a player's mind is connected to. [TestFixture] @@ -25,8 +26,6 @@ namespace Content.IntegrationTests.Tests.Minds var playerMan = server.ResolveDependency(); var mapManager = server.ResolveDependency(); - var mindSystem = entMan.EntitySysManager.GetEntitySystem(); - EntityUid playerEnt = default; EntityUid visitEnt = default; Mind mind = null; @@ -40,9 +39,11 @@ namespace Content.IntegrationTests.Tests.Minds playerEnt = entMan.SpawnEntity(null, pos); visitEnt = entMan.SpawnEntity(null, pos); - mind = mindSystem.CreateMind(player.UserId); - mindSystem.TransferTo(mind, playerEnt); - mindSystem.Visit(mind, visitEnt); + mind = new Mind(player.UserId); + mind.ChangeOwningPlayer(player.UserId); + + mind.TransferTo(playerEnt); + mind.Visit(visitEnt); Assert.That(player.AttachedEntity, Is.EqualTo(visitEnt)); Assert.That(mind.VisitingEntity, Is.EqualTo(visitEnt)); @@ -90,9 +91,6 @@ namespace Content.IntegrationTests.Tests.Minds var entMan = server.ResolveDependency(); var playerMan = server.ResolveDependency(); var mapManager = server.ResolveDependency(); - - var mindSystem = entMan.EntitySysManager.GetEntitySystem(); - var map = await PoolManager.CreateTestMap(pairTracker); EntityUid playerEnt = default; @@ -105,8 +103,10 @@ namespace Content.IntegrationTests.Tests.Minds playerEnt = entMan.SpawnEntity(null, pos); - mind = mindSystem.CreateMind(player.UserId); - mindSystem.TransferTo(mind, playerEnt); + mind = new Mind(player.UserId); + mind.ChangeOwningPlayer(player.UserId); + + mind.TransferTo(playerEnt); Assert.That(mind.CurrentEntity, Is.EqualTo(playerEnt)); }); @@ -136,26 +136,27 @@ namespace Content.IntegrationTests.Tests.Minds [Test] public async Task TestGhostOnDeleteMap() { - await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings { NoClient = true }); + 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 playerMan = server.ResolveDependency(); var mapManager = server.ResolveDependency(); - - var mindSystem = entMan.EntitySysManager.GetEntitySystem(); - var map = await PoolManager.CreateTestMap(pairTracker); EntityUid playerEnt = default; Mind mind = null; await server.WaitAssertion(() => { + var player = playerMan.ServerSessions.Single(); + playerEnt = entMan.SpawnEntity(null, coordinates); + mind = new Mind(player.UserId); + mind.ChangeOwningPlayer(player.UserId); - mind = mindSystem.CreateMind(null); - mindSystem.TransferTo(mind, playerEnt); + mind.TransferTo(playerEnt); Assert.That(mind.CurrentEntity, Is.EqualTo(playerEnt)); }); diff --git a/Content.IntegrationTests/Tests/Minds/MindTests.cs b/Content.IntegrationTests/Tests/Minds/MindTests.cs deleted file mode 100644 index 402ce95398..0000000000 --- a/Content.IntegrationTests/Tests/Minds/MindTests.cs +++ /dev/null @@ -1,295 +0,0 @@ -#nullable enable -using System; -using System.Threading.Tasks; -using Content.Server.Mind; -using Content.Server.Mind.Components; -using Content.Server.Roles; -using Content.Server.Traitor; -using Content.Shared.Damage; -using Content.Shared.Damage.Prototypes; -using Content.Shared.FixedPoint; -using Content.Shared.Roles; -using NUnit.Framework; -using Robust.Server.GameObjects; -using Robust.Shared.GameObjects; -using Robust.Shared.Map; -using Robust.Shared.Network; -using Robust.Shared.Prototypes; - -namespace Content.IntegrationTests.Tests.Minds; - -[TestFixture] -public sealed class MindTests -{ - private const string Prototypes = @" -- type: entity - id: MindTestEntity - components: - - type: MindContainer - -- type: entity - parent: MindTestEntity - id: MindTestEntityDamageable - components: - - type: Damageable - damageContainer: Biological - - type: Body - prototype: Human - requiredLegs: 2 - - type: MobState - - type: MobThresholds - thresholds: - 0: Alive - 100: Critical - 200: Dead - - type: Destructible - thresholds: - - trigger: - !type:DamageTypeTrigger - damageType: Blunt - damage: 400 - behaviors: - - !type:GibBehavior { } -"; - - /// - /// Exception handling for PlayerData and NetUserId invalid due to testing. - /// Can be removed when Players can be mocked. - /// - /// - private void CatchPlayerDataException(Action func) - { - try - { - func(); - } - catch (ArgumentException e) - { - // Prevent exiting due to PlayerData not being initialized. - if (e.Message == "New owner must have previously logged into the server. (Parameter 'newOwner')") - return; - throw; - } - } - - [Test] - public async Task TestCreateAndTransferMindToNewEntity() - { - await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{ NoClient = true }); - var server = pairTracker.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.UserId, Is.EqualTo(null)); - - mindSystem.TransferTo(mind, entity); - Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind)); - }); - - await pairTracker.CleanReturnAsync(); - } - - [Test] - public async Task TestReplaceMind() - { - await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{ NoClient = true }); - var server = pairTracker.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); - mindSystem.TransferTo(mind, entity); - Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind)); - - var mind2 = mindSystem.CreateMind(null); - mindSystem.TransferTo(mind2, entity); - Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind2)); - Assert.That(mind.OwnedEntity != entity); - }); - - await pairTracker.CleanReturnAsync(); - } - - [Test] - public async Task TestEntityDeadWhenGibbed() - { - await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{ NoClient = true, ExtraPrototypes = Prototypes }); - var server = pairTracker.Pair.Server; - - var entMan = server.ResolveDependency(); - var protoMan = server.ResolveDependency(); - - EntityUid entity = default!; - MindContainerComponent mindContainerComp = default!; - Mind mind = default!; - var mindSystem = entMan.EntitySysManager.GetEntitySystem(); - var damageableSystem = entMan.EntitySysManager.GetEntitySystem(); - - await server.WaitAssertion(() => - { - entity = entMan.SpawnEntity("MindTestEntityDamageable", new MapCoordinates()); - mindContainerComp = entMan.EnsureComponent(entity); - - mind = mindSystem.CreateMind(null); - - mindSystem.TransferTo(mind, entity); - Assert.That(mindSystem.GetMind(entity, mindContainerComp), Is.EqualTo(mind)); - Assert.That(!mindSystem.IsCharacterDeadPhysically(mind)); - }); - - await PoolManager.RunTicksSync(pairTracker.Pair, 5); - - await server.WaitAssertion(() => - { - var damageable = entMan.GetComponent(entity); - if (!protoMan.TryIndex("Blunt", out var prototype)) - { - return; - } - - damageableSystem.SetDamage(entity, damageable, new DamageSpecifier(prototype, FixedPoint2.New(401))); - Assert.That(mindSystem.GetMind(entity, mindContainerComp), Is.EqualTo(mind)); - }); - - await PoolManager.RunTicksSync(pairTracker.Pair, 5); - - await server.WaitAssertion(() => - { - Assert.That(mindSystem.IsCharacterDeadPhysically(mind)); - }); - - await pairTracker.CleanReturnAsync(); - } - - [Test] - public async Task TestMindTransfersToOtherEntity() - { - await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{ NoClient = true }); - var server = pairTracker.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); - - mindSystem.TransferTo(mind, entity); - - Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind)); - - mindSystem.TransferTo(mind, targetEntity); - Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(null)); - Assert.That(mindSystem.GetMind(targetEntity), Is.EqualTo(mind)); - }); - - await pairTracker.CleanReturnAsync(); - } - - [Test] - public async Task TestOwningPlayerCanBeChanged() - { - await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{ NoClient = true }); - var server = pairTracker.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); - - mindSystem.TransferTo(mind, entity); - - Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind)); - - var newUserId = new NetUserId(Guid.NewGuid()); - Assert.That(mindComp.HasMind); - CatchPlayerDataException(() => - mindSystem.ChangeOwningPlayer(mindComp.Mind!, newUserId)); - - Assert.That(mind.UserId, Is.EqualTo(newUserId)); - }); - - await pairTracker.CleanReturnAsync(); - } - - [Test] - public async Task TestAddRemoveHasRoles() - { - await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{ NoClient = true }); - var server = pairTracker.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.UserId, Is.EqualTo(null)); - - mindSystem.TransferTo(mind, entity); - Assert.That(mindSystem.GetMind(entity, mindComp), Is.EqualTo(mind)); - - Assert.That(!mindSystem.HasRole(mind)); - Assert.That(!mindSystem.HasRole(mind)); - - var traitorRole = new TraitorRole(mind, new AntagPrototype()); - - mindSystem.AddRole(mind, traitorRole); - - Assert.That(mindSystem.HasRole(mind)); - Assert.That(!mindSystem.HasRole(mind)); - - var jobRole = new Job(mind, new JobPrototype()); - - mindSystem.AddRole(mind, jobRole); - - Assert.That(mindSystem.HasRole(mind)); - Assert.That(mindSystem.HasRole(mind)); - - mindSystem.RemoveRole(mind, traitorRole); - - Assert.That(!mindSystem.HasRole(mind)); - Assert.That(mindSystem.HasRole(mind)); - - mindSystem.RemoveRole(mind, jobRole); - - Assert.That(!mindSystem.HasRole(mind)); - Assert.That(!mindSystem.HasRole(mind)); - }); - - await pairTracker.CleanReturnAsync(); - } -} diff --git a/Content.Server/AME/Components/AMEControllerComponent.cs b/Content.Server/AME/Components/AMEControllerComponent.cs index 4285ff5fbd..1a398a5eb5 100644 --- a/Content.Server/AME/Components/AMEControllerComponent.cs +++ b/Content.Server/AME/Components/AMEControllerComponent.cs @@ -176,20 +176,20 @@ namespace Content.Server.AME.Components } // Logging - _entities.TryGetComponent(player, out MindContainerComponent? mindContainerComponent); - if (mindContainerComponent != null) + _entities.TryGetComponent(player, out MindComponent? mindComponent); + if (mindComponent != null) { var humanReadableState = _injecting ? "Inject" : "Not inject"; if (msg.Button == UiButton.IncreaseFuel || msg.Button == UiButton.DecreaseFuel) - _adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{_entities.ToPrettyString(mindContainerComponent.Owner):player} has set the AME to inject {InjectionAmount} while set to {humanReadableState}"); + _adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{_entities.ToPrettyString(mindComponent.Owner):player} has set the AME to inject {InjectionAmount} while set to {humanReadableState}"); if (msg.Button == UiButton.ToggleInjection) - _adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{_entities.ToPrettyString(mindContainerComponent.Owner):player} has set the AME to {humanReadableState}"); + _adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{_entities.ToPrettyString(mindComponent.Owner):player} has set the AME to {humanReadableState}"); // Admin alert if (GetCoreCount() * 2 == InjectionAmount - 2 && msg.Button == UiButton.IncreaseFuel) - _chat.SendAdminAlert(player, $"increased AME over safe limit to {InjectionAmount}", mindContainerComponent); + _chat.SendAdminAlert(player, $"increased AME over safe limit to {InjectionAmount}", mindComponent); } GetAMENodeGroup()?.UpdateCoreVisuals(); diff --git a/Content.Server/Administration/Commands/AGhost.cs b/Content.Server/Administration/Commands/AGhost.cs index 82c786af86..037c289cbd 100644 --- a/Content.Server/Administration/Commands/AGhost.cs +++ b/Content.Server/Administration/Commands/AGhost.cs @@ -1,6 +1,5 @@ using Content.Server.GameTicking; using Content.Server.Ghost.Components; -using Content.Server.Mind; using Content.Server.Players; using Content.Shared.Administration; using Content.Shared.Ghost; @@ -34,12 +33,10 @@ namespace Content.Server.Administration.Commands shell.WriteLine("You can't ghost here!"); return; } - - var mindSystem = _entities.System(); if (mind.VisitingEntity != default && _entities.HasComponent(mind.VisitingEntity)) { - mindSystem.UnVisit(mind); + player.ContentData()!.Mind?.UnVisit(); return; } @@ -59,12 +56,12 @@ namespace Content.Server.Administration.Commands else if (!string.IsNullOrWhiteSpace(mind.Session?.Name)) _entities.GetComponent(ghost).EntityName = mind.Session.Name; - mindSystem.Visit(mind, ghost); + mind.Visit(ghost); } else { _entities.GetComponent(ghost).EntityName = player.Name; - mindSystem.TransferTo(mind, ghost); + mind.TransferTo(ghost); } var comp = _entities.GetComponent(ghost); diff --git a/Content.Server/Administration/Commands/ControlMob.cs b/Content.Server/Administration/Commands/ControlMob.cs index 18fb3bbb65..4346ca7f17 100644 --- a/Content.Server/Administration/Commands/ControlMob.cs +++ b/Content.Server/Administration/Commands/ControlMob.cs @@ -1,4 +1,3 @@ -using Content.Server.Mind; using Content.Server.Mind.Components; using Content.Server.Players; using Content.Shared.Administration; @@ -45,7 +44,7 @@ namespace Content.Server.Administration.Commands return; } - if (!_entities.HasComponent(target)) + if (!_entities.HasComponent(target)) { shell.WriteLine(Loc.GetString("shell-entity-is-not-mob")); return; @@ -55,8 +54,7 @@ namespace Content.Server.Administration.Commands DebugTools.AssertNotNull(mind); - var mindSystem = _entities.System(); - mindSystem.TransferTo(mind!, target); + mind!.TransferTo(target); } } } diff --git a/Content.Server/Administration/Commands/SetMindCommand.cs b/Content.Server/Administration/Commands/SetMindCommand.cs index 6ef9c7eede..5c728f6599 100644 --- a/Content.Server/Administration/Commands/SetMindCommand.cs +++ b/Content.Server/Administration/Commands/SetMindCommand.cs @@ -1,4 +1,3 @@ -using Content.Server.Mind; using Content.Server.Mind.Components; using Content.Server.Players; using Content.Shared.Administration; @@ -10,10 +9,9 @@ namespace Content.Server.Administration.Commands [AdminCommand(AdminFlags.Admin)] sealed class SetMindCommand : IConsoleCommand { - public string Command => "setmind"; - public string Description => Loc.GetString("set-mind-command-description", ("requiredComponent", nameof(MindContainerComponent))); + public string Description => Loc.GetString("set-mind-command-description", ("requiredComponent", nameof(MindComponent))); public string Help => Loc.GetString("set-mind-command-help-text", ("command", Command)); @@ -41,7 +39,7 @@ namespace Content.Server.Administration.Commands return; } - if (!entityManager.HasComponent(eUid)) + if (!entityManager.HasComponent(eUid)) { shell.WriteLine(Loc.GetString("set-mind-command-target-has-no-mind-message")); return; @@ -61,16 +59,16 @@ namespace Content.Server.Administration.Commands return; } - var mindSystem = entityManager.System(); - var mind = playerCData.Mind; if (mind == null) { - mind = mindSystem.CreateMind(session.UserId); - mind.CharacterName = entityManager.GetComponent(eUid).EntityName; + mind = new Mind.Mind(session.UserId) + { + CharacterName = entityManager.GetComponent(eUid).EntityName + }; + mind.ChangeOwningPlayer(session.UserId); } - - mindSystem.TransferTo(mind, eUid); + mind.TransferTo(eUid); } } } diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs index d340c39c7a..b134d15fb3 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs @@ -28,7 +28,7 @@ public sealed partial class AdminVerbSystem if (!_adminManager.HasAdminFlag(player, AdminFlags.Fun)) return; - var targetHasMind = TryComp(args.Target, out MindContainerComponent? targetMindComp); + var targetHasMind = TryComp(args.Target, out MindComponent? targetMindComp); if (!targetHasMind || targetMindComp == null) return; @@ -56,7 +56,7 @@ public sealed partial class AdminVerbSystem Icon = new SpriteSpecifier.Rsi(new ResourcePath("/Textures/Structures/Wallmounts/signs.rsi"), "bio"), Act = () => { - TryComp(args.Target, out MindContainerComponent? mindComp); + TryComp(args.Target, out MindComponent? mindComp); if (mindComp == null || mindComp.Mind == null) return; diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.cs b/Content.Server/Administration/Systems/AdminVerbSystem.cs index 3707014bda..7b1def620b 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.cs @@ -8,7 +8,6 @@ using Content.Server.Configurable; using Content.Server.Disposal.Tube.Components; using Content.Server.EUI; using Content.Server.Ghost.Roles; -using Content.Server.Mind; using Content.Server.Mind.Commands; using Content.Server.Mind.Components; using Content.Server.Players; @@ -52,7 +51,6 @@ namespace Content.Server.Administration.Systems [Dependency] private readonly UserInterfaceSystem _uiSystem = default!; [Dependency] private readonly PrayerSystem _prayerSystem = default!; [Dependency] private readonly EuiManager _eui = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; private readonly Dictionary _openSolutionUis = new(); @@ -231,12 +229,7 @@ namespace Content.Server.Administration.Systems Act = () => { MakeSentientCommand.MakeSentient(args.Target, EntityManager); - - var mind = player.ContentData()?.Mind; - if (mind == null) - return; - - _mindSystem.TransferTo(mind, args.Target, ghostCheckOverride: true); + player.ContentData()?.Mind?.TransferTo(args.Target, ghostCheckOverride: true); }, Impact = LogImpact.High, ConfirmationPopup = true @@ -270,7 +263,7 @@ namespace Content.Server.Administration.Systems // Make Sentient verb if (_groupController.CanCommand(player, "makesentient") && args.User != args.Target && - !EntityManager.HasComponent(args.Target)) + !EntityManager.HasComponent(args.Target)) { Verb verb = new() { @@ -333,7 +326,7 @@ namespace Content.Server.Administration.Systems // Make ghost role verb if (_groupController.CanCommand(player, "makeghostrole") && - !(EntityManager.GetComponentOrNull(args.Target)?.HasMind ?? false)) + !(EntityManager.GetComponentOrNull(args.Target)?.HasMind ?? false)) { Verb verb = new(); verb.Text = Loc.GetString("make-ghost-role-verb-get-data-text"); diff --git a/Content.Server/Body/Systems/BodySystem.cs b/Content.Server/Body/Systems/BodySystem.cs index 3a70b51893..472b6b8acd 100644 --- a/Content.Server/Body/Systems/BodySystem.cs +++ b/Content.Server/Body/Systems/BodySystem.cs @@ -4,7 +4,6 @@ using Content.Server.Body.Components; using Content.Server.GameTicking; using Content.Server.Humanoid; using Content.Server.Kitchen.Components; -using Content.Server.Mind; using Content.Server.Mind.Components; using Content.Shared.Body.Components; using Content.Shared.Body.Part; @@ -29,7 +28,6 @@ public sealed class BodySystem : SharedBodySystem [Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!; [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; public override void Initialize() { @@ -42,14 +40,16 @@ public sealed class BodySystem : SharedBodySystem private void OnRelayMoveInput(EntityUid uid, BodyComponent component, ref MoveInputEvent args) { - if (_mobState.IsDead(uid) && _mindSystem.TryGetMind(uid, out var mind)) + if (_mobState.IsDead(uid) && + EntityManager.TryGetComponent(uid, out var mind) && + mind.HasMind) { - if (!mind.TimeOfDeath.HasValue) + if (!mind.Mind!.TimeOfDeath.HasValue) { - mind.TimeOfDeath = _gameTiming.RealTime; + mind.Mind.TimeOfDeath = _gameTiming.RealTime; } - _ticker.OnGhostAttempt(mind, true); + _ticker.OnGhostAttempt(mind.Mind!, true); } } diff --git a/Content.Server/Body/Systems/BrainSystem.cs b/Content.Server/Body/Systems/BrainSystem.cs index 2098293870..52b743eebc 100644 --- a/Content.Server/Body/Systems/BrainSystem.cs +++ b/Content.Server/Body/Systems/BrainSystem.cs @@ -1,6 +1,5 @@ using Content.Server.Body.Components; using Content.Server.Ghost.Components; -using Content.Server.Mind; using Content.Server.Mind.Components; using Content.Shared.Body.Components; using Content.Shared.Body.Events; @@ -11,8 +10,6 @@ namespace Content.Server.Body.Systems { public sealed class BrainSystem : EntitySystem { - [Dependency] private readonly MindSystem _mindSystem = default!; - public override void Initialize() { base.Initialize(); @@ -37,8 +34,8 @@ namespace Content.Server.Body.Systems private void HandleMind(EntityUid newEntity, EntityUid oldEntity) { - EntityManager.EnsureComponent(newEntity); - var oldMind = EntityManager.EnsureComponent(oldEntity); + EntityManager.EnsureComponent(newEntity); + var oldMind = EntityManager.EnsureComponent(oldEntity); EnsureComp(newEntity); if (HasComp(newEntity)) @@ -47,10 +44,7 @@ namespace Content.Server.Body.Systems // TODO: This is an awful solution. EnsureComp(newEntity); - if (!_mindSystem.TryGetMind(oldEntity, out var mind, oldMind)) - return; - - _mindSystem.TransferTo(mind, newEntity); + oldMind.Mind?.TransferTo(newEntity); } } } diff --git a/Content.Server/Bql/QuerySelectors.cs b/Content.Server/Bql/QuerySelectors.cs index 829dee7e38..a3b943bc9d 100644 --- a/Content.Server/Bql/QuerySelectors.cs +++ b/Content.Server/Bql/QuerySelectors.cs @@ -1,6 +1,5 @@ using System.Linq; using Content.Server.Chemistry.Components.SolutionManager; -using Content.Server.Mind; using Content.Server.Mind.Components; using Content.Server.Power.Components; using Content.Shared.Tag; @@ -22,7 +21,7 @@ namespace Content.Server.Bql { return input.Where(e => { - if (entityManager.TryGetComponent(e, out var mind)) + if (entityManager.TryGetComponent(e, out var mind)) return (mind.Mind?.VisitingEntity == e) ^ isInverted; return isInverted; @@ -33,7 +32,7 @@ namespace Content.Server.Bql { return DoSelection( - entityManager.EntityQuery().Select(x => x.Owner), + entityManager.EntityQuery().Select(x => x.Owner), arguments, isInverted, entityManager); } } @@ -69,16 +68,14 @@ namespace Content.Server.Bql public override IEnumerable DoSelection(IEnumerable input, IReadOnlyList arguments, bool isInverted, IEntityManager entityManager) { - var mindSystem = entityManager.System(); return input.Where(e => - entityManager.TryGetComponent(e, out var mind) - && mind.Mind != null - && !mindSystem.IsCharacterDeadPhysically(mind.Mind)); + (entityManager.TryGetComponent(e, out var mind) && + !(mind.Mind?.CharacterDeadPhysically ?? false)) ^ isInverted); } public override IEnumerable DoInitialSelection(IReadOnlyList arguments, bool isInverted, IEntityManager entityManager) { - return DoSelection(entityManager.EntityQuery().Select(x => x.Owner), arguments, + return DoSelection(entityManager.EntityQuery().Select(x => x.Owner), arguments, isInverted, entityManager); } } diff --git a/Content.Server/CharacterInfo/CharacterInfoSystem.cs b/Content.Server/CharacterInfo/CharacterInfoSystem.cs index bd26a4836b..282722ceae 100644 --- a/Content.Server/CharacterInfo/CharacterInfoSystem.cs +++ b/Content.Server/CharacterInfo/CharacterInfoSystem.cs @@ -26,9 +26,9 @@ public sealed class CharacterInfoSystem : EntitySystem var conditions = new Dictionary>(); var jobTitle = "No Profession"; var briefing = "!!ERROR: No Briefing!!"; //should never show on the UI unless there's a bug - if (EntityManager.TryGetComponent(entity, out MindContainerComponent? mindContainerComponent) && mindContainerComponent.Mind != null) + if (EntityManager.TryGetComponent(entity, out MindComponent? mindComponent) && mindComponent.Mind != null) { - var mind = mindContainerComponent.Mind; + var mind = mindComponent.Mind; // Get objectives foreach (var objective in mind.AllObjectives) diff --git a/Content.Server/Chat/Commands/SuicideCommand.cs b/Content.Server/Chat/Commands/SuicideCommand.cs index 16c699b0a9..2f08881cb0 100644 --- a/Content.Server/Chat/Commands/SuicideCommand.cs +++ b/Content.Server/Chat/Commands/SuicideCommand.cs @@ -29,7 +29,7 @@ namespace Content.Server.Chat.Commands var mind = player.ContentData()?.Mind; // This check also proves mind not-null for at the end when the mob is ghosted. - if (mind?.OwnedEntity is not { Valid: true } victim) + if (mind?.OwnedComponent?.Owner is not { Valid: true } victim) { shell.WriteLine("You don't have a mind!"); return; diff --git a/Content.Server/Chat/Managers/ChatManager.cs b/Content.Server/Chat/Managers/ChatManager.cs index b81c5f96b0..90924188b2 100644 --- a/Content.Server/Chat/Managers/ChatManager.cs +++ b/Content.Server/Chat/Managers/ChatManager.cs @@ -116,19 +116,19 @@ namespace Content.Server.Chat.Managers ChatMessageToMany(ChatChannel.AdminAlert, message, wrappedMessage, default, false, true, clients); } - public void SendAdminAlert(EntityUid player, string message, MindContainerComponent? mindContainerComponent = null) + public void SendAdminAlert(EntityUid player, string message, MindComponent? mindComponent = null) { - if(mindContainerComponent == null && !_entityManager.TryGetComponent(player, out mindContainerComponent)) + if(mindComponent == null && !_entityManager.TryGetComponent(player, out mindComponent)) { SendAdminAlert(message); return; } var adminSystem = _entityManager.System(); - var antag = mindContainerComponent.Mind!.UserId != null - && (adminSystem.GetCachedPlayerInfo(mindContainerComponent.Mind!.UserId.Value)?.Antag ?? false); + var antag = mindComponent.Mind!.UserId != null + && (adminSystem.GetCachedPlayerInfo(mindComponent.Mind!.UserId.Value)?.Antag ?? false); - SendAdminAlert($"{mindContainerComponent.Mind!.Session?.Name}{(antag ? " (ANTAG)" : "")} {message}"); + SendAdminAlert($"{mindComponent.Mind!.Session?.Name}{(antag ? " (ANTAG)" : "")} {message}"); } public void SendHookOOC(string sender, string message) diff --git a/Content.Server/Chat/Managers/IChatManager.cs b/Content.Server/Chat/Managers/IChatManager.cs index f3e0e8e2cf..6d74f76422 100644 --- a/Content.Server/Chat/Managers/IChatManager.cs +++ b/Content.Server/Chat/Managers/IChatManager.cs @@ -24,7 +24,7 @@ namespace Content.Server.Chat.Managers void SendHookOOC(string sender, string message); void SendAdminAnnouncement(string message); void SendAdminAlert(string message); - void SendAdminAlert(EntityUid player, string message, MindContainerComponent? mindContainerComponent = null); + void SendAdminAlert(EntityUid player, string message, MindComponent? mindComponent = null); void ChatMessageToOne(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, INetChannel client, Color? colorOverride = null, bool recordReplay = false, string? audioPath = null, float audioVolume = 0); diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index a4e23558fb..fd3182e65c 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -497,9 +497,9 @@ public sealed partial class ChatSystem : SharedChatSystem if (player == null) return true; - var mindContainerComponent = player.ContentData()?.Mind; + var mindComponent = player.ContentData()?.Mind; - if (mindContainerComponent == null) + if (mindComponent == null) { shell?.WriteError("You don't have a mind!"); return false; diff --git a/Content.Server/Chemistry/ReagentEffects/MakeSentient.cs b/Content.Server/Chemistry/ReagentEffects/MakeSentient.cs index 81f92cb8da..c762ba8a83 100644 --- a/Content.Server/Chemistry/ReagentEffects/MakeSentient.cs +++ b/Content.Server/Chemistry/ReagentEffects/MakeSentient.cs @@ -13,12 +13,6 @@ public sealed class MakeSentient : ReagentEffect var entityManager = args.EntityManager; var uid = args.SolutionEntity; - // This makes it so it doesn't affect things that are already sentient - if (entityManager.HasComponent(uid)) - { - return; - } - // This piece of code makes things able to speak "normally". One thing of note is that monkeys have a unique accent and won't be affected by this. entityManager.RemoveComponent(uid); @@ -26,7 +20,7 @@ public sealed class MakeSentient : ReagentEffect entityManager.RemoveComponent(uid); // This makes it so it doesn't add a ghost role to things that are already sentient - if (entityManager.HasComponent(uid)) + if (entityManager.HasComponent(uid)) { return; } diff --git a/Content.Server/Cloning/CloningConsoleSystem.cs b/Content.Server/Cloning/CloningConsoleSystem.cs index 4da87a6339..eb8e2b80cb 100644 --- a/Content.Server/Cloning/CloningConsoleSystem.cs +++ b/Content.Server/Cloning/CloningConsoleSystem.cs @@ -164,7 +164,7 @@ namespace Content.Server.Cloning if (body is null) return; - if (!TryComp(body, out var mindComp)) + if (!TryComp(body, out var mindComp)) return; var mind = mindComp.Mind; @@ -214,7 +214,7 @@ namespace Content.Server.Cloning { scanBodyInfo = MetaData(scanBody.Value).EntityName; - TryComp(scanBody, out var mindComp); + TryComp(scanBody, out var mindComp); if (!_mobStateSystem.IsDead(scanBody.Value)) { diff --git a/Content.Server/Cloning/CloningSystem.cs b/Content.Server/Cloning/CloningSystem.cs index c17dff31ef..45ffc4a967 100644 --- a/Content.Server/Cloning/CloningSystem.cs +++ b/Content.Server/Cloning/CloningSystem.cs @@ -19,7 +19,6 @@ using Content.Server.Construction; using Content.Server.Materials; using Content.Server.Stack; using Content.Server.Jobs; -using Content.Server.Mind; using Content.Shared.Humanoid; using Content.Shared.Humanoid.Prototypes; using Content.Shared.Zombies; @@ -55,7 +54,6 @@ namespace Content.Server.Cloning [Dependency] private readonly ChatSystem _chatSystem = default!; [Dependency] private readonly IConfigurationManager _configManager = default!; [Dependency] private readonly MaterialStorageSystem _material = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; public readonly Dictionary ClonesWaitingForMind = new(); public const float EasyModeCloningCost = 0.7f; @@ -99,12 +97,12 @@ namespace Content.Server.Cloning { if (!ClonesWaitingForMind.TryGetValue(mind, out var entity) || !EntityManager.EntityExists(entity) || - !TryComp(entity, out var mindComp) || + !TryComp(entity, out var mindComp) || mindComp.Mind != null) return; - _mindSystem.TransferTo(mind, entity, ghostCheckOverride: true); - _mindSystem.UnVisit(mind); + mind.TransferTo(entity, ghostCheckOverride: true); + mind.UnVisit(); ClonesWaitingForMind.Remove(mind); } @@ -159,7 +157,7 @@ namespace Content.Server.Cloning { if (EntityManager.EntityExists(clone) && !_mobStateSystem.IsDead(clone) && - TryComp(clone, out var cloneMindComp) && + TryComp(clone, out var cloneMindComp) && (cloneMindComp.Mind == null || cloneMindComp.Mind == mind)) return false; // Mind already has clone diff --git a/Content.Server/Drone/DroneSystem.cs b/Content.Server/Drone/DroneSystem.cs index 1cffb79ae7..00bde35a58 100644 --- a/Content.Server/Drone/DroneSystem.cs +++ b/Content.Server/Drone/DroneSystem.cs @@ -72,7 +72,7 @@ namespace Content.Server.Drone private void OnExamined(EntityUid uid, DroneComponent component, ExaminedEvent args) { - if (TryComp(uid, out var mind) && mind.HasMind) + if (TryComp(uid, out var mind) && mind.HasMind) { args.PushMarkup(Loc.GetString("drone-active")); } @@ -132,7 +132,7 @@ namespace Content.Server.Drone foreach (var entity in _lookup.GetEntitiesInRange(xform.MapPosition, component.InteractionBlockRange)) { // Return true if the entity is/was controlled by a player and is not a drone or ghost. - if (HasComp(entity) && !HasComp(entity) && !HasComp(entity)) + if (HasComp(entity) && !HasComp(entity) && !HasComp(entity)) { // Filter out dead ghost roles. Dead normal players are intended to block. if ((TryComp(entity, out var entityMobState) && HasComp(entity) && _mobStateSystem.IsDead(entity, entityMobState))) diff --git a/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs b/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs index 441696f0e2..7f03e68aa4 100644 --- a/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs +++ b/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs @@ -392,7 +392,7 @@ public sealed partial class ExplosionSystem : EntitySystem { // no damage-dict multiplication required. _damageableSystem.TryChangeDamage(uid, damage, ignoreResistances: true, damageable: damageable); - if (HasComp(uid) || HasComp(uid)) + if (HasComp(uid) || HasComp(uid)) { var damageStr = string.Join(", ", damage.DamageDict.Select(entry => $"{entry.Key}: {entry.Value}")); _adminLogger.Add(LogType.Explosion, LogImpact.Medium, @@ -403,7 +403,7 @@ public sealed partial class ExplosionSystem : EntitySystem { var appliedDamage = damage * ev.DamageCoefficient; _damageableSystem.TryChangeDamage(uid, appliedDamage, ignoreResistances: true, damageable: damageable); - if (HasComp(uid) || HasComp(uid)) + if (HasComp(uid) || HasComp(uid)) { var damageStr = string.Join(", ", appliedDamage.DamageDict.Select(entry => $"{entry.Key}: {entry.Value}")); _adminLogger.Add(LogType.Explosion, LogImpact.Medium, diff --git a/Content.Server/GameTicking/GameTicker.GamePreset.cs b/Content.Server/GameTicking/GameTicker.GamePreset.cs index 46483eb099..eb44943e76 100644 --- a/Content.Server/GameTicking/GameTicker.GamePreset.cs +++ b/Content.Server/GameTicking/GameTicker.GamePreset.cs @@ -5,7 +5,6 @@ using Content.Server.GameTicking.Events; using Content.Server.GameTicking.Presets; using Content.Server.GameTicking.Rules; using Content.Server.Ghost.Components; -using Content.Server.Mind; using Content.Shared.CCVar; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; @@ -21,7 +20,6 @@ namespace Content.Server.GameTicking public const float PresetFailedCooldownIncrease = 30f; [Dependency] private readonly MobStateSystem _mobStateSystem = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; public GamePresetPrototype? Preset { get; private set; } @@ -180,7 +178,7 @@ namespace Content.Server.GameTicking if (mind.VisitingEntity != default) { - _mindSystem.UnVisit(mind); + mind.UnVisit(); } var position = playerEntity is {Valid: true} @@ -198,7 +196,7 @@ namespace Content.Server.GameTicking // + If we're in a mob that is critical, and we're supposed to be able to return if possible, // we're succumbing - the mob is killed. Therefore, character is dead. Ghosting OK. // (If the mob survives, that's a bug. Ghosting is kept regardless.) - var canReturn = canReturnGlobal && _mindSystem.IsCharacterDeadPhysically(mind); + var canReturn = canReturnGlobal && mind.CharacterDeadPhysically; if (canReturnGlobal && TryComp(playerEntity, out MobStateComponent? mobState)) { @@ -240,9 +238,9 @@ namespace Content.Server.GameTicking _ghosts.SetCanReturnToBody(ghostComponent, canReturn); if (canReturn) - _mindSystem.Visit(mind, ghost); + mind.Visit(ghost); else - _mindSystem.TransferTo(mind, ghost); + mind.TransferTo(ghost); return true; } diff --git a/Content.Server/GameTicking/GameTicker.Player.cs b/Content.Server/GameTicking/GameTicker.Player.cs index fd4a2e6a9c..10edb7d096 100644 --- a/Content.Server/GameTicking/GameTicker.Player.cs +++ b/Content.Server/GameTicking/GameTicker.Player.cs @@ -8,7 +8,6 @@ using Robust.Server.Player; using Robust.Shared.Enums; using Robust.Shared.Timing; using Robust.Shared.Utility; -using PlayerData = Content.Server.Players.PlayerData; namespace Content.Server.GameTicking { diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index 6ab473c6d2..e64837ca9f 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -21,7 +21,6 @@ using System.Linq; using System.Threading.Tasks; using Content.Shared.Database; using Robust.Shared.Asynchronous; -using PlayerData = Content.Server.Players.PlayerData; namespace Content.Server.GameTicking { @@ -321,12 +320,12 @@ namespace Content.Server.GameTicking var connected = false; var observer = mind.AllRoles.Any(role => role is ObserverRole); // Continuing - if (userId != null && _playerManager.ValidSessionId(userId.Value)) + if (_playerManager.TryGetSessionById(userId, out var ply)) { connected = true; } PlayerData? contentPlayerData = null; - if (userId != null && _playerManager.TryGetPlayerData(userId.Value, out var playerData)) + if (_playerManager.TryGetPlayerData(userId, out var playerData)) { contentPlayerData = playerData.ContentData(); } diff --git a/Content.Server/GameTicking/GameTicker.Spawning.cs b/Content.Server/GameTicking/GameTicker.Spawning.cs index 6a5373981c..0826638a6f 100644 --- a/Content.Server/GameTicking/GameTicker.Spawning.cs +++ b/Content.Server/GameTicking/GameTicker.Spawning.cs @@ -172,12 +172,15 @@ namespace Content.Server.GameTicking DebugTools.AssertNotNull(data); data!.WipeMind(); - var newMind = _mindSystem.CreateMind(data.UserId, character.Name); - _mindSystem.ChangeOwningPlayer(newMind, data.UserId); + var newMind = new Mind.Mind(data.UserId) + { + CharacterName = character.Name + }; + newMind.ChangeOwningPlayer(data.UserId); var jobPrototype = _prototypeManager.Index(jobId); var job = new Job(newMind, jobPrototype); - _mindSystem.AddRole(newMind, job); + newMind.AddRole(job); _playTimeTrackings.PlayerRolesChanged(player); @@ -186,7 +189,7 @@ namespace Content.Server.GameTicking DebugTools.AssertNotNull(mobMaybe); var mob = mobMaybe!.Value; - _mindSystem.TransferTo(newMind, mob); + newMind.TransferTo(mob); if (lateJoin) { @@ -275,15 +278,15 @@ namespace Content.Server.GameTicking DebugTools.AssertNotNull(data); data!.WipeMind(); - var newMind = _mindSystem.CreateMind(data.UserId); - _mindSystem.ChangeOwningPlayer(newMind, data.UserId); - _mindSystem.AddRole(newMind, new ObserverRole(newMind)); + var newMind = new Mind.Mind(data.UserId); + newMind.ChangeOwningPlayer(data.UserId); + newMind.AddRole(new ObserverRole(newMind)); var mob = SpawnObserverMob(); EntityManager.GetComponent(mob).EntityName = name; var ghost = EntityManager.GetComponent(mob); EntitySystem.Get().SetCanReturnToBody(ghost, false); - _mindSystem.TransferTo(newMind, mob); + newMind.TransferTo(mob); _playerGameStatuses[player.UserId] = PlayerGameStatus.JoinedGame; RaiseNetworkEvent(GetStatusSingle(player, PlayerGameStatus.JoinedGame)); diff --git a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs index 4e36b8d5f1..bf2c7946db 100644 --- a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs @@ -6,8 +6,6 @@ using Content.Server.GameTicking.Rules.Configurations; using Content.Server.Ghost.Roles.Components; using Content.Server.Ghost.Roles.Events; using Content.Server.Humanoid; -using Content.Server.Humanoid.Systems; -using Content.Server.Mind; using Content.Server.Mind.Components; using Content.Server.NPC.Systems; using Content.Server.Nuke; @@ -55,8 +53,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem [Dependency] private readonly GameTicker _ticker = default!; [Dependency] private readonly MapLoaderSystem _map = default!; [Dependency] private readonly ShuttleSystem _shuttle = default!; - [Dependency] private readonly RandomHumanoidSystem _randomHumanoid = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; + private enum WinType { @@ -171,10 +168,10 @@ public sealed class NukeopsRuleSystem : GameRuleSystem private void OnComponentInit(EntityUid uid, NukeOperativeComponent component, ComponentInit args) { // If entity has a prior mind attached, add them to the players list. - if (!TryComp(uid, out var mindContainerComponent) || !RuleAdded) + if (!TryComp(uid, out var mindComponent) || !RuleAdded) return; - var session = mindContainerComponent.Mind?.Session; + var session = mindComponent.Mind?.Session; var name = MetaData(uid).EntityName; if (session != null) _operativePlayers.Add(name, session); @@ -576,18 +573,18 @@ public sealed class NukeopsRuleSystem : GameRuleSystem private void OnMindAdded(EntityUid uid, NukeOperativeComponent component, MindAddedMessage args) { - if (!TryComp(uid, out var mindContainerComponent) || mindContainerComponent.Mind == null) + if (!TryComp(uid, out var mindComponent) || mindComponent.Mind == null) return; - var mind = mindContainerComponent.Mind; + var mind = mindComponent.Mind; if (_operativeMindPendingData.TryGetValue(uid, out var role)) { - _mindSystem.AddRole(mind, new TraitorRole(mind, _prototypeManager.Index(role))); + mind.AddRole(new TraitorRole(mind, _prototypeManager.Index(role))); _operativeMindPendingData.Remove(uid); } - if (!_mindSystem.TryGetSession(mind, out var playerSession)) + if (!mind.TryGetSession(out var playerSession)) return; if (_operativePlayers.ContainsValue(playerSession)) return; @@ -761,11 +758,14 @@ public sealed class NukeopsRuleSystem : GameRuleSystem var mob = EntityManager.SpawnEntity(species.Prototype, _random.Pick(spawns)); SetupOperativeEntity(mob, spawnDetails.Name, spawnDetails.Gear, profile); - var newMind = _mindSystem.CreateMind(session.UserId, spawnDetails.Name); - _mindSystem.ChangeOwningPlayer(newMind, session.UserId); - _mindSystem.AddRole(newMind, new TraitorRole(newMind, nukeOpsAntag)); + var newMind = new Mind.Mind(session.UserId) + { + CharacterName = spawnDetails.Name + }; + newMind.ChangeOwningPlayer(session.UserId); + newMind.AddRole(new TraitorRole(newMind, nukeOpsAntag)); - _mindSystem.TransferTo(newMind, mob); + newMind.TransferTo(mob); } else if (addSpawnPoints) { @@ -801,7 +801,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem if (!mind.OwnedEntity.HasValue) return; - _mindSystem.AddRole(mind, new TraitorRole(mind, _prototypeManager.Index(_nukeopsRuleConfig.OperativeRoleProto))); + mind.AddRole(new TraitorRole(mind, _prototypeManager.Index(_nukeopsRuleConfig.OperativeRoleProto))); SetOutfitCommand.SetOutfit(mind.OwnedEntity.Value, "SyndicateOperativeGearFull", EntityManager); } @@ -862,10 +862,10 @@ public sealed class NukeopsRuleSystem : GameRuleSystem } // Add pre-existing nuke operatives to the credit list. - var query = EntityQuery(true); + var query = EntityQuery(true); foreach (var (_, mindComp) in query) { - if (!mindComp.HasMind || !_mindSystem.TryGetSession(mindComp.Mind, out var session)) + if (mindComp.Mind == null || !mindComp.Mind.TryGetSession(out var session)) continue; var name = MetaData(mindComp.Owner).EntityName; _operativePlayers.Add(name, session); diff --git a/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs b/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs index d917342e1b..c5877ab513 100644 --- a/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/PiratesRuleSystem.cs @@ -2,7 +2,6 @@ using System.Linq; using Content.Server.Administration.Commands; using Content.Server.Cargo.Systems; using Content.Server.Chat.Managers; -using Content.Server.Mind; using Content.Server.Preferences.Managers; using Content.Server.Spawners.Components; using Content.Server.Station.Components; @@ -39,7 +38,6 @@ public sealed class PiratesRuleSystem : GameRuleSystem [Dependency] private readonly PricingSystem _pricingSystem = default!; [Dependency] private readonly MapLoaderSystem _map = default!; [Dependency] private readonly NamingSystem _namingSystem = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; [ViewVariables] private List _pirates = new(); @@ -208,13 +206,16 @@ public sealed class PiratesRuleSystem : GameRuleSystem var name = _namingSystem.GetName("Human", gender); var session = ops[i]; - var newMind = _mindSystem.CreateMind(session.UserId, name); - _mindSystem.ChangeOwningPlayer(newMind, session.UserId); + var newMind = new Mind.Mind(session.UserId) + { + CharacterName = name + }; + newMind.ChangeOwningPlayer(session.UserId); var mob = Spawn("MobHuman", _random.Pick(spawns)); MetaData(mob).EntityName = name; - _mindSystem.TransferTo(newMind, mob); + newMind.TransferTo(mob); var profile = _prefs.GetPreferences(session.UserId).SelectedCharacter as HumanoidCharacterProfile; _stationSpawningSystem.EquipStartingGear(mob, pirateGear, profile); diff --git a/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs b/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs index d9e3abba08..3c82367182 100644 --- a/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading; using Content.Server.Chat.Managers; using Content.Server.GameTicking.Rules.Configurations; -using Content.Server.Mind; using Content.Server.Players; using Content.Server.Roles; using Content.Server.Station.Components; @@ -51,7 +50,6 @@ public sealed class SuspicionRuleSystem : GameRuleSystem [Dependency] private readonly SharedDoorSystem _doorSystem = default!; [Dependency] private readonly EntityLookupSystem _lookupSystem = default!; [Dependency] private readonly UplinkSystem _uplink = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; public override string Prototype => "Suspicion"; @@ -173,11 +171,11 @@ public sealed class SuspicionRuleSystem : GameRuleSystem DebugTools.AssertNotNull(mind?.OwnedEntity); var traitorRole = new SuspicionTraitorRole(mind!, antagPrototype); - _mindSystem.AddRole(mind!, traitorRole); + mind!.AddRole(traitorRole); traitors.Add(traitorRole); // try to place uplink - _uplink.AddUplink(mind!.OwnedEntity!.Value, traitorStartingBalance); + _uplink.AddUplink(mind.OwnedEntity!.Value, traitorStartingBalance); } foreach (var player in list) @@ -187,7 +185,7 @@ public sealed class SuspicionRuleSystem : GameRuleSystem DebugTools.AssertNotNull(mind); - _mindSystem.AddRole(mind!, new SuspicionInnocentRole(mind!, antagPrototype)); + mind!.AddRole(new SuspicionInnocentRole(mind, antagPrototype)); } foreach (var traitor in traitors) @@ -206,11 +204,8 @@ public sealed class SuspicionRuleSystem : GameRuleSystem _chatManager.DispatchServerAnnouncement(Loc.GetString("rule-suspicion-added-announcement")); - var filter = Filter.Empty().AddWhere(session => - { - var mind = ((IPlayerSession) session).ContentData()?.Mind; - return mind != null && _mindSystem.HasRole(mind); - }); + var filter = Filter.Empty() + .AddWhere(session => ((IPlayerSession) session).ContentData()?.Mind?.HasRole() ?? false); SoundSystem.Play(_addedSound.GetSound(), filter, AudioParams.Default); @@ -306,7 +301,7 @@ public sealed class SuspicionRuleSystem : GameRuleSystem var mind = playerSession.ContentData()?.Mind; - if (mind != null && _mindSystem.HasRole(mind)) + if (mind != null && mind.HasRole()) traitorsAlive++; else innocentsAlive++; diff --git a/Content.Server/GameTicking/Rules/TraitorDeathMatchRuleSystem.cs b/Content.Server/GameTicking/Rules/TraitorDeathMatchRuleSystem.cs index 4c3f6214a4..f1bb0c1ee7 100644 --- a/Content.Server/GameTicking/Rules/TraitorDeathMatchRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/TraitorDeathMatchRuleSystem.cs @@ -3,7 +3,6 @@ using Content.Server.Atmos.EntitySystems; using Content.Server.Chat.Managers; using Content.Server.GameTicking.Rules.Configurations; using Content.Server.Hands.Components; -using Content.Server.Mind; using Content.Server.PDA; using Content.Server.Players; using Content.Server.Spawners.Components; @@ -42,7 +41,6 @@ public sealed class TraitorDeathMatchRuleSystem : GameRuleSystem [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Dependency] private readonly TransformSystem _transformSystem = default!; [Dependency] private readonly UplinkSystem _uplink = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; public override string Prototype => "TraitorDeathMatch"; @@ -83,7 +81,7 @@ public sealed class TraitorDeathMatchRuleSystem : GameRuleSystem var antagPrototype = _prototypeManager.Index(TraitorPrototypeID); var traitorRole = new TraitorRole(mind, antagPrototype); - _mindSystem.AddRole(mind, traitorRole); + mind.AddRole(traitorRole); // Delete anything that may contain "dangerous" role-specific items. // (This includes the PDA, as everybody gets the captain PDA in this mode for true-all-access reasons.) diff --git a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs index 9fee214de4..e005357f1f 100644 --- a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs @@ -1,6 +1,5 @@ using System.Linq; using Content.Server.Chat.Managers; -using Content.Server.Mind; using Content.Server.Objectives.Interfaces; using Content.Server.Players; using Content.Server.Roles; @@ -37,7 +36,6 @@ public sealed class TraitorRuleSystem : GameRuleSystem [Dependency] private readonly MobStateSystem _mobStateSystem = default!; [Dependency] private readonly UplinkSystem _uplink = default!; [Dependency] private readonly SharedAudioSystem _audioSystem = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; private ISawmill _sawmill = default!; @@ -256,7 +254,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem var antagPrototype = _prototypeManager.Index(TraitorPrototypeID); var traitorRole = new TraitorRole(mind, antagPrototype); - _mindSystem.AddRole(mind, traitorRole); + mind.AddRole(traitorRole); Traitors.Add(traitorRole); traitorRole.GreetTraitor(Codewords); @@ -272,7 +270,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem { var objective = _objectivesManager.GetRandomObjective(traitorRole.Mind, "TraitorObjectiveGroups"); if (objective == null) continue; - if (_mindSystem.TryAddObjective(traitorRole.Mind, objective)) + if (traitorRole.Mind.TryAddObjective(objective)) difficulty += objective.Difficulty; } @@ -344,7 +342,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem foreach (var traitor in Traitors) { var name = traitor.Mind.CharacterName; - _mindSystem.TryGetSession(traitor.Mind, out var session); + traitor.Mind.TryGetSession(out var session); var username = session?.Name; var objectives = traitor.Mind.AllObjectives.ToArray(); diff --git a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs index 126032a780..f51a22b42d 100644 --- a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs @@ -5,7 +5,6 @@ using Content.Server.Chat.Managers; using Content.Server.Disease; using Content.Server.Disease.Components; using Content.Server.Humanoid; -using Content.Server.Mind; using Content.Server.Mind.Components; using Content.Server.Players; using Content.Server.Popups; @@ -44,7 +43,6 @@ public sealed class ZombieRuleSystem : GameRuleSystem [Dependency] private readonly ActionsSystem _action = default!; [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly ZombifyOnDeathSystem _zombify = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; private Dictionary _initialInfectedNames = new(); @@ -104,7 +102,7 @@ public sealed class ZombieRuleSystem : GameRuleSystem { var meta = MetaData(survivor); var username = string.Empty; - if (TryComp(survivor, out var mindcomp)) + if (TryComp(survivor, out var mindcomp)) if (mindcomp.Mind != null && mindcomp.Mind.Session != null) username = mindcomp.Mind.Session.Name; @@ -286,7 +284,7 @@ public sealed class ZombieRuleSystem : GameRuleSystem DebugTools.AssertNotNull(mind.OwnedEntity); - _mindSystem.AddRole(mind, new TraitorRole(mind, _prototypeManager.Index(PatientZeroPrototypeID))); + mind.AddRole(new TraitorRole(mind, _prototypeManager.Index(PatientZeroPrototypeID))); var inCharacterName = string.Empty; if (mind.OwnedEntity != null) diff --git a/Content.Server/Ghost/GhostSystem.cs b/Content.Server/Ghost/GhostSystem.cs index 2b6dd4f716..5213ec83c0 100644 --- a/Content.Server/Ghost/GhostSystem.cs +++ b/Content.Server/Ghost/GhostSystem.cs @@ -92,13 +92,13 @@ namespace Content.Server.Ghost if (EntityManager.HasComponent(uid)) return; - if (!EntityManager.TryGetComponent(uid, out var mind) || !mind.HasMind || mind.Mind.IsVisitingEntity) + if (!EntityManager.TryGetComponent(uid, out var mind) || !mind.HasMind || mind.Mind!.IsVisitingEntity) return; if (component.MustBeDead && (_mobState.IsAlive(uid) || _mobState.IsCritical(uid))) return; - _ticker.OnGhostAttempt(mind.Mind, component.CanReturn); + _ticker.OnGhostAttempt(mind.Mind!, component.CanReturn); } private void OnGhostStartup(EntityUid uid, GhostComponent component, ComponentStartup args) @@ -199,7 +199,7 @@ namespace Content.Server.Ghost return; } - _mindSystem.UnVisit(actor.PlayerSession.ContentData()!.Mind); + actor.PlayerSession.ContentData()!.Mind?.UnVisit(); } private void OnGhostWarpToTargetRequest(GhostWarpToTargetRequestEvent msg, EntitySessionEventArgs args) @@ -236,7 +236,7 @@ namespace Content.Server.Ghost if (Deleted(uid) || Terminating(uid)) return; - if (EntityManager.TryGetComponent(uid, out var mind)) + if (EntityManager.TryGetComponent(uid, out var mind)) _mindSystem.SetGhostOnShutdown(uid, false, mind); EntityManager.DeleteEntity(uid); } @@ -260,7 +260,7 @@ namespace Content.Server.Ghost { if (attached == except) continue; - TryComp(attached, out var mind); + TryComp(attached, out var mind); string playerInfo = $"{EntityManager.GetComponent(attached).EntityName} ({mind?.Mind?.CurrentJob?.Name ?? "Unknown"})"; diff --git a/Content.Server/Ghost/Roles/Components/GhostRoleMobSpawnerComponent.cs b/Content.Server/Ghost/Roles/Components/GhostRoleMobSpawnerComponent.cs index 0833f738bc..720bd5387e 100644 --- a/Content.Server/Ghost/Roles/Components/GhostRoleMobSpawnerComponent.cs +++ b/Content.Server/Ghost/Roles/Components/GhostRoleMobSpawnerComponent.cs @@ -48,7 +48,7 @@ namespace Content.Server.Ghost.Roles.Components if (MakeSentient) MakeSentientCommand.MakeSentient(mob, _entMan, AllowMovement, AllowSpeech); - mob.EnsureComponent(); + mob.EnsureComponent(); var ghostRoleSystem = EntitySystem.Get(); ghostRoleSystem.GhostRoleInternalCreateMindAndTransfer(session, Owner, mob, this); diff --git a/Content.Server/Ghost/Roles/Components/GhostTakeoverAvailableComponent.cs b/Content.Server/Ghost/Roles/Components/GhostTakeoverAvailableComponent.cs index e6eec1d37b..0a9a9435f9 100644 --- a/Content.Server/Ghost/Roles/Components/GhostTakeoverAvailableComponent.cs +++ b/Content.Server/Ghost/Roles/Components/GhostTakeoverAvailableComponent.cs @@ -17,7 +17,7 @@ namespace Content.Server.Ghost.Roles.Components Taken = true; - var mind = Owner.EnsureComponent(); + var mind = Owner.EnsureComponent(); if (mind.HasMind) return false; diff --git a/Content.Server/Ghost/Roles/GhostRoleSystem.cs b/Content.Server/Ghost/Roles/GhostRoleSystem.cs index 4e17477b34..00f53c27fa 100644 --- a/Content.Server/Ghost/Roles/GhostRoleSystem.cs +++ b/Content.Server/Ghost/Roles/GhostRoleSystem.cs @@ -3,7 +3,6 @@ using Content.Server.EUI; using Content.Server.Ghost.Components; using Content.Server.Ghost.Roles.Components; using Content.Server.Ghost.Roles.UI; -using Content.Server.Mind; using Content.Server.Mind.Components; using Content.Server.Players; using Content.Shared.Administration; @@ -31,7 +30,6 @@ namespace Content.Server.Ghost.Roles [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly FollowerSystem _followerSystem = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; private uint _nextRoleIdentifier; private bool _needsUpdateGhostRoleCount = true; @@ -206,12 +204,14 @@ namespace Content.Server.Ghost.Roles DebugTools.AssertNotNull(contentData); - var newMind = _mindSystem.CreateMind(player.UserId, - EntityManager.GetComponent(mob).EntityName); - _mindSystem.AddRole(newMind, new GhostRoleMarkerRole(newMind, role.RoleName)); + var newMind = new Mind.Mind(player.UserId) + { + CharacterName = EntityManager.GetComponent(mob).EntityName + }; + newMind.AddRole(new GhostRoleMarkerRole(newMind, role.RoleName)); - _mindSystem.ChangeOwningPlayer(newMind, player.UserId); - _mindSystem.TransferTo(newMind, mob); + newMind.ChangeOwningPlayer(player.UserId); + newMind.TransferTo(mob); } public GhostRoleInfo[] GetGhostRolesInfo() diff --git a/Content.Server/Ghost/Roles/MakeGhostRoleCommand.cs b/Content.Server/Ghost/Roles/MakeGhostRoleCommand.cs index ceeeb52077..128afc20bc 100644 --- a/Content.Server/Ghost/Roles/MakeGhostRoleCommand.cs +++ b/Content.Server/Ghost/Roles/MakeGhostRoleCommand.cs @@ -35,7 +35,7 @@ namespace Content.Server.Ghost.Roles return; } - if (entityManager.TryGetComponent(uid, out MindContainerComponent? mind) && + if (entityManager.TryGetComponent(uid, out MindComponent? mind) && mind.HasMind) { shell.WriteLine($"Entity {metaData.EntityName} with id {uid} already has a mind."); diff --git a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs index 295ceb05d1..b418e6a6e3 100644 --- a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs +++ b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs @@ -246,7 +246,7 @@ namespace Content.Server.Medical.BiomassReclaimer // Reject souled bodies in easy mode. if (_configManager.GetCVar(CCVars.BiomassEasyMode) && HasComp(dragged) && - TryComp(dragged, out var mindComp)) + TryComp(dragged, out var mindComp)) { if (mindComp.Mind?.UserId != null && _playerManager.TryGetSessionById(mindComp.Mind.UserId.Value, out _)) return false; diff --git a/Content.Server/Mind/Commands/MakeSentientCommand.cs b/Content.Server/Mind/Commands/MakeSentientCommand.cs index 22ca8ebde0..d7f7f7087b 100644 --- a/Content.Server/Mind/Commands/MakeSentientCommand.cs +++ b/Content.Server/Mind/Commands/MakeSentientCommand.cs @@ -44,7 +44,7 @@ namespace Content.Server.Mind.Commands public static void MakeSentient(EntityUid uid, IEntityManager entityManager, bool allowMovement = true, bool allowSpeech = true) { - entityManager.EnsureComponent(uid); + entityManager.EnsureComponent(uid); if (allowMovement) { entityManager.EnsureComponent(uid); diff --git a/Content.Server/Mind/Commands/MindInfoCommand.cs b/Content.Server/Mind/Commands/MindInfoCommand.cs index 749135d260..fc2b0ff001 100644 --- a/Content.Server/Mind/Commands/MindInfoCommand.cs +++ b/Content.Server/Mind/Commands/MindInfoCommand.cs @@ -40,7 +40,7 @@ namespace Content.Server.Mind.Commands } var builder = new StringBuilder(); - builder.AppendFormat("player: {0}, mob: {1}\nroles: ", mind.UserId, mind.OwnedEntity); + builder.AppendFormat("player: {0}, mob: {1}\nroles: ", mind.UserId, mind.OwnedComponent?.Owner); foreach (var role in mind.AllRoles) { builder.AppendFormat("{0} ", role.Name); diff --git a/Content.Server/Mind/Commands/RenameCommand.cs b/Content.Server/Mind/Commands/RenameCommand.cs index 5fdb311f2e..7b3cb92c16 100644 --- a/Content.Server/Mind/Commands/RenameCommand.cs +++ b/Content.Server/Mind/Commands/RenameCommand.cs @@ -48,7 +48,7 @@ public sealed class RenameCommand : IConsoleCommand var entSysMan = IoCManager.Resolve(); - if (entMan.TryGetComponent(entityUid, out MindContainerComponent? mind) && mind.Mind != null) + if (entMan.TryGetComponent(entityUid, out MindComponent? mind) && mind.Mind != null) { // Mind mind.Mind.CharacterName = name; diff --git a/Content.Server/Mind/Components/MindContainerComponent.cs b/Content.Server/Mind/Components/MindComponent.cs similarity index 88% rename from Content.Server/Mind/Components/MindContainerComponent.cs rename to Content.Server/Mind/Components/MindComponent.cs index 5dad7a46c5..325e92123c 100644 --- a/Content.Server/Mind/Components/MindContainerComponent.cs +++ b/Content.Server/Mind/Components/MindComponent.cs @@ -1,13 +1,10 @@ -using System.Diagnostics.CodeAnalysis; -using YamlDotNet.Core.Tokens; - namespace Content.Server.Mind.Components { /// /// Stores a on a mob. /// [RegisterComponent, Access(typeof(MindSystem))] - public sealed class MindContainerComponent : Component + public sealed class MindComponent : Component { /// /// The mind controlling this mob. Can be null. @@ -20,7 +17,6 @@ namespace Content.Server.Mind.Components /// True if we have a mind, false otherwise. /// [ViewVariables] - [MemberNotNullWhen(true, nameof(Mind))] public bool HasMind => Mind != null; /// diff --git a/Content.Server/Mind/Components/VisitingMindComponent.cs b/Content.Server/Mind/Components/VisitingMindComponent.cs index 38e3c18c21..e7b81c0cc7 100644 --- a/Content.Server/Mind/Components/VisitingMindComponent.cs +++ b/Content.Server/Mind/Components/VisitingMindComponent.cs @@ -3,8 +3,14 @@ namespace Content.Server.Mind.Components [RegisterComponent] public sealed class VisitingMindComponent : Component { - [ViewVariables] - public Mind Mind { get; set; } = default!; + [ViewVariables] public Mind Mind { get; set; } = default!; + + protected override void OnRemove() + { + base.OnRemove(); + + Mind?.UnVisit(); + } } public sealed class MindUnvisitedMessage : EntityEventArgs diff --git a/Content.Server/Mind/Mind.cs b/Content.Server/Mind/Mind.cs index 81f26d55a9..c022300b89 100644 --- a/Content.Server/Mind/Mind.cs +++ b/Content.Server/Mind/Mind.cs @@ -1,9 +1,19 @@ +using System.Diagnostics.CodeAnalysis; using System.Linq; +using Content.Server.Administration.Logs; +using Content.Server.GameTicking; +using Content.Server.Ghost.Components; using Content.Server.Mind.Components; using Content.Server.Objectives; +using Content.Server.Players; using Content.Server.Roles; +using Content.Shared.Database; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; +using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Network; +using Robust.Shared.Utility; namespace Content.Server.Mind { @@ -19,9 +29,16 @@ namespace Content.Server.Mind /// public sealed class Mind { - internal readonly ISet Roles = new HashSet(); + private readonly MobStateSystem _mobStateSystem = default!; + private readonly GameTicker _gameTickerSystem = default!; + private readonly MindSystem _mindSystem = default!; + [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly IAdminLogManager _adminLogger = default!; - internal readonly List Objectives = new(); + private readonly ISet _roles = new HashSet(); + + private readonly List _objectives = new(); public string Briefing = String.Empty; @@ -31,32 +48,36 @@ namespace Content.Server.Mind /// The provided UserId is solely for tracking of intended owner. /// /// The session ID of the original owner (may get credited). - public Mind(NetUserId? userId) + public Mind(NetUserId userId) { OriginalOwnerUserId = userId; + IoCManager.InjectDependencies(this); + _entityManager.EntitySysManager.Resolve(ref _mobStateSystem); + _entityManager.EntitySysManager.Resolve(ref _gameTickerSystem); + _entityManager.EntitySysManager.Resolve(ref _mindSystem); } + // TODO: This session should be able to be changed, probably. /// /// The session ID of the player owning this mind. /// [ViewVariables] - public NetUserId? UserId { get; internal set; } + public NetUserId? UserId { get; private set; } /// /// The session ID of the original owner, if any. /// May end up used for round-end information (as the owner may have abandoned Mind since) /// [ViewVariables] - public NetUserId? OriginalOwnerUserId { get; } + public NetUserId OriginalOwnerUserId { get; } [ViewVariables] public bool IsVisitingEntity => VisitingEntity != null; [ViewVariables] - public EntityUid? VisitingEntity { get; set; } + public EntityUid? VisitingEntity { get; private set; } - [ViewVariables] - public EntityUid? CurrentEntity => VisitingEntity ?? OwnedEntity; + [ViewVariables] public EntityUid? CurrentEntity => VisitingEntity ?? OwnedEntity; [ViewVariables(VVAccess.ReadWrite)] public string? CharacterName { get; set; } @@ -66,33 +87,33 @@ namespace Content.Server.Mind /// Can be null - will be null if the Mind is not considered "dead". /// [ViewVariables] - public TimeSpan? TimeOfDeath { get; set; } + public TimeSpan? TimeOfDeath { get; set; } = null; /// /// The component currently owned by this mind. /// Can be null. /// [ViewVariables] - public MindContainerComponent? OwnedComponent { get; internal set; } + public MindComponent? OwnedComponent { get; private set; } /// /// The entity currently owned by this mind. /// Can be null. /// [ViewVariables] - public EntityUid? OwnedEntity { get; internal set; } + public EntityUid? OwnedEntity => OwnedComponent?.Owner; /// /// An enumerable over all the roles this mind has. /// [ViewVariables] - public IEnumerable AllRoles => Roles; + public IEnumerable AllRoles => _roles; /// /// An enumerable over all the objectives this mind has. /// [ViewVariables] - public IEnumerable AllObjectives => Objectives; + public IEnumerable AllObjectives => _objectives; /// /// Prevents user from ghosting out @@ -113,11 +134,343 @@ namespace Content.Server.Mind /// Can be null, in which case the player is currently not logged in. /// [ViewVariables] - public IPlayerSession? Session { get; internal set; } + public IPlayerSession? Session + { + get + { + if (!UserId.HasValue) + { + return null; + } + _playerManager.TryGetSessionById(UserId.Value, out var ret); + return ret; + } + } + + /// + /// True if this Mind is 'sufficiently dead' IC (objectives, endtext). + /// Note that this is *IC logic*, it's not necessarily tied to any specific truth. + /// "If administrators decide that zombies are dead, this returns true for zombies." + /// (Maybe you were looking for the action blocker system?) + /// + [ViewVariables] + public bool CharacterDeadIC => CharacterDeadPhysically; + + /// + /// True if the OwnedEntity of this mind is physically dead. + /// This specific definition, as opposed to CharacterDeadIC, is used to determine if ghosting should allow return. + /// + [ViewVariables] + public bool CharacterDeadPhysically + { + get + { + // This is written explicitly so that the logic can be understood. + // But it's also weird and potentially situational. + // Specific considerations when updating this: + // + Does being turned into a borg (if/when implemented) count as dead? + // *If not, add specific conditions to users of this property where applicable.* + // + Is being transformed into a donut 'dead'? + // TODO: Consider changing the way ghost roles work. + // Mind is an *IC* mind, therefore ghost takeover is IC revival right now. + // + Is it necessary to have a reference to a specific 'mind iteration' to cycle when certain events happen? + // (If being a borg or AI counts as dead, then this is highly likely, as it's still the same Mind for practical purposes.) + + // This can be null if they're deleted (spike / brain nom) + var targetMobState = _entityManager.GetComponentOrNull(OwnedEntity); + // This can be null if it's a brain (this happens very often) + // Brains are the result of gibbing so should definitely count as dead + if (targetMobState == null) + return true; + // They might actually be alive. + return _mobStateSystem.IsDead(OwnedEntity!.Value, targetMobState); + } + } + + /// + /// A string to represent the mind for logging + /// + private string MindOwnerLoggingString + { + get + { + if (OwnedEntity != null) + return _entityManager.ToPrettyString(OwnedEntity.Value); + if (UserId != null) + return UserId.Value.ToString(); + return "(originally " + OriginalOwnerUserId + ")"; + } + } + + /// + /// Gives this mind a new role. + /// + /// The type of the role to give. + /// The instance of the role. + /// + /// Thrown if we already have a role with this type. + /// + public Role AddRole(Role role) + { + if (_roles.Contains(role)) + { + throw new ArgumentException($"We already have this role: {role}"); + } + + _roles.Add(role); + role.Greet(); + + var message = new RoleAddedEvent(this, role); + if (OwnedEntity != null) + { + _entityManager.EventBus.RaiseLocalEvent(OwnedEntity.Value, message, true); + } + _adminLogger.Add(LogType.Mind, LogImpact.Low, + $"'{role.Name}' added to mind of {MindOwnerLoggingString}"); + + return role; + } + + /// + /// Removes a role from this mind. + /// + /// The type of the role to remove. + /// + /// Thrown if we do not have this role. + /// + public void RemoveRole(Role role) + { + if (!_roles.Contains(role)) + { + throw new ArgumentException($"We do not have this role: {role}"); + } + + _roles.Remove(role); + + var message = new RoleRemovedEvent(this, role); + + if (OwnedEntity != null) + { + _entityManager.EventBus.RaiseLocalEvent(OwnedEntity.Value, message, true); + } + _adminLogger.Add(LogType.Mind, LogImpact.Low, + $"'{role.Name}' removed from mind of {MindOwnerLoggingString}"); + } + + public bool HasRole() where T : Role + { + var t = typeof(T); + + return _roles.Any(role => role.GetType() == t); + } /// /// Gets the current job /// - public Job? CurrentJob => Roles.OfType().SingleOrDefault(); + public Job? CurrentJob => _roles.OfType().SingleOrDefault(); + + /// + /// Adds an objective to this mind. + /// + public bool TryAddObjective(ObjectivePrototype objectivePrototype) + { + if (!objectivePrototype.CanBeAssigned(this)) + return false; + var objective = objectivePrototype.GetObjective(this); + if (_objectives.Contains(objective)) + return false; + + foreach (var condition in objective.Conditions) + _adminLogger.Add(LogType.Mind, LogImpact.Low, $"'{condition.Title}' added to mind of {MindOwnerLoggingString}"); + + + _objectives.Add(objective); + return true; + } + + /// + /// Removes an objective to this mind. + /// + /// Returns true if the removal succeeded. + public bool TryRemoveObjective(int index) + { + if (_objectives.Count >= index) return false; + + var objective = _objectives[index]; + + foreach (var condition in objective.Conditions) + _adminLogger.Add(LogType.Mind, LogImpact.Low, $"'{condition.Title}' removed from the mind of {MindOwnerLoggingString}"); + + _objectives.Remove(objective); + return true; + } + + /// + /// Transfer this mind's control over to a new entity. + /// + /// + /// The entity to control. + /// Can be null, in which case it will simply detach the mind from any entity. + /// + /// + /// If true, skips ghost check for Visiting Entity + /// + /// + /// Thrown if is already owned by another mind. + /// + public void TransferTo(EntityUid? entity, bool ghostCheckOverride = false) + { + // Looks like caller just wants us to go back to normal. + if (entity == OwnedEntity) + { + UnVisit(); + return; + } + + MindComponent? component = null; + var alreadyAttached = false; + + if (entity != null) + { + if (!_entityManager.TryGetComponent(entity.Value, out component)) + { + component = _entityManager.AddComponent(entity.Value); + } + else if (component.HasMind) + { + _gameTickerSystem.OnGhostAttempt(component.Mind!, false); + } + + if (_entityManager.TryGetComponent(entity.Value, out var actor)) + { + // Happens when transferring to your currently visited entity. + if (actor.PlayerSession != Session) + { + throw new ArgumentException("Visit target already has a session.", nameof(entity)); + } + + alreadyAttached = true; + } + } + + if(OwnedComponent != null) + _mindSystem.InternalEjectMind(OwnedComponent.Owner, OwnedComponent); + + OwnedComponent = component; + if(OwnedComponent != null) + _mindSystem.InternalAssignMind(OwnedComponent.Owner, this, OwnedComponent); + + // Don't do the full deletion cleanup if we're transferring to our visitingentity + if (alreadyAttached) + { + // Set VisitingEntity null first so the removal of VisitingMind doesn't get through Unvisit() and delete what we're visiting. + // Yes this control flow sucks. + VisitingEntity = null; + _entityManager.RemoveComponent(entity!.Value); + } + else if (VisitingEntity != null + && (ghostCheckOverride // to force mind transfer, for example from ControlMobVerb + || !_entityManager.TryGetComponent(VisitingEntity!, out GhostComponent? ghostComponent) // visiting entity is not a Ghost + || !ghostComponent.CanReturnToBody)) // it is a ghost, but cannot return to body anyway, so it's okay + { + RemoveVisitingEntity(); + } + + // Player is CURRENTLY connected. + if (Session != null && !alreadyAttached && VisitingEntity == null) + { + Session.AttachToEntity(entity); + Logger.Info($"Session {Session.Name} transferred to entity {entity}."); + } + } + + public void ChangeOwningPlayer(NetUserId? newOwner) + { + var playerMgr = IoCManager.Resolve(); + PlayerData? newOwnerData = null; + + if (newOwner.HasValue) + { + if (!playerMgr.TryGetPlayerData(newOwner.Value, out var uncast)) + { + // This restriction is because I'm too lazy to initialize the player data + // for a client that hasn't logged in yet. + // Go ahead and remove it if you need. + throw new ArgumentException("new owner must have previously logged into the server."); + } + + newOwnerData = uncast.ContentData(); + } + + // Make sure to remove control from our old owner if they're logged in. + var oldSession = Session; + oldSession?.AttachToEntity(null); + + if (UserId.HasValue) + { + var data = playerMgr.GetPlayerData(UserId.Value).ContentData(); + DebugTools.AssertNotNull(data); + data!.UpdateMindFromMindChangeOwningPlayer(null); + } + + UserId = newOwner; + if (!newOwner.HasValue) + { + return; + } + + // Yank new owner out of their old mind too. + // Can I mention how much I love the word yank? + DebugTools.AssertNotNull(newOwnerData); + newOwnerData!.Mind?.ChangeOwningPlayer(null); + newOwnerData.UpdateMindFromMindChangeOwningPlayer(this); + } + + public void Visit(EntityUid entity) + { + Session?.AttachToEntity(entity); + VisitingEntity = entity; + + var comp = _entityManager.AddComponent(entity); + comp.Mind = this; + + Logger.Info($"Session {Session?.Name} visiting entity {entity}."); + } + + /// + /// Returns the mind to its original entity. + /// + public void UnVisit() + { + var currentEntity = Session?.AttachedEntity; + Session?.AttachToEntity(OwnedEntity); + RemoveVisitingEntity(); + + if (Session != null && OwnedEntity != null && currentEntity != OwnedEntity) + _adminLogger.Add(LogType.Mind, LogImpact.Low, + $"{Session.Name} returned to {_entityManager.ToPrettyString(OwnedEntity.Value)}"); + } + + /// + /// Cleans up the VisitingEntity. + /// + private void RemoveVisitingEntity() + { + if (VisitingEntity == null) + return; + + var oldVisitingEnt = VisitingEntity.Value; + // Null this before removing the component to avoid any infinite loops. + VisitingEntity = null; + + DebugTools.AssertNotNull(oldVisitingEnt); + _entityManager.RemoveComponent(oldVisitingEnt); + _entityManager.EventBus.RaiseLocalEvent(oldVisitingEnt, new MindUnvisitedMessage(), true); + } + + public bool TryGetSession([NotNullWhen(true)] out IPlayerSession? session) + { + return (session = Session) != null; + } } } diff --git a/Content.Server/Mind/MindSystem.cs b/Content.Server/Mind/MindSystem.cs index 1bc99ab78e..f9101234ce 100644 --- a/Content.Server/Mind/MindSystem.cs +++ b/Content.Server/Mind/MindSystem.cs @@ -1,24 +1,13 @@ -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using Content.Server.Administration.Logs; using Content.Server.GameTicking; using Content.Server.Ghost; using Content.Server.Ghost.Components; using Content.Server.Mind.Components; -using Content.Server.Objectives; -using Content.Server.Players; -using Content.Server.Roles; -using Content.Shared.Database; using Content.Shared.Examine; +using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; using Content.Shared.Interaction.Events; -using Content.Shared.Mobs.Components; -using Robust.Server.GameObjects; -using Robust.Server.Player; using Robust.Shared.Map; -using Robust.Shared.Network; using Robust.Shared.Timing; -using Robust.Shared.Utility; namespace Content.Server.Mind; @@ -28,25 +17,17 @@ public sealed class MindSystem : EntitySystem [Dependency] private readonly GameTicker _gameTicker = default!; [Dependency] private readonly MobStateSystem _mobStateSystem = default!; [Dependency] private readonly GhostSystem _ghostSystem = default!; - [Dependency] private readonly IAdminLogManager _adminLogger = default!; - [Dependency] private readonly IPlayerManager _playerManager = default!; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnShutdown); - SubscribeLocalEvent(OnExamined); - SubscribeLocalEvent(OnSuicide); - SubscribeLocalEvent(OnVisitingMindRemoved); - } - - private void OnVisitingMindRemoved(EntityUid uid, VisitingMindComponent component, ComponentRemove args) - { - UnVisit(component.Mind); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnExamined); + SubscribeLocalEvent(OnSuicide); } - public void SetGhostOnShutdown(EntityUid uid, bool value, MindContainerComponent? mind = null) + public void SetGhostOnShutdown(EntityUid uid, bool value, MindComponent? mind = null) { if (!Resolve(uid, ref mind)) return; @@ -56,10 +37,10 @@ public sealed class MindSystem : EntitySystem /// /// Don't call this unless you know what the hell you're doing. - /// Use instead. + /// Use instead. /// If that doesn't cover it, make something to cover it. /// - private void InternalAssignMind(EntityUid uid, Mind value, MindContainerComponent? mind = null) + public void InternalAssignMind(EntityUid uid, Mind value, MindComponent? mind = null) { if (!Resolve(uid, ref mind)) return; @@ -70,10 +51,10 @@ public sealed class MindSystem : EntitySystem /// /// Don't call this unless you know what the hell you're doing. - /// Use instead. + /// Use instead. /// If that doesn't cover it, make something to cover it. /// - private void InternalEjectMind(EntityUid uid, MindContainerComponent? mind = null) + public void InternalEjectMind(EntityUid uid, MindComponent? mind = null) { if (!Resolve(uid, ref mind)) return; @@ -84,501 +65,109 @@ public sealed class MindSystem : EntitySystem mind.Mind = null; } - private void OnShutdown(EntityUid uid, MindContainerComponent mindContainerComp, ComponentShutdown args) + private void OnShutdown(EntityUid uid, MindComponent mind, ComponentShutdown args) { // Let's not create ghosts if not in the middle of the round. if (_gameTicker.RunLevel != GameRunLevel.InRound) return; - if (!TryGetMind(uid, out var mind, mindContainerComp)) - return; - - if (mind.VisitingEntity is {Valid: true} visiting) - { - if (TryComp(visiting, out GhostComponent? ghost)) - { - _ghostSystem.SetCanReturnToBody(ghost, false); - } - - TransferTo(mind, visiting); - } - else if (mindContainerComp.GhostOnShutdown) + if (mind.HasMind) { - // Changing an entities parents while deleting is VERY sus. This WILL throw exceptions. - // TODO: just find the applicable spawn position directly without actually updating the transform's parent. - Transform(uid).AttachToGridOrMap(); - var spawnPosition = Transform(uid).Coordinates; - - // Use a regular timer here because the entity has probably been deleted. - Timer.Spawn(0, () => + if (mind.Mind?.VisitingEntity is {Valid: true} visiting) { - // Make extra sure the round didn't end between spawning the timer and it being executed. - if (_gameTicker.RunLevel != GameRunLevel.InRound) - return; - - // Async this so that we don't throw if the grid we're on is being deleted. - var gridId = spawnPosition.GetGridUid(EntityManager); - if (!spawnPosition.IsValid(EntityManager) || gridId == EntityUid.Invalid || !_mapManager.GridExists(gridId)) - { - spawnPosition = _gameTicker.GetObserverSpawnPoint(); - } - - // TODO refactor observer spawning. - // please. - if (!spawnPosition.IsValid(EntityManager)) + if (TryComp(visiting, out GhostComponent? ghost)) { - // This should be an error, if it didn't cause tests to start erroring when they delete a player. - Logger.WarningS("mind", $"Entity \"{ToPrettyString(uid)}\" for {mind.CharacterName} was deleted, and no applicable spawn location is available."); - TransferTo(mind, null); - return; + _ghostSystem.SetCanReturnToBody(ghost, false); } - var ghost = Spawn("MobObserver", spawnPosition); - var ghostComponent = Comp(ghost); - _ghostSystem.SetCanReturnToBody(ghostComponent, false); - - // Log these to make sure they're not causing the GameTicker round restart bugs... - Logger.DebugS("mind", $"Entity \"{ToPrettyString(uid)}\" for {mind.CharacterName} was deleted, spawned \"{ToPrettyString(ghost)}\"."); - - var val = mind.CharacterName ?? string.Empty; - MetaData(ghost).EntityName = val; - TransferTo(mind, ghost); - }); - } - } - - private void OnExamined(EntityUid uid, MindContainerComponent mindContainer, ExaminedEvent args) - { - if (!mindContainer.ShowExamineInfo || !args.IsInDetailsRange) - return; - - var dead = _mobStateSystem.IsDead(uid); - var hasSession = mindContainer.Mind?.Session; - - if (dead && hasSession == null) - args.PushMarkup($"[color=yellow]{Loc.GetString("comp-mind-examined-dead-and-ssd", ("ent", uid))}[/color]"); - else if (dead) - args.PushMarkup($"[color=red]{Loc.GetString("comp-mind-examined-dead", ("ent", uid))}[/color]"); - else if (!mindContainer.HasMind) - args.PushMarkup($"[color=mediumpurple]{Loc.GetString("comp-mind-examined-catatonic", ("ent", uid))}[/color]"); - else if (hasSession == null) - args.PushMarkup($"[color=yellow]{Loc.GetString("comp-mind-examined-ssd", ("ent", uid))}[/color]"); - } - - private void OnSuicide(EntityUid uid, MindContainerComponent component, SuicideEvent args) - { - if (args.Handled) - return; - - if (component.HasMind && component.Mind.PreventSuicide) - { - args.BlockSuicideAttempt(true); - } - } - - public Mind? GetMind(EntityUid uid, MindContainerComponent? mind = null) - { - if (!Resolve(uid, ref mind)) - return null; - - if (mind.HasMind) - return mind.Mind; - return null; - } - - public Mind CreateMind(NetUserId? userId, string? name = null) - { - var mind = new Mind(userId); - mind.CharacterName = name; - ChangeOwningPlayer(mind, userId); - return mind; - } - - /// - /// True if the OwnedEntity of this mind is physically dead. - /// This specific definition, as opposed to CharacterDeadIC, is used to determine if ghosting should allow return. - /// - public bool IsCharacterDeadPhysically(Mind mind) - { - // This is written explicitly so that the logic can be understood. - // But it's also weird and potentially situational. - // Specific considerations when updating this: - // + Does being turned into a borg (if/when implemented) count as dead? - // *If not, add specific conditions to users of this property where applicable.* - // + Is being transformed into a donut 'dead'? - // TODO: Consider changing the way ghost roles work. - // Mind is an *IC* mind, therefore ghost takeover is IC revival right now. - // + Is it necessary to have a reference to a specific 'mind iteration' to cycle when certain events happen? - // (If being a borg or AI counts as dead, then this is highly likely, as it's still the same Mind for practical purposes.) - - if (mind.OwnedEntity == null) - return true; - - // This can be null if they're deleted (spike / brain nom) - var targetMobState = EntityManager.GetComponentOrNull(mind.OwnedEntity); - // This can be null if it's a brain (this happens very often) - // Brains are the result of gibbing so should definitely count as dead - if (targetMobState == null) - return true; - // They might actually be alive. - return _mobStateSystem.IsDead(mind.OwnedEntity.Value, targetMobState); - } - - public void Visit(Mind mind, EntityUid entity) - { - mind.Session?.AttachToEntity(entity); - mind.VisitingEntity = entity; - - var comp = AddComp(entity); - comp.Mind = mind; - - Logger.Info($"Session {mind.Session?.Name} visiting entity {entity}."); - } - - /// - /// Returns the mind to its original entity. - /// - public void UnVisit(Mind? mind) - { - if (mind == null) - return; - - var currentEntity = mind.Session?.AttachedEntity; - mind.Session?.AttachToEntity(mind.OwnedEntity); - RemoveVisitingEntity(mind); - - var owned = mind.OwnedEntity; - if (mind.Session != null && owned != null && owned != currentEntity) - { - _adminLogger.Add(LogType.Mind, LogImpact.Low, - $"{mind.Session.Name} returned to {ToPrettyString(owned.Value)}"); - } - } - - /// - /// Cleans up the VisitingEntity. - /// - /// - private void RemoveVisitingEntity(Mind mind) - { - if (mind.VisitingEntity == null) - return; - - var oldVisitingEnt = mind.VisitingEntity.Value; - // Null this before removing the component to avoid any infinite loops. - mind.VisitingEntity = null; - - DebugTools.AssertNotNull(oldVisitingEnt); - RemComp(oldVisitingEnt); - RaiseLocalEvent(oldVisitingEnt, new MindUnvisitedMessage(), true); - } - - /// - /// Transfer this mind's control over to a new entity. - /// - /// The mind to transfer - /// - /// The entity to control. - /// Can be null, in which case it will simply detach the mind from any entity. - /// - /// - /// If true, skips ghost check for Visiting Entity - /// - /// - /// Thrown if is already owned by another mind. - /// - public void TransferTo(Mind mind, EntityUid? entity, bool ghostCheckOverride = false) - { - // Looks like caller just wants us to go back to normal. - if (entity == mind.OwnedEntity) - { - UnVisit(mind); - return; - } - - MindContainerComponent? component = null; - var alreadyAttached = false; - - if (entity != null) - { - if (!TryComp(entity.Value, out component)) - { - component = AddComp(entity.Value); + mind.Mind!.TransferTo(visiting); } - else if (component.HasMind) + else if (mind.GhostOnShutdown) { - _gameTicker.OnGhostAttempt(component.Mind, false); - } + // Changing an entities parents while deleting is VERY sus. This WILL throw exceptions. + // TODO: just find the applicable spawn position dirctly without actually updating the transform's parent. + Transform(uid).AttachToGridOrMap(); + var spawnPosition = Transform(uid).Coordinates; - if (TryComp(entity.Value, out var actor)) - { - // Happens when transferring to your currently visited entity. - if (actor.PlayerSession != mind.Session) + // Use a regular timer here because the entity has probably been deleted. + Timer.Spawn(0, () => { - throw new ArgumentException("Visit target already has a session.", nameof(entity)); - } - - alreadyAttached = true; + // Make extra sure the round didn't end between spawning the timer and it being executed. + if (_gameTicker.RunLevel != GameRunLevel.InRound) + return; + + // Async this so that we don't throw if the grid we're on is being deleted. + var gridId = spawnPosition.GetGridUid(EntityManager); + if (!spawnPosition.IsValid(EntityManager) || gridId == EntityUid.Invalid || !_mapManager.GridExists(gridId)) + { + spawnPosition = _gameTicker.GetObserverSpawnPoint(); + } + + // TODO refactor observer spawning. + // please. + if (!spawnPosition.IsValid(EntityManager)) + { + // This should be an error, if it didn't cause tests to start erroring when they delete a player. + Logger.WarningS("mind", $"Entity \"{ToPrettyString(uid)}\" for {mind.Mind?.CharacterName} was deleted, and no applicable spawn location is available."); + mind.Mind?.TransferTo(null); + return; + } + + var ghost = Spawn("MobObserver", spawnPosition); + var ghostComponent = Comp(ghost); + _ghostSystem.SetCanReturnToBody(ghostComponent, false); + + // Log these to make sure they're not causing the GameTicker round restart bugs... + Logger.DebugS("mind", $"Entity \"{ToPrettyString(uid)}\" for {mind.Mind?.CharacterName} was deleted, spawned \"{ToPrettyString(ghost)}\"."); + + if (mind.Mind == null) + return; + + var val = mind.Mind.CharacterName ?? string.Empty; + MetaData(ghost).EntityName = val; + mind.Mind.TransferTo(ghost); + }); } } - - var oldComp = mind.OwnedComponent; - var oldEntity = mind.OwnedEntity; - if(oldComp != null && oldEntity != null) - InternalEjectMind(oldEntity.Value, oldComp); - - SetOwnedEntity(mind, entity, component); - if (mind.OwnedComponent != null) - InternalAssignMind(mind.OwnedEntity!.Value, mind, mind.OwnedComponent); - - // Don't do the full deletion cleanup if we're transferring to our VisitingEntity - if (alreadyAttached) - { - // Set VisitingEntity null first so the removal of VisitingMind doesn't get through Unvisit() and delete what we're visiting. - // Yes this control flow sucks. - mind.VisitingEntity = null; - RemComp(entity!.Value); - } - else if (mind.VisitingEntity != null - && (ghostCheckOverride // to force mind transfer, for example from ControlMobVerb - || !TryComp(mind.VisitingEntity!, out GhostComponent? ghostComponent) // visiting entity is not a Ghost - || !ghostComponent.CanReturnToBody)) // it is a ghost, but cannot return to body anyway, so it's okay - { - RemoveVisitingEntity(mind); - } - - // Player is CURRENTLY connected. - if (mind.Session != null && !alreadyAttached && mind.VisitingEntity == null) - { - mind.Session.AttachToEntity(entity); - Logger.Info($"Session {mind.Session.Name} transferred to entity {entity}."); - } } - public void ChangeOwningPlayer(Mind mind, NetUserId? newOwner) + private void OnExamined(EntityUid uid, MindComponent mind, ExaminedEvent args) { - // Make sure to remove control from our old owner if they're logged in. - var oldSession = mind.Session; - oldSession?.AttachToEntity(null); - - if (mind.UserId.HasValue) - { - if (_playerManager.TryGetPlayerData(mind.UserId.Value, out var oldUncast)) - { - var data = oldUncast.ContentData(); - DebugTools.AssertNotNull(data); - data!.UpdateMindFromMindChangeOwningPlayer(null); - } - else - { - Logger.Warning($"Mind UserId {newOwner} is does not exist in PlayerManager"); - } - } - - SetUserId(mind, newOwner); - if (!newOwner.HasValue) + if (!mind.ShowExamineInfo || !args.IsInDetailsRange) { return; } - - if (!_playerManager.TryGetPlayerData(newOwner.Value, out var uncast)) - { - // This restriction is because I'm too lazy to initialize the player data - // for a client that hasn't logged in yet. - // Go ahead and remove it if you need. - throw new ArgumentException("New owner must have previously logged into the server.", nameof(newOwner)); - } - - // PlayerData? newOwnerData = null; - var newOwnerData = uncast.ContentData(); - - // Yank new owner out of their old mind too. - // Can I mention how much I love the word yank? - DebugTools.AssertNotNull(newOwnerData); - if (newOwnerData!.Mind != null) - ChangeOwningPlayer(newOwnerData.Mind, null); - newOwnerData.UpdateMindFromMindChangeOwningPlayer(mind); - } - - /// - /// Adds an objective to this mind. - /// - public bool TryAddObjective(Mind mind, ObjectivePrototype objectivePrototype) - { - if (!objectivePrototype.CanBeAssigned(mind)) - return false; - var objective = objectivePrototype.GetObjective(mind); - if (mind.Objectives.Contains(objective)) - return false; - - foreach (var condition in objective.Conditions) - { - _adminLogger.Add(LogType.Mind, LogImpact.Low, $"'{condition.Title}' added to mind of {MindOwnerLoggingString(mind)}"); - } - - - mind.Objectives.Add(objective); - return true; - } - - /// - /// Removes an objective to this mind. - /// - /// Returns true if the removal succeeded. - public bool TryRemoveObjective(Mind mind, int index) - { - if (mind.Objectives.Count >= index) return false; - var objective = mind.Objectives[index]; + var dead = TryComp(uid, out var state) && _mobStateSystem.IsDead(uid, state); - foreach (var condition in objective.Conditions) + if (dead) { - _adminLogger.Add(LogType.Mind, LogImpact.Low, $"'{condition.Title}' removed from the mind of {MindOwnerLoggingString(mind)}"); + if (mind.Mind?.Session == null) { + // Player has no session attached and dead + args.PushMarkup($"[color=yellow]{Loc.GetString("mind-component-no-mind-and-dead-text", ("ent", uid))}[/color]"); + } else { + // Player is dead with session + args.PushMarkup($"[color=red]{Loc.GetString("comp-mind-examined-dead", ("ent", uid))}[/color]"); + } } - - mind.Objectives.Remove(objective); - return true; - } - - /// - /// Gives this mind a new role. - /// - /// The mind to add the role to. - /// The type of the role to give. - /// The instance of the role. - /// - /// Thrown if we already have a role with this type. - /// - public void AddRole(Mind mind, Role role) - { - if (mind.Roles.Contains(role)) + else if (!mind.HasMind) { - throw new ArgumentException($"We already have this role: {role}"); + args.PushMarkup($"[color=mediumpurple]{Loc.GetString("comp-mind-examined-catatonic", ("ent", uid))}[/color]"); } - - mind.Roles.Add(role); - role.Greet(); - - var message = new RoleAddedEvent(mind, role); - if (mind.OwnedEntity != null) + else if (mind.Mind?.Session == null) { - RaiseLocalEvent(mind.OwnedEntity.Value, message, true); + args.PushMarkup($"[color=yellow]{Loc.GetString("comp-mind-examined-ssd", ("ent", uid))}[/color]"); } - - _adminLogger.Add(LogType.Mind, LogImpact.Low, - $"'{role.Name}' added to mind of {MindOwnerLoggingString(mind)}"); } - /// - /// Removes a role from this mind. - /// - /// The mind to remove the role from. - /// The type of the role to remove. - /// - /// Thrown if we do not have this role. - /// - public void RemoveRole(Mind mind, Role role) + private void OnSuicide(EntityUid uid, MindComponent component, SuicideEvent args) { - if (!mind.Roles.Contains(role)) - { - throw new ArgumentException($"We do not have this role: {role}"); - } - - mind.Roles.Remove(role); - - var message = new RoleRemovedEvent(mind, role); + if (args.Handled) + return; - if (mind.OwnedEntity != null) + if (component.HasMind && component.Mind!.PreventSuicide) { - RaiseLocalEvent(mind.OwnedEntity.Value, message, true); + args.BlockSuicideAttempt(true); } - _adminLogger.Add(LogType.Mind, LogImpact.Low, - $"'{role.Name}' removed from mind of {MindOwnerLoggingString(mind)}"); - } - - public bool HasRole(Mind mind) where T : Role - { - var t = typeof(T); - - return mind.Roles.Any(role => role.GetType() == t); - } - - public bool TryGetSession(Mind mind, [NotNullWhen(true)] out IPlayerSession? session) - { - return (session = mind.Session) != null; - } - - /// - /// Gets a mind from uid and/or MindContainerComponent. Used for null checks. - /// - /// Entity UID that owns the mind. - /// The returned mind. - /// Mind component on to get the mind from. - /// True if mind found. False if not. - public bool TryGetMind(EntityUid uid, [NotNullWhen(true)] out Mind? mind, MindContainerComponent? mindContainerComponent = null) - { - mind = null; - if (!Resolve(uid, ref mindContainerComponent)) - return false; - - if (!mindContainerComponent.HasMind) - return false; - - mind = mindContainerComponent.Mind; - return true; - } - - /// - /// Sets the Mind's OwnedComponent and OwnedEntity - /// - /// Mind to set OwnedComponent and OwnedEntity on - /// Entity owned by - /// MindContainerComponent owned by - private void SetOwnedEntity(Mind mind, EntityUid? uid, MindContainerComponent? mindContainerComponent) - { - if (uid != null) - Resolve(uid.Value, ref mindContainerComponent); - - mind.OwnedEntity = uid; - mind.OwnedComponent = mindContainerComponent; - } - - /// - /// Sets the Mind's UserId and Session - /// - /// - /// - private void SetUserId(Mind mind, NetUserId? userId) - { - mind.UserId = userId; - - if (!userId.HasValue) - return; - - _playerManager.TryGetSessionById(userId.Value, out var ret); - mind.Session = ret; - } - - /// - /// True if this Mind is 'sufficiently dead' IC (Objectives, EndText). - /// Note that this is *IC logic*, it's not necessarily tied to any specific truth. - /// "If administrators decide that zombies are dead, this returns true for zombies." - /// (Maybe you were looking for the action blocker system?) - /// - public bool IsCharacterDeadIc(Mind mind) - { - return IsCharacterDeadPhysically(mind); - } - - /// - /// A string to represent the mind for logging - /// - private string MindOwnerLoggingString(Mind mind) - { - if (mind.OwnedEntity != null) - return ToPrettyString(mind.OwnedEntity.Value); - if (mind.UserId != null) - return mind.UserId.Value.ToString(); - return "(originally " + mind.OriginalOwnerUserId + ")"; } } diff --git a/Content.Server/Mind/MindTrackerSystem.cs b/Content.Server/Mind/MindTrackerSystem.cs index 2ab76ce9af..49f2400b08 100644 --- a/Content.Server/Mind/MindTrackerSystem.cs +++ b/Content.Server/Mind/MindTrackerSystem.cs @@ -20,7 +20,7 @@ namespace Content.Server.Mind base.Initialize(); SubscribeLocalEvent(Reset); - SubscribeLocalEvent(OnMindAdded); + SubscribeLocalEvent(OnMindAdded); } void Reset(RoundRestartCleanupEvent ev) @@ -28,7 +28,7 @@ namespace Content.Server.Mind AllMinds.Clear(); } - void OnMindAdded(EntityUid uid, MindContainerComponent mc, MindAddedMessage args) + void OnMindAdded(EntityUid uid, MindComponent mc, MindAddedMessage args) { var mind = mc.Mind; if (mind != null) diff --git a/Content.Server/Mind/TransferMindOnGibSystem.cs b/Content.Server/Mind/TransferMindOnGibSystem.cs index d499d6a4dd..1aed10c324 100644 --- a/Content.Server/Mind/TransferMindOnGibSystem.cs +++ b/Content.Server/Mind/TransferMindOnGibSystem.cs @@ -15,7 +15,6 @@ public sealed class TransferMindOnGibSystem : EntitySystem { [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly TagSystem _tag = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; /// public override void Initialize() @@ -25,7 +24,7 @@ public sealed class TransferMindOnGibSystem : EntitySystem private void OnGib(EntityUid uid, TransferMindOnGibComponent component, BeingGibbedEvent args) { - if (!TryComp(uid, out var mindcomp) || mindcomp.Mind == null) + if (!TryComp(uid, out var mindcomp) || mindcomp.Mind == null) return; var validParts = args.GibbedParts.Where(p => _tag.HasTag(p, component.TargetTag)).ToHashSet(); @@ -33,6 +32,6 @@ public sealed class TransferMindOnGibSystem : EntitySystem return; var ent = _random.Pick(validParts); - _mindSystem.TransferTo(mindcomp.Mind, ent); + mindcomp.Mind.TransferTo(ent); } } diff --git a/Content.Server/Objectives/Commands/AddObjectiveCommand.cs b/Content.Server/Objectives/Commands/AddObjectiveCommand.cs index 7353763b63..ea4372b1aa 100644 --- a/Content.Server/Objectives/Commands/AddObjectiveCommand.cs +++ b/Content.Server/Objectives/Commands/AddObjectiveCommand.cs @@ -1,5 +1,4 @@ using Content.Server.Administration; -using Content.Server.Mind; using Content.Server.Players; using Content.Shared.Administration; using Robust.Server.Player; @@ -11,8 +10,6 @@ namespace Content.Server.Objectives.Commands [AdminCommand(AdminFlags.Admin)] public sealed class AddObjectiveCommand : IConsoleCommand { - [Dependency] private readonly IEntityManager _entityManager = default!; - public string Command => "addobjective"; public string Description => "Adds an objective to the player's mind."; public string Help => "addobjective "; @@ -45,10 +42,8 @@ namespace Content.Server.Objectives.Commands shell.WriteLine($"Can't find matching ObjectivePrototype {objectivePrototype}"); return; } - - var mindSystem = _entityManager.System(); - if (!mindSystem.TryAddObjective(mind, objectivePrototype)) + if (!mind.TryAddObjective(objectivePrototype)) { shell.WriteLine("Objective requirements dont allow that objective to be added."); } diff --git a/Content.Server/Objectives/Commands/RemoveObjectiveCommand.cs b/Content.Server/Objectives/Commands/RemoveObjectiveCommand.cs index c0846a1e43..96979ab6fa 100644 --- a/Content.Server/Objectives/Commands/RemoveObjectiveCommand.cs +++ b/Content.Server/Objectives/Commands/RemoveObjectiveCommand.cs @@ -1,5 +1,4 @@ using Content.Server.Administration; -using Content.Server.Mind; using Content.Server.Players; using Content.Shared.Administration; using Robust.Server.Player; @@ -10,8 +9,6 @@ namespace Content.Server.Objectives.Commands [AdminCommand(AdminFlags.Admin)] public sealed class RemoveObjectiveCommand : IConsoleCommand { - [Dependency] private readonly IEntityManager _entityManager = default!; - public string Command => "rmobjective"; public string Description => "Removes an objective from the player's mind."; public string Help => "rmobjective "; @@ -35,8 +32,7 @@ namespace Content.Server.Objectives.Commands if (int.TryParse(args[1], out var i)) { - var mindSystem = _entityManager.System(); - shell.WriteLine(mindSystem.TryRemoveObjective(mind, i) + shell.WriteLine(mind.TryRemoveObjective(i) ? "Objective successfully removed!" : "Objective removing failed. Maybe the index is out of bounds? Check lsobjectives!"); } diff --git a/Content.Server/Objectives/Conditions/DieCondition.cs b/Content.Server/Objectives/Conditions/DieCondition.cs index b6ec92804a..340b5ba60c 100644 --- a/Content.Server/Objectives/Conditions/DieCondition.cs +++ b/Content.Server/Objectives/Conditions/DieCondition.cs @@ -1,4 +1,3 @@ -using Content.Server.Mind; using Content.Server.Objectives.Interfaces; using JetBrains.Annotations; using Robust.Shared.Utility; @@ -22,15 +21,7 @@ namespace Content.Server.Objectives.Conditions public SpriteSpecifier Icon => new SpriteSpecifier.Rsi(new ResourcePath("Mobs/Ghosts/ghost_human.rsi"), "icon"); - public float Progress - { - get - { - var entityManager = IoCManager.Resolve(); - var mindSystem = entityManager.System(); - return _mind == null || mindSystem.IsCharacterDeadIc(_mind) ? 1f : 0f; - } - } + public float Progress => (_mind?.CharacterDeadIC ?? true) ? 1f : 0f; public float Difficulty => 0.5f; diff --git a/Content.Server/Objectives/Conditions/EscapeShuttleCondition.cs b/Content.Server/Objectives/Conditions/EscapeShuttleCondition.cs index 1a34cdd34d..ea86c2c7d6 100644 --- a/Content.Server/Objectives/Conditions/EscapeShuttleCondition.cs +++ b/Content.Server/Objectives/Conditions/EscapeShuttleCondition.cs @@ -1,4 +1,3 @@ -using Content.Server.Mind; using Content.Server.Objectives.Interfaces; using Content.Server.Station.Components; using Content.Shared.Cuffs.Components; @@ -47,14 +46,13 @@ namespace Content.Server.Objectives.Conditions { get { var entMan = IoCManager.Resolve(); - var mindSystem = entMan.System(); if (_mind?.OwnedEntity == null || !entMan.TryGetComponent(_mind.OwnedEntity, out var xform)) return 0f; var shuttleContainsAgent = false; - var agentIsAlive = !mindSystem.IsCharacterDeadIc(_mind); + var agentIsAlive = !_mind.CharacterDeadIC; var agentIsEscaping = true; if (entMan.TryGetComponent(_mind.OwnedEntity, out var cuffed) diff --git a/Content.Server/Objectives/Conditions/KillPersonCondition.cs b/Content.Server/Objectives/Conditions/KillPersonCondition.cs index 34b06cd094..2ae101f40f 100644 --- a/Content.Server/Objectives/Conditions/KillPersonCondition.cs +++ b/Content.Server/Objectives/Conditions/KillPersonCondition.cs @@ -1,4 +1,3 @@ -using Content.Server.Mind; using Content.Server.Objectives.Interfaces; using Content.Shared.Mobs.Systems; using Robust.Shared.Utility; @@ -33,15 +32,7 @@ namespace Content.Server.Objectives.Conditions public SpriteSpecifier Icon => new SpriteSpecifier.Rsi(new ResourcePath("Objects/Weapons/Guns/Pistols/viper.rsi"), "icon"); - public float Progress - { - get - { - var entityManager = IoCManager.Resolve(); - var mindSystem = entityManager.System(); - return Target == null || mindSystem.IsCharacterDeadIc(Target) ? 1f : 0f; - } - } + public float Progress => (Target?.CharacterDeadIC ?? true) ? 1f : 0f; public float Difficulty => 2f; diff --git a/Content.Server/Objectives/Conditions/KillRandomPersonCondition.cs b/Content.Server/Objectives/Conditions/KillRandomPersonCondition.cs index d84b75fff3..5cdef407dd 100644 --- a/Content.Server/Objectives/Conditions/KillRandomPersonCondition.cs +++ b/Content.Server/Objectives/Conditions/KillRandomPersonCondition.cs @@ -13,7 +13,7 @@ namespace Content.Server.Objectives.Conditions { public override IObjectiveCondition GetAssigned(Mind.Mind mind) { - var allHumans = EntityManager.EntityQuery(true).Where(mc => + var allHumans = EntityManager.EntityQuery(true).Where(mc => { var entity = mc.Mind?.OwnedEntity; diff --git a/Content.Server/Objectives/Conditions/RandomTraitorAliveCondition.cs b/Content.Server/Objectives/Conditions/RandomTraitorAliveCondition.cs index 87a43bfdee..8906a2b737 100644 --- a/Content.Server/Objectives/Conditions/RandomTraitorAliveCondition.cs +++ b/Content.Server/Objectives/Conditions/RandomTraitorAliveCondition.cs @@ -3,7 +3,6 @@ using Content.Server.Objectives.Interfaces; using Robust.Shared.Random; using Robust.Shared.Utility; using Content.Server.GameTicking.Rules; -using Content.Server.Mind; namespace Content.Server.Objectives.Conditions { @@ -42,15 +41,7 @@ namespace Content.Server.Objectives.Conditions public SpriteSpecifier Icon => new SpriteSpecifier.Rsi(new ResourcePath("Objects/Misc/bureaucracy.rsi"), "folder-white"); - public float Progress - { - get - { - var entityManager = IoCManager.Resolve(); - var mindSystem = entityManager.System(); - return _target == null || mindSystem.IsCharacterDeadIc(_target) ? 1f : 0f; - } - } + public float Progress => (!_target?.CharacterDeadIC ?? true) ? 1f : 0f; public float Difficulty => 1.75f; diff --git a/Content.Server/Objectives/Requirements/TraitorRequirement.cs b/Content.Server/Objectives/Requirements/TraitorRequirement.cs index ae08b77973..3f25ce593a 100644 --- a/Content.Server/Objectives/Requirements/TraitorRequirement.cs +++ b/Content.Server/Objectives/Requirements/TraitorRequirement.cs @@ -1,5 +1,4 @@ -using Content.Server.Mind; -using Content.Server.Objectives.Interfaces; +using Content.Server.Objectives.Interfaces; using Content.Server.Traitor; using JetBrains.Annotations; @@ -11,9 +10,7 @@ namespace Content.Server.Objectives.Requirements { public bool CanBeAssigned(Mind.Mind mind) { - var entityManager = IoCManager.Resolve(); - var mindSystem = entityManager.System(); - return mindSystem.HasRole(mind); + return mind.HasRole(); } } } diff --git a/Content.Server/PAI/PAISystem.cs b/Content.Server/PAI/PAISystem.cs index 9454377b16..2939ae58c0 100644 --- a/Content.Server/PAI/PAISystem.cs +++ b/Content.Server/PAI/PAISystem.cs @@ -33,7 +33,7 @@ namespace Content.Server.PAI { if (args.IsInDetailsRange) { - if (EntityManager.TryGetComponent(uid, out var mind) && mind.HasMind) + if (EntityManager.TryGetComponent(uid, out var mind) && mind.HasMind) { args.PushMarkup(Loc.GetString("pai-system-pai-installed")); } @@ -58,7 +58,7 @@ namespace Content.Server.PAI args.Handled = true; // Check for pAI activation - if (EntityManager.TryGetComponent(uid, out var mind) && mind.HasMind) + if (EntityManager.TryGetComponent(uid, out var mind) && mind.HasMind) { _popupSystem.PopupEntity(Loc.GetString("pai-system-pai-installed"), uid, args.User, PopupType.Large); return; @@ -136,7 +136,7 @@ namespace Content.Server.PAI if (!args.CanAccess || !args.CanInteract) return; - if (EntityManager.TryGetComponent(uid, out var mind) && mind.HasMind) + if (EntityManager.TryGetComponent(uid, out var mind) && mind.HasMind) { ActivationVerb verb = new(); verb.Text = Loc.GetString("pai-system-wipe-device-verb-text"); @@ -146,9 +146,9 @@ namespace Content.Server.PAI // Wiping device :( // The shutdown of the Mind should cause automatic reset of the pAI during OnMindRemoved // EDIT: But it doesn't!!!! Wtf? Do stuff manually - if (EntityManager.HasComponent(uid)) + if (EntityManager.HasComponent(uid)) { - EntityManager.RemoveComponent(uid); + EntityManager.RemoveComponent(uid); _popupSystem.PopupEntity(Loc.GetString("pai-system-wiped-device"), uid, args.User, PopupType.Large); PAITurningOff(uid); } diff --git a/Content.Server/PDA/PDASystem.cs b/Content.Server/PDA/PDASystem.cs index 4ca293b25a..fd8626cf74 100644 --- a/Content.Server/PDA/PDASystem.cs +++ b/Content.Server/PDA/PDASystem.cs @@ -4,7 +4,6 @@ using Content.Server.Instruments; using Content.Server.Light.Components; using Content.Server.Light.EntitySystems; using Content.Server.Light.Events; -using Content.Server.Mind; using Content.Server.PDA.Ringer; using Content.Server.Store.Components; using Content.Server.Store.Systems; @@ -28,7 +27,6 @@ namespace Content.Server.PDA [Dependency] private readonly StationSystem _stationSystem = default!; [Dependency] private readonly CartridgeLoaderSystem _cartridgeLoaderSystem = default!; [Dependency] private readonly StoreSystem _storeSystem = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; public override void Initialize() { @@ -126,10 +124,8 @@ namespace Content.Server.PDA if (session.AttachedEntity is not { Valid: true } user) continue; - if (storeComponent.AccountOwner == user - || (TryComp(session.AttachedEntity, out var mindComp) - && mindComp.Mind != null - && _mindSystem.HasRole(mindComp.Mind))) + if (storeComponent.AccountOwner == user || (TryComp(session.AttachedEntity, out var mindcomp) && mindcomp.Mind != null && + mindcomp.Mind.HasRole())) _cartridgeLoaderSystem?.UpdateUiState(pda.Owner, uplinkState, session); } } @@ -185,10 +181,9 @@ namespace Content.Server.PDA if (!TryComp(pda.Owner, out var storeComp)) return; - if (storeComp.AccountOwner != args.User - && !(TryComp(args.User, out var mindComp) - && mindComp.Mind != null - && _mindSystem.HasRole(mindComp.Mind))) return; + if (storeComp.AccountOwner != args.User && + !(TryComp(args.User, out var mindcomp) && mindcomp.Mind != null && mindcomp.Mind.HasRole())) + return; if (!_uiSystem.TryGetUi(pda.Owner, PDAUiKey.Key, out var ui)) return; diff --git a/Content.Server/ParticleAccelerator/Components/ParticleAcceleratorControlBoxComponent.cs b/Content.Server/ParticleAccelerator/Components/ParticleAcceleratorControlBoxComponent.cs index 58ea128a3c..435b285421 100644 --- a/Content.Server/ParticleAccelerator/Components/ParticleAcceleratorControlBoxComponent.cs +++ b/Content.Server/ParticleAccelerator/Components/ParticleAcceleratorControlBoxComponent.cs @@ -456,9 +456,9 @@ namespace Content.Server.ParticleAccelerator.Components } // Logging - _entMan.TryGetComponent(playerSession?.AttachedEntity, out MindContainerComponent? mindContainerComponent); - if(mindContainerComponent != null) - _adminLogger.Add(LogType.Action, LogImpact.Low, $"{_entMan.ToPrettyString(mindContainerComponent.Owner):player} has set {_entMan.ToPrettyString(Owner)} to on"); + _entMan.TryGetComponent(playerSession?.AttachedEntity, out MindComponent? mindComponent); + if(mindComponent != null) + _adminLogger.Add(LogType.Action, LogImpact.Low, $"{_entMan.ToPrettyString(mindComponent.Owner):player} has set {_entMan.ToPrettyString(Owner)} to on"); _isEnabled = true; UpdatePowerDraw(); @@ -480,9 +480,9 @@ namespace Content.Server.ParticleAccelerator.Components public void SwitchOff(IPlayerSession? playerSession = null, bool rescan = false) { // Logging - _entMan.TryGetComponent(playerSession?.AttachedEntity, out MindContainerComponent? mindContainerComponent); - if(mindContainerComponent != null) - _adminLogger.Add(LogType.Action, LogImpact.Low, $"{_entMan.ToPrettyString(mindContainerComponent.Owner):player} has set {_entMan.ToPrettyString(Owner)} to off{(rescan ? " via rescan" : "")}"); + _entMan.TryGetComponent(playerSession?.AttachedEntity, out MindComponent? mindComponent); + if(mindComponent != null) + _adminLogger.Add(LogType.Action, LogImpact.Low, $"{_entMan.ToPrettyString(mindComponent.Owner):player} has set {_entMan.ToPrettyString(Owner)} to off{(rescan ? " via rescan" : "")}"); _isEnabled = false; PowerOff(); @@ -535,7 +535,7 @@ namespace Content.Server.ParticleAccelerator.Components UpdatePartVisualStates(); // Logging - _entMan.TryGetComponent(playerSession?.AttachedEntity, out MindContainerComponent? mindContainerComponent); + _entMan.TryGetComponent(playerSession?.AttachedEntity, out MindComponent? mindComponent); LogImpact impact; switch (state) { @@ -552,8 +552,8 @@ namespace Content.Server.ParticleAccelerator.Components impact = LogImpact.Extreme; break; } - if(mindContainerComponent != null) - _adminLogger.Add(LogType.Action, impact, $"{_entMan.ToPrettyString(mindContainerComponent.Owner):player} has set the strength of {_entMan.ToPrettyString(Owner)} to {state}"); + if(mindComponent != null) + _adminLogger.Add(LogType.Action, impact, $"{_entMan.ToPrettyString(mindComponent.Owner):player} has set the strength of {_entMan.ToPrettyString(Owner)} to {state}"); if (_isEnabled) { diff --git a/Content.Server/Players/PlayerData.cs b/Content.Server/Players/PlayerData.cs index c8e368cfed..f811dfee76 100644 --- a/Content.Server/Players/PlayerData.cs +++ b/Content.Server/Players/PlayerData.cs @@ -1,4 +1,3 @@ -using Content.Server.Mind; using Robust.Server.Player; using Robust.Shared.Network; @@ -38,15 +37,9 @@ namespace Content.Server.Players public void WipeMind() { - var entityManager = IoCManager.Resolve(); - var mindSystem = entityManager.System(); - + Mind?.TransferTo(null); // This will ensure Mind == null - if (Mind == null) - return; - - mindSystem.TransferTo(Mind, null); - mindSystem.ChangeOwningPlayer(Mind, null); + Mind?.ChangeOwningPlayer(null); } /// diff --git a/Content.Server/Polymorph/Systems/PolymorphSystem.cs b/Content.Server/Polymorph/Systems/PolymorphSystem.cs index 24ffa658fa..c08a92be17 100644 --- a/Content.Server/Polymorph/Systems/PolymorphSystem.cs +++ b/Content.Server/Polymorph/Systems/PolymorphSystem.cs @@ -2,7 +2,6 @@ using Content.Server.Actions; using Content.Server.Buckle.Systems; using Content.Server.Humanoid; using Content.Server.Inventory; -using Content.Server.Mind; using Content.Server.Mind.Commands; using Content.Server.Mind.Components; using Content.Server.Polymorph.Components; @@ -41,7 +40,6 @@ namespace Content.Server.Polymorph.Systems [Dependency] private readonly SharedHandsSystem _hands = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly TransformSystem _transform = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; private readonly ISawmill _saw = default!; @@ -197,8 +195,8 @@ namespace Content.Server.Polymorph.Systems _humanoid.CloneAppearance(uid, child); } - if (_mindSystem.TryGetMind(uid, out var mind)) - _mindSystem.TransferTo(mind, child); + if (TryComp(uid, out var mind) && mind.Mind != null) + mind.Mind.TransferTo(child); //Ensures a map to banish the entity to EnsurePausesdMap(); @@ -274,8 +272,10 @@ namespace Content.Server.Polymorph.Systems } } - if (_mindSystem.TryGetMind(uid, out var mind)) - _mindSystem.TransferTo(mind, parent); + if (TryComp(uid, out var mind) && mind.Mind != null) + { + mind.Mind.TransferTo(parent); + } _popup.PopupEntity(Loc.GetString("polymorph-revert-popup-generic", ("parent", Identity.Entity(uid, EntityManager)), diff --git a/Content.Server/Revenant/EntitySystems/EssenceSystem.cs b/Content.Server/Revenant/EntitySystems/EssenceSystem.cs index 5f95da95e8..a466573344 100644 --- a/Content.Server/Revenant/EntitySystems/EssenceSystem.cs +++ b/Content.Server/Revenant/EntitySystems/EssenceSystem.cs @@ -67,7 +67,7 @@ public sealed class EssenceSystem : EntitySystem switch (mob.CurrentState) { case MobState.Alive: - if (TryComp(uid, out var mind) && mind.Mind != null) + if (TryComp(uid, out var mind) && mind.Mind != null) component.EssenceAmount = _random.NextFloat(75f, 100f); else component.EssenceAmount = _random.NextFloat(45f, 70f); diff --git a/Content.Server/Roles/AddRoleCommand.cs b/Content.Server/Roles/AddRoleCommand.cs index b172873fdf..2240d091da 100644 --- a/Content.Server/Roles/AddRoleCommand.cs +++ b/Content.Server/Roles/AddRoleCommand.cs @@ -6,15 +6,12 @@ using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Prototypes; using System.Linq; -using Content.Server.Mind; namespace Content.Server.Roles { [AdminCommand(AdminFlags.Admin)] public sealed class AddRoleCommand : IConsoleCommand { - [Dependency] private readonly EntityManager _entityManager = default!; - public string Command => "addrole"; public string Description => "Adds a role to a player's mind."; @@ -57,8 +54,7 @@ namespace Content.Server.Roles } var role = new Job(mind, jobPrototype); - var mindSystem = _entityManager.System(); - mindSystem.AddRole(mind, role); + mind.AddRole(role); } } } diff --git a/Content.Server/Roles/Job.cs b/Content.Server/Roles/Job.cs index c5c7403600..cd81dea484 100644 --- a/Content.Server/Roles/Job.cs +++ b/Content.Server/Roles/Job.cs @@ -2,7 +2,6 @@ using Content.Server.Chat.Managers; using Content.Server.Chat.Systems; using Content.Shared.Roles; using System.Globalization; -using Content.Server.Mind; namespace Content.Server.Roles { @@ -36,11 +35,8 @@ namespace Content.Server.Roles public override void Greet() { base.Greet(); - - var entityManager = IoCManager.Resolve(); - var mindSystem = entityManager.System(); - if (mindSystem.TryGetSession(Mind, out var session)) + if (Mind.TryGetSession(out var session)) { var chatMgr = IoCManager.Resolve(); chatMgr.DispatchServerMessage(session, Loc.GetString("job-greet-introduce-job-name", diff --git a/Content.Server/Roles/RemoveRoleCommand.cs b/Content.Server/Roles/RemoveRoleCommand.cs index 00b6492404..ae0a0f8f4a 100644 --- a/Content.Server/Roles/RemoveRoleCommand.cs +++ b/Content.Server/Roles/RemoveRoleCommand.cs @@ -1,5 +1,4 @@ using Content.Server.Administration; -using Content.Server.Mind; using Content.Server.Players; using Content.Shared.Administration; using Content.Shared.Roles; @@ -13,7 +12,6 @@ namespace Content.Server.Roles public sealed class RemoveRoleCommand : IConsoleCommand { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - [Dependency] private readonly IEntityManager _entityManager = default!; public string Command => "rmrole"; @@ -45,8 +43,7 @@ namespace Content.Server.Roles } var role = new Job(mind, _prototypeManager.Index(args[1])); - var mindSystem = _entityManager.System(); - mindSystem.RemoveRole(mind, role); + mind.RemoveRole(role); } } } diff --git a/Content.Server/Storage/EntitySystems/BluespaceLockerSystem.cs b/Content.Server/Storage/EntitySystems/BluespaceLockerSystem.cs index ca8c254f7d..8c2e06cf48 100644 --- a/Content.Server/Storage/EntitySystems/BluespaceLockerSystem.cs +++ b/Content.Server/Storage/EntitySystems/BluespaceLockerSystem.cs @@ -86,7 +86,7 @@ public sealed class BluespaceLockerSystem : EntitySystem if (component.BehaviorProperties.TransportEntities || component.BehaviorProperties.TransportSentient) foreach (var entity in target.Value.storageComponent.Contents.ContainedEntities.ToArray()) { - if (EntityManager.HasComponent(entity)) + if (EntityManager.HasComponent(entity)) { if (!component.BehaviorProperties.TransportSentient) continue; @@ -297,7 +297,7 @@ public sealed class BluespaceLockerSystem : EntitySystem if (component.BehaviorProperties.TransportEntities || component.BehaviorProperties.TransportSentient) foreach (var entity in entityStorageComponent.Contents.ContainedEntities.ToArray()) { - if (EntityManager.HasComponent(entity)) + if (EntityManager.HasComponent(entity)) { if (!component.BehaviorProperties.TransportSentient) continue; diff --git a/Content.Server/Store/Conditions/BuyerAntagCondition.cs b/Content.Server/Store/Conditions/BuyerAntagCondition.cs index 9e16cd1be7..d0f4292dbe 100644 --- a/Content.Server/Store/Conditions/BuyerAntagCondition.cs +++ b/Content.Server/Store/Conditions/BuyerAntagCondition.cs @@ -28,7 +28,7 @@ public sealed class BuyerAntagCondition : ListingCondition { var ent = args.EntityManager; - if (!ent.TryGetComponent(args.Buyer, out var mind) || mind.Mind == null) + if (!ent.TryGetComponent(args.Buyer, out var mind) || mind.Mind == null) return true; if (Blacklist != null) diff --git a/Content.Server/Store/Conditions/BuyerJobCondition.cs b/Content.Server/Store/Conditions/BuyerJobCondition.cs index b34b6a320b..d867a65d33 100644 --- a/Content.Server/Store/Conditions/BuyerJobCondition.cs +++ b/Content.Server/Store/Conditions/BuyerJobCondition.cs @@ -28,7 +28,7 @@ public sealed class BuyerJobCondition : ListingCondition { var ent = args.EntityManager; - if (!ent.TryGetComponent(args.Buyer, out var mind) || mind.Mind == null) + if (!ent.TryGetComponent(args.Buyer, out var mind) || mind.Mind == null) return true; //this is for things like surplus crate if (Blacklist != null) diff --git a/Content.Server/Suspicion/Roles/SuspicionInnocentRole.cs b/Content.Server/Suspicion/Roles/SuspicionInnocentRole.cs index 9703b11fbd..7c07cbd8df 100644 --- a/Content.Server/Suspicion/Roles/SuspicionInnocentRole.cs +++ b/Content.Server/Suspicion/Roles/SuspicionInnocentRole.cs @@ -1,5 +1,4 @@ using Content.Server.Chat.Managers; -using Content.Server.Mind; using Content.Shared.Roles; namespace Content.Server.Suspicion.Roles @@ -24,10 +23,8 @@ namespace Content.Server.Suspicion.Roles base.Greet(); var chat = IoCManager.Resolve(); - var entityManager = IoCManager.Resolve(); - var mindSystem = entityManager.System(); - if (mindSystem.TryGetSession(Mind, out var session)) + if (Mind.TryGetSession(out var session)) { chat.DispatchServerMessage(session, $"You're an {Name}!"); chat.DispatchServerMessage(session, $"Objective: {Objective}"); diff --git a/Content.Server/Suspicion/Roles/SuspicionTraitorRole.cs b/Content.Server/Suspicion/Roles/SuspicionTraitorRole.cs index 87d1fe3593..b42b22da42 100644 --- a/Content.Server/Suspicion/Roles/SuspicionTraitorRole.cs +++ b/Content.Server/Suspicion/Roles/SuspicionTraitorRole.cs @@ -1,6 +1,5 @@ using System.Linq; using Content.Server.Chat.Managers; -using Content.Server.Mind; using Content.Shared.Roles; namespace Content.Server.Suspicion.Roles @@ -22,10 +21,7 @@ namespace Content.Server.Suspicion.Roles public void GreetSuspicion(List traitors, IChatManager chatMgr) { - var entityManager = IoCManager.Resolve(); - var mindSystem = entityManager.System(); - - if (mindSystem.TryGetSession(Mind, out var session)) + if (Mind.TryGetSession(out var session)) { chatMgr.DispatchServerMessage(session, Loc.GetString("suspicion-role-greeting", ("roleName", Name))); chatMgr.DispatchServerMessage(session, Loc.GetString("suspicion-objective", ("objectiveText", Objective))); diff --git a/Content.Server/Suspicion/SuspicionRoleComponent.cs b/Content.Server/Suspicion/SuspicionRoleComponent.cs index f95919e3a8..59964254c8 100644 --- a/Content.Server/Suspicion/SuspicionRoleComponent.cs +++ b/Content.Server/Suspicion/SuspicionRoleComponent.cs @@ -67,13 +67,13 @@ namespace Content.Server.Suspicion public void SyncRoles() { - if (!_entMan.TryGetComponent(Owner, out MindContainerComponent? mind) || + if (!_entMan.TryGetComponent(Owner, out MindComponent? mind) || !mind.HasMind) { return; } - Role = mind.Mind.AllRoles.First(role => role is SuspicionRole); + Role = mind.Mind!.AllRoles.First(role => role is SuspicionRole); } public void AddAlly(SuspicionRoleComponent ally) diff --git a/Content.Server/Teleportation/PortalSystem.cs b/Content.Server/Teleportation/PortalSystem.cs index dabcefa9b9..1730a48ac0 100644 --- a/Content.Server/Teleportation/PortalSystem.cs +++ b/Content.Server/Teleportation/PortalSystem.cs @@ -14,7 +14,7 @@ public sealed class PortalSystem : SharedPortalSystem protected override void LogTeleport(EntityUid portal, EntityUid subject, EntityCoordinates source, EntityCoordinates target) { - if (HasComp(subject)) + if (HasComp(subject)) _adminLogger.Add(LogType.Teleport, LogImpact.Low, $"{ToPrettyString(subject):player} teleported via {ToPrettyString(portal)} from {source} to {target}"); } } diff --git a/Content.Server/Traitor/TraitorRole.cs b/Content.Server/Traitor/TraitorRole.cs index ca16f1a527..4e23122e7d 100644 --- a/Content.Server/Traitor/TraitorRole.cs +++ b/Content.Server/Traitor/TraitorRole.cs @@ -1,5 +1,4 @@ using Content.Server.Chat.Managers; -using Content.Server.Mind; using Content.Server.Roles; using Content.Shared.Roles; @@ -21,10 +20,7 @@ namespace Content.Server.Traitor public void GreetTraitor(string[] codewords) { - var entityManager = IoCManager.Resolve(); - var mindSystem = entityManager.System(); - - if (mindSystem.TryGetSession(Mind, out var session)) + if (Mind.TryGetSession(out var session)) { var chatMgr = IoCManager.Resolve(); chatMgr.DispatchServerMessage(session, Loc.GetString("traitor-role-greeting")); diff --git a/Content.Server/TraitorDeathMatch/TraitorDeathMatchRedemptionSystem.cs b/Content.Server/TraitorDeathMatch/TraitorDeathMatchRedemptionSystem.cs index ef81894bc2..9def8fc316 100644 --- a/Content.Server/TraitorDeathMatch/TraitorDeathMatchRedemptionSystem.cs +++ b/Content.Server/TraitorDeathMatch/TraitorDeathMatchRedemptionSystem.cs @@ -26,7 +26,7 @@ public sealed class TraitorDeathMatchRedemptionSystem : EntitySystem private void OnInteractUsing(EntityUid uid, TraitorDeathMatchRedemptionComponent component, InteractUsingEvent args) { - if (!EntityManager.TryGetComponent(args.User, out var userMindComponent)) + if (!EntityManager.TryGetComponent(args.User, out var userMindComponent)) { _popup.PopupEntity(Loc.GetString( "traitor-death-match-redemption-component-interact-using-main-message", diff --git a/Content.Server/Zombies/ZombifyOnDeathSystem.cs b/Content.Server/Zombies/ZombifyOnDeathSystem.cs index 572ab6f592..1994b98a7a 100644 --- a/Content.Server/Zombies/ZombifyOnDeathSystem.cs +++ b/Content.Server/Zombies/ZombifyOnDeathSystem.cs @@ -24,7 +24,6 @@ using Content.Shared.Popups; using Content.Server.Atmos.Miasma; using Content.Server.Humanoid; using Content.Server.IdentityManagement; -using Content.Server.Mind; using Content.Shared.Humanoid; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; @@ -55,7 +54,6 @@ namespace Content.Server.Zombies [Dependency] private readonly EmoteOnDamageSystem _emoteOnDamage = default!; [Dependency] private readonly IChatManager _chatMan = default!; [Dependency] private readonly IPrototypeManager _proto = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; public override void Initialize() { @@ -198,16 +196,16 @@ namespace Content.Server.Zombies _identity.QueueIdentityUpdate(target); //He's gotta have a mind - var mindComp = EnsureComp(target); - if (_mindSystem.TryGetMind(target, out var mind, mindComp) && _mindSystem.TryGetSession(mind, out var session)) + var mindcomp = EnsureComp(target); + if (mindcomp.Mind != null && mindcomp.Mind.TryGetSession(out var session)) { //Zombie role for player manifest - _mindSystem.AddRole(mind, new TraitorRole(mind, _proto.Index(zombiecomp.ZombieRoleId))); + mindcomp.Mind.AddRole(new TraitorRole(mindcomp.Mind, _proto.Index(zombiecomp.ZombieRoleId))); //Greeting message for new bebe zombers _chatMan.DispatchServerMessage(session, Loc.GetString("zombie-infection-greeting")); } - if (!HasComp(target) && !mindComp.HasMind) //this specific component gives build test trouble so pop off, ig + if (!HasComp(target) && !mindcomp.HasMind) //this specific component gives build test trouble so pop off, ig { //yet more hardcoding. Visit zombie.ftl for more information. EntityManager.EnsureComponent(target, out var ghostcomp); diff --git a/Resources/Locale/en-US/mind/components/mind-component.ftl b/Resources/Locale/en-US/mind/components/mind-component.ftl index 7374dcd163..0711958b70 100644 --- a/Resources/Locale/en-US/mind/components/mind-component.ftl +++ b/Resources/Locale/en-US/mind/components/mind-component.ftl @@ -1,10 +1,13 @@ -# MindContainerComponent localization +# MindComponent localization comp-mind-ghosting-prevented = You are not able to ghost right now. ## Messages displayed when a body is examined and in a certain state - comp-mind-examined-catatonic = { CAPITALIZE(SUBJECT($ent)) } { CONJUGATE-BE($ent) } totally catatonic. The stresses of life in deep-space must have been too much for { OBJECT($ent) }. Any recovery is unlikely. comp-mind-examined-dead = { CAPITALIZE(POSS-ADJ($ent)) } soul has departed. comp-mind-examined-ssd = { CAPITALIZE(SUBJECT($ent)) } { CONJUGATE-HAVE($ent) } a blank, absent-minded stare and appears completely unresponsive to anything. { CAPITALIZE(SUBJECT($ent)) } may snap out of it soon. -comp-mind-examined-dead-and-ssd = { CAPITALIZE(POSS-ADJ($ent)) } soul has departed and moved on. Any recovery is unlikely. + + +mind-component-no-mind-and-alive-text = { CAPITALIZE(POSS-ADJ($ent)) } is totally catatonic. The stresses of life in deep-space must have been too much for them. Any recovery is unlikely. +mind-component-no-mind-and-dead-text = { CAPITALIZE(POSS-ADJ($ent)) } soul has departed and moved on. Any recovery is unlikely. +mind-component-mind-and-no-session-text = { CAPITALIZE(POSS-ADJ($ent)) } { CONJUGATE-HAVE($ent) } a blank, absent-minded stare and appears completely unresponsive to anything. { CAPITALIZE(POSS-ADJ($ent)) } may snap out of it soon. diff --git a/Resources/Maps/barratry.yml b/Resources/Maps/barratry.yml index 14e1f4ac71..d1708d005d 100644 --- a/Resources/Maps/barratry.yml +++ b/Resources/Maps/barratry.yml @@ -56763,7 +56763,7 @@ entities: description: Alas poor Yorick... name: captain's skull type: GhostTakeoverAvailable - - type: MindContainer + - type: Mind - type: InputMover - type: MobMover - type: MovementAlwaysTouching diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml b/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml index ba22125b13..ace5fd81ec 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml @@ -3,7 +3,7 @@ name: revenant description: A spooky ghostie. components: - - type: MindContainer + - type: Mind - type: InputMover - type: MobMover - type: Input diff --git a/Resources/Prototypes/Entities/Mobs/Player/diona.yml b/Resources/Prototypes/Entities/Mobs/Player/diona.yml index 97c97d0214..79dfcdcf4b 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/diona.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/diona.yml @@ -11,7 +11,7 @@ interactSuccessString: hugging-success-generic interactSuccessSound: /Audio/Effects/thudswoosh.ogg messagePerceivedByOthers: hugging-success-generic-others - - type: MindContainer + - type: Mind showExamineInfo: true - type: Input context: "human" diff --git a/Resources/Prototypes/Entities/Mobs/Player/dwarf.yml b/Resources/Prototypes/Entities/Mobs/Player/dwarf.yml index a9dd505bb4..e0d1a3a246 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/dwarf.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/dwarf.yml @@ -12,7 +12,7 @@ interactSuccessString: hugging-success-generic interactSuccessSound: /Audio/Effects/thudswoosh.ogg messagePerceivedByOthers: hugging-success-generic-others - - type: MindContainer + - type: Mind showExamineInfo: true - type: Input context: "human" diff --git a/Resources/Prototypes/Entities/Mobs/Player/familiars.yml b/Resources/Prototypes/Entities/Mobs/Player/familiars.yml index 0e887fc40e..d8477281ed 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/familiars.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/familiars.yml @@ -21,7 +21,7 @@ - type: Access tags: - Chapel - - type: MindContainer + - type: Mind showExamineInfo: true - type: Alerts - type: Familiar @@ -72,7 +72,7 @@ - type: Access tags: - Chapel - - type: MindContainer + - type: Mind showExamineInfo: true - type: Familiar - type: Vocal diff --git a/Resources/Prototypes/Entities/Mobs/Player/human.yml b/Resources/Prototypes/Entities/Mobs/Player/human.yml index 19fe958bfe..60f86a10b8 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/human.yml @@ -11,7 +11,7 @@ interactSuccessString: hugging-success-generic interactSuccessSound: /Audio/Effects/thudswoosh.ogg messagePerceivedByOthers: hugging-success-generic-others - - type: MindContainer + - type: Mind showExamineInfo: true - type: Input context: "human" diff --git a/Resources/Prototypes/Entities/Mobs/Player/observer.yml b/Resources/Prototypes/Entities/Mobs/Player/observer.yml index 81fc4b3670..8ef363de41 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/observer.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/observer.yml @@ -5,7 +5,7 @@ save: false description: Boo! components: - - type: MindContainer + - type: Mind - type: Clickable - type: InteractionOutline - type: Physics diff --git a/Resources/Prototypes/Entities/Mobs/Player/reptilian.yml b/Resources/Prototypes/Entities/Mobs/Player/reptilian.yml index d05950dd18..4890c8b6a8 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/reptilian.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/reptilian.yml @@ -11,7 +11,7 @@ interactSuccessString: hugging-success-generic interactSuccessSound: /Audio/Effects/thudswoosh.ogg messagePerceivedByOthers: hugging-success-generic-others - - type: MindContainer + - type: Mind showExamineInfo: true - type: Input context: "human" diff --git a/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml b/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml index 3764e686e1..054e50b921 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml @@ -8,7 +8,7 @@ interactSuccessString: hugging-success-generic interactSuccessSound: /Audio/Effects/thudswoosh.ogg messagePerceivedByOthers: hugging-success-generic-others - - type: MindContainer + - type: Mind showExamineInfo: true - type: Input context: "human" diff --git a/Resources/Prototypes/Entities/Mobs/Player/slime.yml b/Resources/Prototypes/Entities/Mobs/Player/slime.yml index c56ae9a092..c379eeb95e 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/slime.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/slime.yml @@ -10,7 +10,7 @@ interactSuccessString: hugging-success-generic interactSuccessSound: /Audio/Effects/thudswoosh.ogg messagePerceivedByOthers: hugging-success-generic-others - - type: MindContainer + - type: Mind showExamineInfo: true - type: Input context: "human" diff --git a/Resources/Prototypes/Entities/Mobs/Player/vox.yml b/Resources/Prototypes/Entities/Mobs/Player/vox.yml index 870297ae80..a74e95680c 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/vox.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/vox.yml @@ -11,7 +11,7 @@ interactSuccessString: hugging-success-generic interactSuccessSound: /Audio/Effects/thudswoosh.ogg messagePerceivedByOthers: hugging-success-generic-others - - type: MindContainer + - type: Mind showExamineInfo: true - type: Input context: "human" @@ -32,3 +32,4 @@ damageRecovery: types: Asphyxiation: -1.0 + -- 2.51.2