]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Revert "Mind ecs" (#14881)
authorLeon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Sun, 26 Mar 2023 21:24:00 +0000 (10:24 +1300)
committerGitHub <noreply@github.com>
Sun, 26 Mar 2023 21:24:00 +0000 (08:24 +1100)
85 files changed:
Content.IntegrationTests/Tests/MindEntityDeletionTest.cs [moved from Content.IntegrationTests/Tests/Minds/MindEntityDeletionTest.cs with 88% similarity]
Content.IntegrationTests/Tests/Minds/MindTests.cs [deleted file]
Content.Server/AME/Components/AMEControllerComponent.cs
Content.Server/Administration/Commands/AGhost.cs
Content.Server/Administration/Commands/ControlMob.cs
Content.Server/Administration/Commands/SetMindCommand.cs
Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs
Content.Server/Administration/Systems/AdminVerbSystem.cs
Content.Server/Body/Systems/BodySystem.cs
Content.Server/Body/Systems/BrainSystem.cs
Content.Server/Bql/QuerySelectors.cs
Content.Server/CharacterInfo/CharacterInfoSystem.cs
Content.Server/Chat/Commands/SuicideCommand.cs
Content.Server/Chat/Managers/ChatManager.cs
Content.Server/Chat/Managers/IChatManager.cs
Content.Server/Chat/Systems/ChatSystem.cs
Content.Server/Chemistry/ReagentEffects/MakeSentient.cs
Content.Server/Cloning/CloningConsoleSystem.cs
Content.Server/Cloning/CloningSystem.cs
Content.Server/Drone/DroneSystem.cs
Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs
Content.Server/GameTicking/GameTicker.GamePreset.cs
Content.Server/GameTicking/GameTicker.Player.cs
Content.Server/GameTicking/GameTicker.RoundFlow.cs
Content.Server/GameTicking/GameTicker.Spawning.cs
Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs
Content.Server/GameTicking/Rules/PiratesRuleSystem.cs
Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs
Content.Server/GameTicking/Rules/TraitorDeathMatchRuleSystem.cs
Content.Server/GameTicking/Rules/TraitorRuleSystem.cs
Content.Server/GameTicking/Rules/ZombieRuleSystem.cs
Content.Server/Ghost/GhostSystem.cs
Content.Server/Ghost/Roles/Components/GhostRoleMobSpawnerComponent.cs
Content.Server/Ghost/Roles/Components/GhostTakeoverAvailableComponent.cs
Content.Server/Ghost/Roles/GhostRoleSystem.cs
Content.Server/Ghost/Roles/MakeGhostRoleCommand.cs
Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs
Content.Server/Mind/Commands/MakeSentientCommand.cs
Content.Server/Mind/Commands/MindInfoCommand.cs
Content.Server/Mind/Commands/RenameCommand.cs
Content.Server/Mind/Components/MindComponent.cs [moved from Content.Server/Mind/Components/MindContainerComponent.cs with 88% similarity]
Content.Server/Mind/Components/VisitingMindComponent.cs
Content.Server/Mind/Mind.cs
Content.Server/Mind/MindSystem.cs
Content.Server/Mind/MindTrackerSystem.cs
Content.Server/Mind/TransferMindOnGibSystem.cs
Content.Server/Objectives/Commands/AddObjectiveCommand.cs
Content.Server/Objectives/Commands/RemoveObjectiveCommand.cs
Content.Server/Objectives/Conditions/DieCondition.cs
Content.Server/Objectives/Conditions/EscapeShuttleCondition.cs
Content.Server/Objectives/Conditions/KillPersonCondition.cs
Content.Server/Objectives/Conditions/KillRandomPersonCondition.cs
Content.Server/Objectives/Conditions/RandomTraitorAliveCondition.cs
Content.Server/Objectives/Requirements/TraitorRequirement.cs
Content.Server/PAI/PAISystem.cs
Content.Server/PDA/PDASystem.cs
Content.Server/ParticleAccelerator/Components/ParticleAcceleratorControlBoxComponent.cs
Content.Server/Players/PlayerData.cs
Content.Server/Polymorph/Systems/PolymorphSystem.cs
Content.Server/Revenant/EntitySystems/EssenceSystem.cs
Content.Server/Roles/AddRoleCommand.cs
Content.Server/Roles/Job.cs
Content.Server/Roles/RemoveRoleCommand.cs
Content.Server/Storage/EntitySystems/BluespaceLockerSystem.cs
Content.Server/Store/Conditions/BuyerAntagCondition.cs
Content.Server/Store/Conditions/BuyerJobCondition.cs
Content.Server/Suspicion/Roles/SuspicionInnocentRole.cs
Content.Server/Suspicion/Roles/SuspicionTraitorRole.cs
Content.Server/Suspicion/SuspicionRoleComponent.cs
Content.Server/Teleportation/PortalSystem.cs
Content.Server/Traitor/TraitorRole.cs
Content.Server/TraitorDeathMatch/TraitorDeathMatchRedemptionSystem.cs
Content.Server/Zombies/ZombifyOnDeathSystem.cs
Resources/Locale/en-US/mind/components/mind-component.ftl
Resources/Maps/barratry.yml
Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml
Resources/Prototypes/Entities/Mobs/Player/diona.yml
Resources/Prototypes/Entities/Mobs/Player/dwarf.yml
Resources/Prototypes/Entities/Mobs/Player/familiars.yml
Resources/Prototypes/Entities/Mobs/Player/human.yml
Resources/Prototypes/Entities/Mobs/Player/observer.yml
Resources/Prototypes/Entities/Mobs/Player/reptilian.yml
Resources/Prototypes/Entities/Mobs/Player/skeleton.yml
Resources/Prototypes/Entities/Mobs/Player/slime.yml
Resources/Prototypes/Entities/Mobs/Player/vox.yml

similarity index 88%
rename from Content.IntegrationTests/Tests/Minds/MindEntityDeletionTest.cs
rename to Content.IntegrationTests/Tests/MindEntityDeletionTest.cs
index 3f50ffcb0d40e24ec3477d39237bf28e5238e17f..93c5fe41f101e37f84c1f196eac3a3286238e93d 100644 (file)
@@ -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<IPlayerManager>();
             var mapManager = server.ResolveDependency<IMapManager>();
 
-            var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
-
             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<IServerEntityManager>();
             var playerMan = server.ResolveDependency<IPlayerManager>();
             var mapManager = server.ResolveDependency<IMapManager>();
-
-            var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
-
             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<IServerEntityManager>();
+            var playerMan = server.ResolveDependency<IPlayerManager>();
             var mapManager = server.ResolveDependency<IMapManager>();
-
-            var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
-
             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 (file)
index 402ce95..0000000
+++ /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 { }
-";
-
-    /// <summary>
-    ///     Exception handling for PlayerData and NetUserId invalid due to testing.
-    ///     Can be removed when Players can be mocked.
-    /// </summary>
-    /// <param name="func"></param>
-    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<IServerEntityManager>();
-
-        await server.WaitAssertion(() =>
-        {
-            var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
-
-            var entity = entMan.SpawnEntity(null, new MapCoordinates());
-            var mindComp = entMan.EnsureComponent<MindContainerComponent>(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<IServerEntityManager>();
-
-        await server.WaitAssertion(() =>
-        {
-            var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
-
-            var entity = entMan.SpawnEntity(null, new MapCoordinates());
-            var mindComp = entMan.EnsureComponent<MindContainerComponent>(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<IServerEntityManager>();
-        var protoMan = server.ResolveDependency<IPrototypeManager>();
-
-        EntityUid entity = default!;
-        MindContainerComponent mindContainerComp = default!;
-        Mind mind = default!;
-        var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
-        var damageableSystem = entMan.EntitySysManager.GetEntitySystem<DamageableSystem>();
-
-        await server.WaitAssertion(() =>
-        {
-            entity = entMan.SpawnEntity("MindTestEntityDamageable", new MapCoordinates());
-            mindContainerComp = entMan.EnsureComponent<MindContainerComponent>(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<DamageableComponent>(entity);
-            if (!protoMan.TryIndex<DamageTypePrototype>("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<IServerEntityManager>();
-
-        await server.WaitAssertion(() =>
-        {
-            var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
-
-            var entity = entMan.SpawnEntity(null, new MapCoordinates());
-            var targetEntity = entMan.SpawnEntity(null, new MapCoordinates());
-            var mindComp = entMan.EnsureComponent<MindContainerComponent>(entity);
-            entMan.EnsureComponent<MindContainerComponent>(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<IServerEntityManager>();
-
-        await server.WaitAssertion(() =>
-        {
-            var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
-
-            var entity = entMan.SpawnEntity(null, new MapCoordinates());
-            var mindComp = entMan.EnsureComponent<MindContainerComponent>(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<IServerEntityManager>();
-
-        await server.WaitAssertion(() =>
-        {
-            var mindSystem = entMan.EntitySysManager.GetEntitySystem<MindSystem>();
-
-            var entity = entMan.SpawnEntity(null, new MapCoordinates());
-            var mindComp = entMan.EnsureComponent<MindContainerComponent>(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<TraitorRole>(mind));
-            Assert.That(!mindSystem.HasRole<Job>(mind));
-
-            var traitorRole = new TraitorRole(mind, new AntagPrototype());
-            
-            mindSystem.AddRole(mind, traitorRole);
-            
-            Assert.That(mindSystem.HasRole<TraitorRole>(mind));
-            Assert.That(!mindSystem.HasRole<Job>(mind));
-
-            var jobRole = new Job(mind, new JobPrototype());
-            
-            mindSystem.AddRole(mind, jobRole);
-            
-            Assert.That(mindSystem.HasRole<TraitorRole>(mind));
-            Assert.That(mindSystem.HasRole<Job>(mind));
-            
-            mindSystem.RemoveRole(mind, traitorRole);
-            
-            Assert.That(!mindSystem.HasRole<TraitorRole>(mind));
-            Assert.That(mindSystem.HasRole<Job>(mind));
-            
-            mindSystem.RemoveRole(mind, jobRole);
-            
-            Assert.That(!mindSystem.HasRole<TraitorRole>(mind));
-            Assert.That(!mindSystem.HasRole<Job>(mind));
-        });
-
-        await pairTracker.CleanReturnAsync();
-    }
-}
index 4285ff5fbd74a65860cff7863471fc4dd7e64d35..1a398a5eb5580803e5561f87f2677979880b019d 100644 (file)
@@ -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();
index 82c786af864d3e515f1b88afae4cf4fbef5061fc..037c289cbd4690672ee84cfc11cff7ce8abbe197 100644 (file)
@@ -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<MindSystem>();
 
             if (mind.VisitingEntity != default && _entities.HasComponent<GhostComponent>(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<MetaDataComponent>(ghost).EntityName = mind.Session.Name;
 
-                mindSystem.Visit(mind, ghost);
+                mind.Visit(ghost);
             }
             else
             {
                 _entities.GetComponent<MetaDataComponent>(ghost).EntityName = player.Name;
-                mindSystem.TransferTo(mind, ghost);
+                mind.TransferTo(ghost);
             }
 
             var comp = _entities.GetComponent<GhostComponent>(ghost);
index 18fb3bbb65a3af32e5add2a0510feaab00926716..4346ca7f170a4cc570d300c8e8734240c7f66acf 100644 (file)
@@ -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<MindContainerComponent>(target))
+            if (!_entities.HasComponent<MindComponent>(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>();
-            mindSystem.TransferTo(mind!, target);
+            mind!.TransferTo(target);
         }
     }
 }
index 6ef9c7eede946f07db98c35e24e0d47d9523cdd1..5c728f65991c332af7fe38e13bdadc66440e9f9c 100644 (file)
@@ -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<MindContainerComponent>(eUid))
+            if (!entityManager.HasComponent<MindComponent>(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<MindSystem>();
-            
             var mind = playerCData.Mind;
             if (mind == null)
             {
-                mind = mindSystem.CreateMind(session.UserId);
-                mind.CharacterName = entityManager.GetComponent<MetaDataComponent>(eUid).EntityName;
+                mind = new Mind.Mind(session.UserId)
+                {
+                    CharacterName = entityManager.GetComponent<MetaDataComponent>(eUid).EntityName
+                };
+                mind.ChangeOwningPlayer(session.UserId);
             }
-
-            mindSystem.TransferTo(mind, eUid);
+            mind.TransferTo(eUid);
         }
     }
 }
index d340c39c7adb29665c91ba47c404b6df1584ec32..b134d15fb3ee77d0ce7bd50e2ba1b3dfebb975be 100644 (file)
@@ -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;
 
index 3707014bda641578193bb622d7c488601a3348ee..7b1def620bbd173b8907bee06d80c2e9f4e15276 100644 (file)
@@ -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<IPlayerSession, EditSolutionsEui> _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<MindContainerComponent>(args.Target))
+                !EntityManager.HasComponent<MindComponent>(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<MindContainerComponent>(args.Target)?.HasMind ?? false))
+                !(EntityManager.GetComponentOrNull<MindComponent>(args.Target)?.HasMind ?? false))
             {
                 Verb verb = new();
                 verb.Text = Loc.GetString("make-ghost-role-verb-get-data-text");
index 3a70b51893c34538e3928102a23b8a103d151747..472b6b8acdea71c209dcc8f62c4bbeeeaab3be27 100644 (file)
@@ -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<MindComponent>(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);
         }
     }
 
index 209829387069b2dda4bb40ab577516fa954e06a9..52b743eebc2aa5451090a7fc7284cc70432abcb0 100644 (file)
@@ -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<MindContainerComponent>(newEntity);
-            var oldMind = EntityManager.EnsureComponent<MindContainerComponent>(oldEntity);
+            EntityManager.EnsureComponent<MindComponent>(newEntity);
+            var oldMind = EntityManager.EnsureComponent<MindComponent>(oldEntity);
 
             EnsureComp<GhostOnMoveComponent>(newEntity);
             if (HasComp<BodyComponent>(newEntity))
@@ -47,10 +44,7 @@ namespace Content.Server.Body.Systems
             // TODO: This is an awful solution.
             EnsureComp<InputMoverComponent>(newEntity);
 
-            if (!_mindSystem.TryGetMind(oldEntity, out var mind, oldMind))
-                return;
-            
-            _mindSystem.TransferTo(mind, newEntity);
+            oldMind.Mind?.TransferTo(newEntity);
         }
     }
 }
index 829dee7e38c116a8489f880ac5e7ec474b705869..a3b943bc9d6320415650b76bd5f6073d885cc78c 100644 (file)
@@ -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<MindContainerComponent>(e, out var mind))
+                    if (entityManager.TryGetComponent<MindComponent>(e, out var mind))
                         return (mind.Mind?.VisitingEntity == e) ^ isInverted;
 
                     return isInverted;
@@ -33,7 +32,7 @@ namespace Content.Server.Bql
             {
 
                 return DoSelection(
-                    entityManager.EntityQuery<MindContainerComponent>().Select(x => x.Owner),
+                    entityManager.EntityQuery<MindComponent>().Select(x => x.Owner),
                     arguments, isInverted, entityManager);
             }
         }
@@ -69,16 +68,14 @@ namespace Content.Server.Bql
 
             public override IEnumerable<EntityUid> DoSelection(IEnumerable<EntityUid> input, IReadOnlyList<object> arguments, bool isInverted, IEntityManager entityManager)
             {
-                var mindSystem = entityManager.System<MindSystem>();
                 return input.Where(e =>
-                    entityManager.TryGetComponent<MindContainerComponent>(e, out var mind)
-                    && mind.Mind != null
-                    && !mindSystem.IsCharacterDeadPhysically(mind.Mind));
+                    (entityManager.TryGetComponent<MindComponent>(e, out var mind) &&
+                    !(mind.Mind?.CharacterDeadPhysically ?? false)) ^ isInverted);
             }
 
             public override IEnumerable<EntityUid> DoInitialSelection(IReadOnlyList<object> arguments, bool isInverted, IEntityManager entityManager)
             {
-                return DoSelection(entityManager.EntityQuery<MindContainerComponent>().Select(x => x.Owner), arguments,
+                return DoSelection(entityManager.EntityQuery<MindComponent>().Select(x => x.Owner), arguments,
                     isInverted, entityManager);
             }
         }
index bd26a4836bb4e7e17ede61ede306fc84ed9e68dd..282722ceae36f7da5ce944424abe714af9b775b8 100644 (file)
@@ -26,9 +26,9 @@ public sealed class CharacterInfoSystem : EntitySystem
         var conditions = new Dictionary<string, List<ConditionInfo>>();
         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)
index 16c699b0a9c044610426dbe12524dd3ca6a37ac6..2f08881cb0f49d12c197b863833c89beef6863af 100644 (file)
@@ -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;
index b81c5f96b0d496533bdc1a2ade6dca4f5f53b6d6..90924188b265646233cb955a61aa9694a406d694 100644 (file)
@@ -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<AdminSystem>();
-            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)
index f3e0e8e2cf7463084b71b39c954fcace0de6f90f..6d74f76422b2b6948efb488c182f7223b0a9cf20 100644 (file)
@@ -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);
index a4e23558fb3d5ce76bd55316fd40c344e949472e..fd3182e65c4360025f3dbbcb2bf7a0e961fddcd4 100644 (file)
@@ -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;
index 81f92cb8da954f46e4776432dcdabe145c61d411..c762ba8a83c47bc0a3395464127f2a62f98ad731 100644 (file)
@@ -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<MindContainerComponent>(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<ReplacementAccentComponent>(uid);
 
@@ -26,7 +20,7 @@ public sealed class MakeSentient : ReagentEffect
         entityManager.RemoveComponent<MonkeyAccentComponent>(uid);
 
         // This makes it so it doesn't add a ghost role to things that are already sentient
-        if (entityManager.HasComponent<MindContainerComponent>(uid))
+        if (entityManager.HasComponent<MindComponent>(uid))
         {
             return;
         }
index 4da87a6339e449e39007ee99cd79e42cec3dcd9b..eb8e2b80cb76af92d314d800e2d9d88e7fc67457 100644 (file)
@@ -164,7 +164,7 @@ namespace Content.Server.Cloning
             if (body is null)
                 return;
 
-            if (!TryComp<MindContainerComponent>(body, out var mindComp))
+            if (!TryComp<MindComponent>(body, out var mindComp))
                 return;
 
             var mind = mindComp.Mind;
@@ -214,7 +214,7 @@ namespace Content.Server.Cloning
                 {
                     scanBodyInfo = MetaData(scanBody.Value).EntityName;
 
-                    TryComp<MindContainerComponent>(scanBody, out var mindComp);
+                    TryComp<MindComponent>(scanBody, out var mindComp);
 
                     if (!_mobStateSystem.IsDead(scanBody.Value))
                     {
index c17dff31ef7928af15e81200676e8f65742aa00a..45ffc4a967546104d219e698f82c0af39f887169 100644 (file)
@@ -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<Mind.Mind, EntityUid> 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<MindContainerComponent>(entity, out var mindComp) ||
+                !TryComp<MindComponent>(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<MindContainerComponent>(clone, out var cloneMindComp) &&
+                    TryComp<MindComponent>(clone, out var cloneMindComp) &&
                     (cloneMindComp.Mind == null || cloneMindComp.Mind == mind))
                     return false; // Mind already has clone
 
index 1cffb79ae7eaac9ec64de3eb9e2013dcaa5ec844..00bde35a5884e4cdbccbe82b31a21471e988e7bf 100644 (file)
@@ -72,7 +72,7 @@ namespace Content.Server.Drone
 
         private void OnExamined(EntityUid uid, DroneComponent component, ExaminedEvent args)
         {
-            if (TryComp<MindContainerComponent>(uid, out var mind) && mind.HasMind)
+            if (TryComp<MindComponent>(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<MindContainerComponent>(entity) && !HasComp<DroneComponent>(entity) && !HasComp<GhostComponent>(entity))
+                if (HasComp<MindComponent>(entity) && !HasComp<DroneComponent>(entity) && !HasComp<GhostComponent>(entity))
                 {
                     // Filter out dead ghost roles. Dead normal players are intended to block.
                     if ((TryComp<MobStateComponent>(entity, out var entityMobState) && HasComp<GhostTakeoverAvailableComponent>(entity) && _mobStateSystem.IsDead(entity, entityMobState)))
index 441696f0e2f32b9a3705982731bd603cad3f60d7..7f03e68aa4f9d9c5401312926924097a25fa26fa 100644 (file)
@@ -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<MindContainerComponent>(uid) || HasComp<ExplosiveComponent>(uid))
+                if (HasComp<MindComponent>(uid) || HasComp<ExplosiveComponent>(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<MindContainerComponent>(uid) || HasComp<ExplosiveComponent>(uid))
+                if (HasComp<MindComponent>(uid) || HasComp<ExplosiveComponent>(uid))
                 {
                     var damageStr = string.Join(", ", appliedDamage.DamageDict.Select(entry => $"{entry.Key}: {entry.Value}"));
                     _adminLogger.Add(LogType.Explosion, LogImpact.Medium,
index 46483eb0990c3e670e97a6d539817c25ff9620e8..eb44943e76f31bd1b976c5ecef1df97d37f7bb42 100644 (file)
@@ -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;
         }
 
index fd4a2e6a9ce0326c23b6aea42ee507e9b9625c96..10edb7d096826e9435d8e1543bb1801d329cec75 100644 (file)
@@ -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
 {
index 6ab473c6d2c59e81072955c4070d2bde6a249d81..e64837ca9fcecabd1abcaabb67369718372f041a 100644 (file)
@@ -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();
                 }
index 6a5373981cdc2ad35fce8df877a3f6c65857fd83..0826638a6fb18c04776e1fa053d12eb23e941d0f 100644 (file)
@@ -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<JobPrototype>(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<MetaDataComponent>(mob).EntityName = name;
             var ghost = EntityManager.GetComponent<GhostComponent>(mob);
             EntitySystem.Get<SharedGhostSystem>().SetCanReturnToBody(ghost, false);
-            _mindSystem.TransferTo(newMind, mob);
+            newMind.TransferTo(mob);
 
             _playerGameStatuses[player.UserId] = PlayerGameStatus.JoinedGame;
             RaiseNetworkEvent(GetStatusSingle(player, PlayerGameStatus.JoinedGame));
index 4e36b8d5f1bd6e486a5445cbe14f72cb4685dac2..bf2c7946db7d69a9b6e918c4afbb5388b9bb0eff 100644 (file)
@@ -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<MindContainerComponent>(uid, out var mindContainerComponent) || !RuleAdded)
+        if (!TryComp<MindComponent>(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<MindContainerComponent>(uid, out var mindContainerComponent) || mindContainerComponent.Mind == null)
+        if (!TryComp<MindComponent>(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<AntagPrototype>(role)));
+            mind.AddRole(new TraitorRole(mind, _prototypeManager.Index<AntagPrototype>(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<AntagPrototype>(_nukeopsRuleConfig.OperativeRoleProto)));
+        mind.AddRole(new TraitorRole(mind, _prototypeManager.Index<AntagPrototype>(_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<NukeOperativeComponent, MindContainerComponent>(true);
+        var query = EntityQuery<NukeOperativeComponent, MindComponent>(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);
index d917342e1bed676baa494e1420ba4d560f9e97b0..c5877ab513b1b72c0fb13345546637f37670dff3 100644 (file)
@@ -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<Mind.Mind> _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);
 
index d9e3abba08900b8805396fd79af39c2332f2b0fe..3c823671829a6278f65e2f642b5423e0c70eb9b3 100644 (file)
@@ -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<SuspicionTraitorRole>(mind);
-        });
+        var filter = Filter.Empty()
+            .AddWhere(session => ((IPlayerSession) session).ContentData()?.Mind?.HasRole<SuspicionTraitorRole>() ?? 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<SuspicionTraitorRole>(mind))
+            if (mind != null && mind.HasRole<SuspicionTraitorRole>())
                 traitorsAlive++;
             else
                 innocentsAlive++;
index 4c3f6214a47d497a344e96aac8145253fcaa05d8..f1bb0c1ee74dfbf0dcf7191cbb7fb920af8d4679 100644 (file)
@@ -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<AntagPrototype>(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.)
index 9fee214de48f1eb8790d811ff1dfc43c6ce2ea51..e005357f1f43093549b405cdcdf87288b18f8dee 100644 (file)
@@ -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<AntagPrototype>(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();
index 126032a7802c79ad39fb73fafa2f0cf83a1fd407..f51a22b42d2882e6116780f62547d7ee43bc5005 100644 (file)
@@ -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<string, string> _initialInfectedNames = new();
 
@@ -104,7 +102,7 @@ public sealed class ZombieRuleSystem : GameRuleSystem
             {
                 var meta = MetaData(survivor);
                 var username = string.Empty;
-                if (TryComp<MindContainerComponent>(survivor, out var mindcomp))
+                if (TryComp<MindComponent>(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<AntagPrototype>(PatientZeroPrototypeID)));
+            mind.AddRole(new TraitorRole(mind, _prototypeManager.Index<AntagPrototype>(PatientZeroPrototypeID)));
 
             var inCharacterName = string.Empty;
             if (mind.OwnedEntity != null)
index 2b6dd4f716fe4d82342d94effa62c0193e28f973..5213ec83c0fbc175544f8220be4562d39c83a892 100644 (file)
@@ -92,13 +92,13 @@ namespace Content.Server.Ghost
             if (EntityManager.HasComponent<VisitingMindComponent>(uid))
                 return;
 
-            if (!EntityManager.TryGetComponent<MindContainerComponent>(uid, out var mind) || !mind.HasMind || mind.Mind.IsVisitingEntity)
+            if (!EntityManager.TryGetComponent<MindComponent>(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<MindContainerComponent?>(uid, out var mind))
+            if (EntityManager.TryGetComponent<MindComponent?>(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<MindContainerComponent>(attached, out var mind);
+                    TryComp<MindComponent>(attached, out var mind);
 
                     string playerInfo = $"{EntityManager.GetComponent<MetaDataComponent>(attached).EntityName} ({mind?.Mind?.CurrentJob?.Name ?? "Unknown"})";
 
index 0833f738bc5d4358b4c56bb541366ed22d9a2fac..720bd5387e43b8241ed66c9678add0ccfe8a6d27 100644 (file)
@@ -48,7 +48,7 @@ namespace Content.Server.Ghost.Roles.Components
             if (MakeSentient)
                 MakeSentientCommand.MakeSentient(mob, _entMan, AllowMovement, AllowSpeech);
 
-            mob.EnsureComponent<MindContainerComponent>();
+            mob.EnsureComponent<MindComponent>();
 
             var ghostRoleSystem = EntitySystem.Get<GhostRoleSystem>();
             ghostRoleSystem.GhostRoleInternalCreateMindAndTransfer(session, Owner, mob, this);
index e6eec1d37b101b7a562e5852e4e3d5ba1656b64d..0a9a9435f957d2834dfc1966d05d17d004e54713 100644 (file)
@@ -17,7 +17,7 @@ namespace Content.Server.Ghost.Roles.Components
 
             Taken = true;
 
-            var mind = Owner.EnsureComponent<MindContainerComponent>();
+            var mind = Owner.EnsureComponent<MindComponent>();
 
             if (mind.HasMind)
                 return false;
index 4e17477b348f5f4a962fe7ab29068bd0e3f9c6c2..00f53c27fa0ca4b0c0b7e4938d4c2fb9c47e9f5a 100644 (file)
@@ -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<MetaDataComponent>(mob).EntityName);
-            _mindSystem.AddRole(newMind, new GhostRoleMarkerRole(newMind, role.RoleName));
+            var newMind = new Mind.Mind(player.UserId)
+            {
+                CharacterName = EntityManager.GetComponent<MetaDataComponent>(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()
index ceeeb52077c9613513e67bea1f5a0db10a3c7c7c..128afc20bcfb87beee58123c5c4d1fb6e1a91097 100644 (file)
@@ -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.");
index 295ceb05d1622764a360fc2efb234858f6c47fa6..b418e6a6e3337f6fd884d57d018d54dc0ffe8e1b 100644 (file)
@@ -246,7 +246,7 @@ namespace Content.Server.Medical.BiomassReclaimer
             // Reject souled bodies in easy mode.
             if (_configManager.GetCVar(CCVars.BiomassEasyMode) &&
                 HasComp<HumanoidAppearanceComponent>(dragged) &&
-                TryComp<MindContainerComponent>(dragged, out var mindComp))
+                TryComp<MindComponent>(dragged, out var mindComp))
             {
                 if (mindComp.Mind?.UserId != null && _playerManager.TryGetSessionById(mindComp.Mind.UserId.Value, out _))
                     return false;
index 22ca8ebde091408619daac1470d66ef994811ebf..d7f7f7087b78d8ee31d91f113d1366d0463313e0 100644 (file)
@@ -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<MindContainerComponent>(uid);
+            entityManager.EnsureComponent<MindComponent>(uid);
             if (allowMovement)
             {
                 entityManager.EnsureComponent<InputMoverComponent>(uid);
index 749135d2605c80777311e18025bc108d27df9110..fc2b0ff00108c4373061354f78efe1028518e02d 100644 (file)
@@ -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);
index 5fdb311f2ed2b0f584c0a5a7d7e9e5c3fa54437e..7b3cb92c1696cca74a16947bfc042889859907a1 100644 (file)
@@ -48,7 +48,7 @@ public sealed class RenameCommand : IConsoleCommand
 
         var entSysMan = IoCManager.Resolve<IEntitySystemManager>();
 
-        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;
similarity index 88%
rename from Content.Server/Mind/Components/MindContainerComponent.cs
rename to Content.Server/Mind/Components/MindComponent.cs
index 5dad7a46c516c767ebb369bbb43fff17910577cf..325e92123c3a9df06c05f3be168203b833552ca2 100644 (file)
@@ -1,13 +1,10 @@
-using System.Diagnostics.CodeAnalysis;
-using YamlDotNet.Core.Tokens;
-
 namespace Content.Server.Mind.Components
 {
     /// <summary>
     ///     Stores a <see cref="Server.Mind.Mind"/> on a mob.
     /// </summary>
     [RegisterComponent, Access(typeof(MindSystem))]
-    public sealed class MindContainerComponent : Component
+    public sealed class MindComponent : Component
     {
         /// <summary>
         ///     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.
         /// </summary>
         [ViewVariables]
-        [MemberNotNullWhen(true, nameof(Mind))]
         public bool HasMind => Mind != null;
 
         /// <summary>
index 38e3c18c21ea019c005533da5734eabfc2f8852d..e7b81c0cc78b2434b8912df71495c0ae90a4849f 100644 (file)
@@ -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
index 81f26d55a98b90a1ac1e0d24b46dcfe9b1b957c8..c022300b89123290bfcecc294eed49cf70921874 100644 (file)
@@ -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
     /// </remarks>
     public sealed class Mind
     {
-        internal readonly ISet<Role> Roles = new HashSet<Role>();
+        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<Objective> Objectives = new();
+        private readonly ISet<Role> _roles = new HashSet<Role>();
+
+        private readonly List<Objective> _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.
         /// </summary>
         /// <param name="userId">The session ID of the original owner (may get credited).</param>
-        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.
         /// <summary>
         ///     The session ID of the player owning this mind.
         /// </summary>
         [ViewVariables]
-        public NetUserId? UserId { get; internal set; }
+        public NetUserId? UserId { get; private set; }
 
         /// <summary>
         ///     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)
         /// </summary>
         [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".
         /// </summary>
         [ViewVariables]
-        public TimeSpan? TimeOfDeath { get; set; }
+        public TimeSpan? TimeOfDeath { get; set; } = null;
 
         /// <summary>
         ///     The component currently owned by this mind.
         ///     Can be null.
         /// </summary>
         [ViewVariables]
-        public MindContainerComponent? OwnedComponent { get; internal set; }
+        public MindComponent? OwnedComponent { get; private set; }
 
         /// <summary>
         ///     The entity currently owned by this mind.
         ///     Can be null.
         /// </summary>
         [ViewVariables]
-        public EntityUid? OwnedEntity { get; internal set; }
+        public EntityUid? OwnedEntity => OwnedComponent?.Owner;
 
         /// <summary>
         ///     An enumerable over all the roles this mind has.
         /// </summary>
         [ViewVariables]
-        public IEnumerable<Role> AllRoles => Roles;
+        public IEnumerable<Role> AllRoles => _roles;
 
         /// <summary>
         ///     An enumerable over all the objectives this mind has.
         /// </summary>
         [ViewVariables]
-        public IEnumerable<Objective> AllObjectives => Objectives;
+        public IEnumerable<Objective> AllObjectives => _objectives;
 
         /// <summary>
         ///     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.
         /// </summary>
         [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;
+            }
+        }
+
+        /// <summary>
+        ///     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?)
+        /// </summary>
+        [ViewVariables]
+        public bool CharacterDeadIC => CharacterDeadPhysically;
+
+        /// <summary>
+        ///     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.
+        /// </summary>
+        [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<MobStateComponent>(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);
+            }
+        }
+
+        /// <summary>
+        ///     A string to represent the mind for logging
+        /// </summary>
+        private string MindOwnerLoggingString
+        {
+            get
+            {
+                if (OwnedEntity != null)
+                    return _entityManager.ToPrettyString(OwnedEntity.Value);
+                if (UserId != null)
+                    return UserId.Value.ToString();
+                return "(originally " + OriginalOwnerUserId + ")";
+            }
+        }
+
+        /// <summary>
+        ///     Gives this mind a new role.
+        /// </summary>
+        /// <param name="role">The type of the role to give.</param>
+        /// <returns>The instance of the role.</returns>
+        /// <exception cref="ArgumentException">
+        ///     Thrown if we already have a role with this type.
+        /// </exception>
+        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;
+        }
+
+        /// <summary>
+        ///     Removes a role from this mind.
+        /// </summary>
+        /// <param name="role">The type of the role to remove.</param>
+        /// <exception cref="ArgumentException">
+        ///     Thrown if we do not have this role.
+        /// </exception>
+        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<T>() where T : Role
+        {
+            var t = typeof(T);
+
+            return _roles.Any(role => role.GetType() == t);
+        }
 
         /// <summary>
         ///     Gets the current job
         /// </summary>
-        public Job? CurrentJob => Roles.OfType<Job>().SingleOrDefault();
+        public Job? CurrentJob => _roles.OfType<Job>().SingleOrDefault();
+
+        /// <summary>
+        /// Adds an objective to this mind.
+        /// </summary>
+        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;
+        }
+
+        /// <summary>
+        /// Removes an objective to this mind.
+        /// </summary>
+        /// <returns>Returns true if the removal succeeded.</returns>
+        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;
+        }
+
+        /// <summary>
+        ///     Transfer this mind's control over to a new entity.
+        /// </summary>
+        /// <param name="entity">
+        ///     The entity to control.
+        ///     Can be null, in which case it will simply detach the mind from any entity.
+        /// </param>
+        /// <param name="ghostCheckOverride">
+        ///     If true, skips ghost check for Visiting Entity
+        /// </param>
+        /// <exception cref="ArgumentException">
+        ///     Thrown if <paramref name="entity"/> is already owned by another mind.
+        /// </exception>
+        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<MindComponent>(entity.Value);
+                }
+                else if (component.HasMind)
+                {
+                    _gameTickerSystem.OnGhostAttempt(component.Mind!, false);
+                }
+
+                if (_entityManager.TryGetComponent<ActorComponent>(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<VisitingMindComponent>(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<IPlayerManager>();
+            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<VisitingMindComponent>(entity);
+            comp.Mind = this;
+
+            Logger.Info($"Session {Session?.Name} visiting entity {entity}.");
+        }
+
+        /// <summary>
+        /// Returns the mind to its original entity.
+        /// </summary>
+        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)}");
+        }
+
+        /// <summary>
+        /// Cleans up the VisitingEntity.
+        /// </summary>
+        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<VisitingMindComponent>(oldVisitingEnt);
+            _entityManager.EventBus.RaiseLocalEvent(oldVisitingEnt, new MindUnvisitedMessage(), true);
+        }
+
+        public bool TryGetSession([NotNullWhen(true)] out IPlayerSession? session)
+        {
+            return (session = Session) != null;
+        }
     }
 }
index 1bc99ab78e9752d38be0c7ccbc1d2ad270a12b5d..f9101234ced325eb16cdfcb8e406504328df8cb4 100644 (file)
@@ -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<MindContainerComponent, ComponentShutdown>(OnShutdown);
-        SubscribeLocalEvent<MindContainerComponent, ExaminedEvent>(OnExamined);
-        SubscribeLocalEvent<MindContainerComponent, SuicideEvent>(OnSuicide);
-        SubscribeLocalEvent<VisitingMindComponent, ComponentRemove>(OnVisitingMindRemoved);
-    }
-
-    private void OnVisitingMindRemoved(EntityUid uid, VisitingMindComponent component, ComponentRemove args)
-    {
-        UnVisit(component.Mind);
+        SubscribeLocalEvent<MindComponent, ComponentShutdown>(OnShutdown);
+        SubscribeLocalEvent<MindComponent, ExaminedEvent>(OnExamined);
+        SubscribeLocalEvent<MindComponent, SuicideEvent>(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
 
     /// <summary>
     ///     Don't call this unless you know what the hell you're doing.
-    ///     Use <see cref="MindSystem.TransferTo(Mind,System.Nullable{Robust.Shared.GameObjects.EntityUid},bool)"/> instead.
+    ///     Use <see cref="Mind.TransferTo(System.Nullable{Robust.Shared.GameObjects.EntityUid},bool)"/> instead.
     ///     If that doesn't cover it, make something to cover it.
     /// </summary>
-    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
 
     /// <summary>
     ///     Don't call this unless you know what the hell you're doing.
-    ///     Use <see cref="MindSystem.TransferTo(Mind,System.Nullable{Robust.Shared.GameObjects.EntityUid},bool)"/> instead.
+    ///     Use <see cref="Mind.TransferTo(System.Nullable{Robust.Shared.GameObjects.EntityUid},bool)"/> instead.
     ///     If that doesn't cover it, make something to cover it.
     /// </summary>
-    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<GhostComponent>(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;
-    }
-
-    /// <summary>
-    ///     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.
-    /// </summary>
-    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<MobStateComponent>(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<VisitingMindComponent>(entity);
-        comp.Mind = mind;
-
-        Logger.Info($"Session {mind.Session?.Name} visiting entity {entity}.");
-    }
-
-    /// <summary>
-    /// Returns the mind to its original entity.
-    /// </summary>
-    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)}");
-        }
-    }
-
-    /// <summary>
-    /// Cleans up the VisitingEntity.
-    /// </summary>
-    /// <param name="mind"></param>
-    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<VisitingMindComponent>(oldVisitingEnt);
-        RaiseLocalEvent(oldVisitingEnt, new MindUnvisitedMessage(), true);
-    }
-
-    /// <summary>
-    ///     Transfer this mind's control over to a new entity.
-    /// </summary>
-    /// <param name="mind">The mind to transfer</param>
-    /// <param name="entity">
-    ///     The entity to control.
-    ///     Can be null, in which case it will simply detach the mind from any entity.
-    /// </param>
-    /// <param name="ghostCheckOverride">
-    ///     If true, skips ghost check for Visiting Entity
-    /// </param>
-    /// <exception cref="ArgumentException">
-    ///     Thrown if <paramref name="entity"/> is already owned by another mind.
-    /// </exception>
-    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<MindContainerComponent>(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<ActorComponent>(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<GhostComponent>(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<VisitingMindComponent>(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);
-    }
-    
-    /// <summary>
-    /// Adds an objective to this mind.
-    /// </summary>
-    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;
-    }
-
-    /// <summary>
-    /// Removes an objective to this mind.
-    /// </summary>
-    /// <returns>Returns true if the removal succeeded.</returns>
-    public bool TryRemoveObjective(Mind mind, int index)
-    {
-        if (mind.Objectives.Count >= index) return false;
 
-        var objective = mind.Objectives[index];
+        var dead = TryComp<MobStateComponent?>(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;
-    }
-
-    /// <summary>
-    ///     Gives this mind a new role.
-    /// </summary>
-    /// <param name="mind">The mind to add the role to.</param>
-    /// <param name="role">The type of the role to give.</param>
-    /// <returns>The instance of the role.</returns>
-    /// <exception cref="ArgumentException">
-    ///     Thrown if we already have a role with this type.
-    /// </exception>
-    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)}");
     }
 
-    /// <summary>
-    ///     Removes a role from this mind.
-    /// </summary>
-    /// <param name="mind">The mind to remove the role from.</param>
-    /// <param name="role">The type of the role to remove.</param>
-    /// <exception cref="ArgumentException">
-    ///     Thrown if we do not have this role.
-    /// </exception>
-    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<T>(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;
-    }
-
-    /// <summary>
-    /// Gets a mind from uid and/or MindContainerComponent. Used for null checks.
-    /// </summary>
-    /// <param name="uid">Entity UID that owns the mind.</param>
-    /// <param name="mind">The returned mind.</param>
-    /// <param name="mindContainerComponent">Mind component on <paramref name="uid"/> to get the mind from.</param>
-    /// <returns>True if mind found. False if not.</returns>
-    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;
-    }
-
-    /// <summary>
-    /// Sets the Mind's OwnedComponent and OwnedEntity
-    /// </summary>
-    /// <param name="mind">Mind to set OwnedComponent and OwnedEntity on</param>
-    /// <param name="uid">Entity owned by <paramref name="mind"/></param>
-    /// <param name="mindContainerComponent">MindContainerComponent owned by <paramref name="mind"/></param>
-    private void SetOwnedEntity(Mind mind, EntityUid? uid, MindContainerComponent? mindContainerComponent)
-    {
-        if (uid != null)
-            Resolve(uid.Value, ref mindContainerComponent);
-
-        mind.OwnedEntity = uid;
-        mind.OwnedComponent = mindContainerComponent;
-    }
-
-    /// <summary>
-    /// Sets the Mind's UserId and Session
-    /// </summary>
-    /// <param name="mind"></param>
-    /// <param name="userId"></param>
-    private void SetUserId(Mind mind, NetUserId? userId)
-    {
-        mind.UserId = userId;
-        
-        if (!userId.HasValue)
-            return;
-        
-        _playerManager.TryGetSessionById(userId.Value, out var ret);
-        mind.Session = ret;
-    }
-    
-    /// <summary>
-    ///     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?)
-    /// </summary>
-    public bool IsCharacterDeadIc(Mind mind)
-    {
-        return IsCharacterDeadPhysically(mind);
-    }
-
-    /// <summary>
-    ///     A string to represent the mind for logging
-    /// </summary>
-    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 + ")";
     }
 }
index 2ab76ce9af9efabdbf524dd96b3c8b8fa6738025..49f2400b0806a70198c04ba33bfd600dde883cd2 100644 (file)
@@ -20,7 +20,7 @@ namespace Content.Server.Mind
             base.Initialize();
 
             SubscribeLocalEvent<RoundRestartCleanupEvent>(Reset);
-            SubscribeLocalEvent<MindContainerComponent, MindAddedMessage>(OnMindAdded);
+            SubscribeLocalEvent<MindComponent, MindAddedMessage>(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)
index d499d6a4dd1beba1be4cdc3ad25d74ae87d1c8e9..1aed10c324bd4f75d62c1c8891d436ef65086272 100644 (file)
@@ -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!;
 
     /// <inheritdoc/>
     public override void Initialize()
@@ -25,7 +24,7 @@ public sealed class TransferMindOnGibSystem : EntitySystem
 
     private void OnGib(EntityUid uid, TransferMindOnGibComponent component, BeingGibbedEvent args)
     {
-        if (!TryComp<MindContainerComponent>(uid, out var mindcomp) || mindcomp.Mind == null)
+        if (!TryComp<MindComponent>(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);
     }
 }
index 7353763b63e7cbf02d91f54105ca90cc2dbc0909..ea4372b1aac82c7d20da2f84ad7cd58bb1332161 100644 (file)
@@ -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 <username> <objectiveID>";
@@ -45,10 +42,8 @@ namespace Content.Server.Objectives.Commands
                 shell.WriteLine($"Can't find matching ObjectivePrototype {objectivePrototype}");
                 return;
             }
-            
-            var mindSystem = _entityManager.System<MindSystem>();
 
-            if (!mindSystem.TryAddObjective(mind, objectivePrototype))
+            if (!mind.TryAddObjective(objectivePrototype))
             {
                 shell.WriteLine("Objective requirements dont allow that objective to be added.");
             }
index c0846a1e434c2b05fefa7d3a7f9818bd5f97ecdd..96979ab6fa92a47074e746d57bd9d34a78228fcc 100644 (file)
@@ -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 <username> <index>";
@@ -35,8 +32,7 @@ namespace Content.Server.Objectives.Commands
 
                 if (int.TryParse(args[1], out var i))
                 {
-                    var mindSystem = _entityManager.System<MindSystem>();
-                    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!");
                 }
index b6ec92804a29396626442e86702abc531d1b08da..340b5ba60cec348ce92082d69b82f0cd838680f2 100644 (file)
@@ -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<EntityManager>();
-                var mindSystem = entityManager.System<MindSystem>();
-                return _mind == null || mindSystem.IsCharacterDeadIc(_mind) ? 1f : 0f;
-            }
-        }
+        public float Progress => (_mind?.CharacterDeadIC ?? true) ? 1f : 0f;
 
         public float Difficulty => 0.5f;
 
index 1a34cdd34d738abcaf2df99dbb7fdd3af9bc327c..ea86c2c7d64d9a5c852ca5093016a5318d2e9f00 100644 (file)
@@ -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<IEntityManager>();
-                var mindSystem = entMan.System<MindSystem>();
 
                 if (_mind?.OwnedEntity == null
                     || !entMan.TryGetComponent<TransformComponent>(_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<CuffableComponent>(_mind.OwnedEntity, out var cuffed)
index 34b06cd094df5d161635a07f0735624336bd0ecd..2ae101f40f98b9e2eb053f3674dba73512dea220 100644 (file)
@@ -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<EntityManager>();
-                var mindSystem = entityManager.System<MindSystem>();
-                return Target == null || mindSystem.IsCharacterDeadIc(Target) ? 1f : 0f;
-            }
-        }
+        public float Progress => (Target?.CharacterDeadIC ?? true) ? 1f : 0f;
 
         public float Difficulty => 2f;
 
index d84b75fff3624e69b87e6a38902388222570cc34..5cdef407ddc03d7564a918161de655bea1546c84 100644 (file)
@@ -13,7 +13,7 @@ namespace Content.Server.Objectives.Conditions
     {
         public override IObjectiveCondition GetAssigned(Mind.Mind mind)
         {
-            var allHumans = EntityManager.EntityQuery<MindContainerComponent>(true).Where(mc =>
+            var allHumans = EntityManager.EntityQuery<MindComponent>(true).Where(mc =>
             {
                 var entity = mc.Mind?.OwnedEntity;
 
index 87a43bfdeec0a981f0b9332ba80336e3a3b670aa..8906a2b7377a522d2ef96c63664187e6042e2413 100644 (file)
@@ -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<EntityManager>();
-                var mindSystem = entityManager.System<MindSystem>();
-                return _target == null || mindSystem.IsCharacterDeadIc(_target) ? 1f : 0f;
-            }
-        }
+        public float Progress => (!_target?.CharacterDeadIC ?? true) ? 1f : 0f;
 
         public float Difficulty => 1.75f;
 
index ae08b779731484a05bf9fd441af7dc5da312d6dd..3f25ce593a746bddf9599a10fa368f08dd594c4b 100644 (file)
@@ -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<IEntityManager>();
-            var mindSystem = entityManager.System<MindSystem>();
-            return mindSystem.HasRole<TraitorRole>(mind);
+            return mind.HasRole<TraitorRole>();
         }
     }
 }
index 9454377b162a2623c0271d401704563d689eed84..2939ae58c0a0abef435ac2a2cc672e1d621370c0 100644 (file)
@@ -33,7 +33,7 @@ namespace Content.Server.PAI
         {
             if (args.IsInDetailsRange)
             {
-                if (EntityManager.TryGetComponent<MindContainerComponent>(uid, out var mind) && mind.HasMind)
+                if (EntityManager.TryGetComponent<MindComponent>(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<MindContainerComponent>(uid, out var mind) && mind.HasMind)
+            if (EntityManager.TryGetComponent<MindComponent>(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<MindContainerComponent>(uid, out var mind) && mind.HasMind)
+            if (EntityManager.TryGetComponent<MindComponent>(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<MindContainerComponent>(uid))
+                    if (EntityManager.HasComponent<MindComponent>(uid))
                     {
-                        EntityManager.RemoveComponent<MindContainerComponent>(uid);
+                        EntityManager.RemoveComponent<MindComponent>(uid);
                         _popupSystem.PopupEntity(Loc.GetString("pai-system-wiped-device"), uid, args.User, PopupType.Large);
                         PAITurningOff(uid);
                     }
index 4ca293b25ad7579cd1d44384bab7d34a7c59ada4..fd8626cf74374e90cc7848b664e05771fe3d5bbd 100644 (file)
@@ -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<MindContainerComponent>(session.AttachedEntity, out var mindComp)
-                        && mindComp.Mind != null
-                        && _mindSystem.HasRole<TraitorRole>(mindComp.Mind)))
+                if (storeComponent.AccountOwner == user || (TryComp<MindComponent>(session.AttachedEntity, out var mindcomp) && mindcomp.Mind != null &&
+                    mindcomp.Mind.HasRole<TraitorRole>()))
                     _cartridgeLoaderSystem?.UpdateUiState(pda.Owner, uplinkState, session);
             }
         }
@@ -185,10 +181,9 @@ namespace Content.Server.PDA
             if (!TryComp<StoreComponent>(pda.Owner, out var storeComp))
                 return;
 
-            if (storeComp.AccountOwner != args.User
-                && !(TryComp<MindContainerComponent>(args.User, out var mindComp)
-                     && mindComp.Mind != null
-                     && _mindSystem.HasRole<TraitorRole>(mindComp.Mind))) return;
+            if (storeComp.AccountOwner != args.User &&
+                !(TryComp<MindComponent>(args.User, out var mindcomp) && mindcomp.Mind != null && mindcomp.Mind.HasRole<TraitorRole>()))
+                return;
 
             if (!_uiSystem.TryGetUi(pda.Owner, PDAUiKey.Key, out var ui))
                 return;
index 58ea128a3c5ca1a402e7e89cdb380905d50a296d..435b285421b95ddcf4f110eb467751c9d201615b 100644 (file)
@@ -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)
             {
index c8e368cfedd87f630725ebc32d05165b670f6b60..f811dfee767dc551dc357cb65900adfe8f34e648 100644 (file)
@@ -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<IEntityManager>();
-            var mindSystem = entityManager.System<MindSystem>();
-            
+            Mind?.TransferTo(null);
             // This will ensure Mind == null
-            if (Mind == null)
-                return;
-
-            mindSystem.TransferTo(Mind, null);
-            mindSystem.ChangeOwningPlayer(Mind, null);
+            Mind?.ChangeOwningPlayer(null);
         }
 
         /// <summary>
index 24ffa658fa0dfd43c1072c665f876904f8cd776c..c08a92be1739d2c2248e8cafbf3386ab1a4704fe 100644 (file)
@@ -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<MindComponent>(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<MindComponent>(uid, out var mind) && mind.Mind != null)
+            {
+                mind.Mind.TransferTo(parent);
+            }
 
             _popup.PopupEntity(Loc.GetString("polymorph-revert-popup-generic",
                 ("parent", Identity.Entity(uid, EntityManager)),
index 5f95da95e871baeaa8d8d5da211aac9100f2e410..a4665733442c5af55f9d36413b3ea76a17e4fa7a 100644 (file)
@@ -67,7 +67,7 @@ public sealed class EssenceSystem : EntitySystem
         switch (mob.CurrentState)
         {
             case MobState.Alive:
-                if (TryComp<MindContainerComponent>(uid, out var mind) && mind.Mind != null)
+                if (TryComp<MindComponent>(uid, out var mind) && mind.Mind != null)
                     component.EssenceAmount = _random.NextFloat(75f, 100f);
                 else
                     component.EssenceAmount = _random.NextFloat(45f, 70f);
index b172873fdf8a503c9ec732f1439a2ba5a03784a2..2240d091dab78b4ab61a49e33beb2149aa6bd9f8 100644 (file)
@@ -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>();
-            mindSystem.AddRole(mind, role);
+            mind.AddRole(role);
         }
     }
 }
index c5c740360029c5e0e4d44ca4714dae25ab3c6a25..cd81dea484c44d99ba1412da45fda61fad9e93fb 100644 (file)
@@ -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<EntityManager>();
-            var mindSystem = entityManager.System<MindSystem>();
 
-            if (mindSystem.TryGetSession(Mind, out var session))
+            if (Mind.TryGetSession(out var session))
             {
                 var chatMgr = IoCManager.Resolve<IChatManager>();
                 chatMgr.DispatchServerMessage(session, Loc.GetString("job-greet-introduce-job-name",
index 00b649240450f7bd16d9d5813919cbb7fb68f357..ae0a0f8f4ae9d589b7c281f0196b1b3c1c0fbbbf 100644 (file)
@@ -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<JobPrototype>(args[1]));
-            var mindSystem = _entityManager.System<MindSystem>();
-            mindSystem.RemoveRole(mind, role);
+            mind.RemoveRole(role);
         }
     }
 }
index ca8c254f7d91672d063d54a99044cef262b4dd4b..8c2e06cf48a9709d79e288dcec0eb36da95b7cdf 100644 (file)
@@ -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<MindContainerComponent>(entity))
+                    if (EntityManager.HasComponent<MindComponent>(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<MindContainerComponent>(entity))
+                if (EntityManager.HasComponent<MindComponent>(entity))
                 {
                     if (!component.BehaviorProperties.TransportSentient)
                         continue;
index 9e16cd1be7cf858dbcce1cef1d58f093ce5e2ccf..d0f4292dbeb4ec903027707b5b641cdd0bff248c 100644 (file)
@@ -28,7 +28,7 @@ public sealed class BuyerAntagCondition : ListingCondition
     {
         var ent = args.EntityManager;
 
-        if (!ent.TryGetComponent<MindContainerComponent>(args.Buyer, out var mind) || mind.Mind == null)
+        if (!ent.TryGetComponent<MindComponent>(args.Buyer, out var mind) || mind.Mind == null)
             return true;
 
         if (Blacklist != null)
index b34b6a320bad6e538f224af576be0d6a50603030..d867a65d33c6c3db36a30f39e37ae4fddee00240 100644 (file)
@@ -28,7 +28,7 @@ public sealed class BuyerJobCondition : ListingCondition
     {
         var ent = args.EntityManager;
 
-        if (!ent.TryGetComponent<MindContainerComponent>(args.Buyer, out var mind) || mind.Mind == null)
+        if (!ent.TryGetComponent<MindComponent>(args.Buyer, out var mind) || mind.Mind == null)
             return true; //this is for things like surplus crate
 
         if (Blacklist != null)
index 9703b11fbda5eb15bcffb6f562e03efcbb32bf3f..7c07cbd8dfaf034db0524a145f7395c0f0451287 100644 (file)
@@ -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<IChatManager>();
-            var entityManager = IoCManager.Resolve<IEntityManager>();
-            var mindSystem = entityManager.System<MindSystem>();
 
-            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}");
index 87d1fe3593e44dd0c26a3f1be86441c3681bbba5..b42b22da42b6e21fd70290bd58780e9d6c2446cd 100644 (file)
@@ -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<SuspicionTraitorRole> traitors, IChatManager chatMgr)
         {
-            var entityManager = IoCManager.Resolve<IEntityManager>();
-            var mindSystem = entityManager.System<MindSystem>();
-            
-            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)));
index f95919e3a8ad4383b72fe6e3426d199a5e89c7e6..59964254c8189fd3b6f5f787a7a463a25ac57aea 100644 (file)
@@ -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)
index dabcefa9b9a20d3ab5360ea8c3cabbd328ada8d1..1730a48ac00f3eb1b9b64379e6df71dc970de1ab 100644 (file)
@@ -14,7 +14,7 @@ public sealed class PortalSystem : SharedPortalSystem
     protected override void LogTeleport(EntityUid portal, EntityUid subject, EntityCoordinates source,
         EntityCoordinates target)
     {
-        if (HasComp<MindContainerComponent>(subject))
+        if (HasComp<MindComponent>(subject))
             _adminLogger.Add(LogType.Teleport, LogImpact.Low, $"{ToPrettyString(subject):player} teleported via {ToPrettyString(portal)} from {source} to {target}");
     }
 }
index ca16f1a527a5c23d9f4c7ccf6817f4525bf94084..4e23122e7d1a9cf00409b2f8b5ecff36fd631491 100644 (file)
@@ -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<IEntityManager>();
-            var mindSystem = entityManager.System<MindSystem>();
-            
-            if (mindSystem.TryGetSession(Mind, out var session))
+            if (Mind.TryGetSession(out var session))
             {
                 var chatMgr = IoCManager.Resolve<IChatManager>();
                 chatMgr.DispatchServerMessage(session, Loc.GetString("traitor-role-greeting"));
index ef81894bc2b2c9af1770b43de1fce340b41d2476..9def8fc3166e6714a65ec7b282a5029dba4f56c0 100644 (file)
@@ -26,7 +26,7 @@ public sealed class TraitorDeathMatchRedemptionSystem : EntitySystem
 
     private void OnInteractUsing(EntityUid uid, TraitorDeathMatchRedemptionComponent component, InteractUsingEvent args)
     {
-        if (!EntityManager.TryGetComponent<MindContainerComponent>(args.User, out var userMindComponent))
+        if (!EntityManager.TryGetComponent<MindComponent>(args.User, out var userMindComponent))
         {
             _popup.PopupEntity(Loc.GetString(
                 "traitor-death-match-redemption-component-interact-using-main-message",
index 572ab6f5928c783bbe27258dfcbac04729742e33..1994b98a7a96debaefcdfda9dcbc3edcf3c32a7b 100644 (file)
@@ -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<MindContainerComponent>(target);
-            if (_mindSystem.TryGetMind(target, out var mind, mindComp) && _mindSystem.TryGetSession(mind, out var session))
+            var mindcomp = EnsureComp<MindComponent>(target);
+            if (mindcomp.Mind != null && mindcomp.Mind.TryGetSession(out var session))
             {
                 //Zombie role for player manifest
-                _mindSystem.AddRole(mind, new TraitorRole(mind, _proto.Index<AntagPrototype>(zombiecomp.ZombieRoleId)));
+                mindcomp.Mind.AddRole(new TraitorRole(mindcomp.Mind, _proto.Index<AntagPrototype>(zombiecomp.ZombieRoleId)));
                 //Greeting message for new bebe zombers
                 _chatMan.DispatchServerMessage(session, Loc.GetString("zombie-infection-greeting"));
             }
 
-            if (!HasComp<GhostRoleMobSpawnerComponent>(target) && !mindComp.HasMind) //this specific component gives build test trouble so pop off, ig
+            if (!HasComp<GhostRoleMobSpawnerComponent>(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<GhostTakeoverAvailableComponent>(target, out var ghostcomp);
index 7374dcd1630da384a4fb61449e9c8901e94efd6d..0711958b70b7c88d302a2c13f66f15739a93d675 100644 (file)
@@ -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.
index 14e1f4ac7107d8a7d122524384e9c62cc83c71df..d1708d005d6e48cf6a9e7da29760ecc7fbe8b758 100644 (file)
@@ -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
index ba22125b13d4c7d0daf11a9c7f60f3b4429ebcaa..ace5fd81ec352436c35cd98d8891ebc75ac4a759 100644 (file)
@@ -3,7 +3,7 @@
   name: revenant
   description: A spooky ghostie.
   components:
-  - type: MindContainer
+  - type: Mind
   - type: InputMover
   - type: MobMover
   - type: Input
index 97c97d021409714a2c16419b1f647da194da2924..79dfcdcf4bf19eb7bde77c822909a2d31c6f7f55 100644 (file)
@@ -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"
index a9dd505bb4b12ddd8e42b72bd56ad5afaa7fe508..e0d1a3a2460fb6c4704714901f034e244572a2be 100644 (file)
@@ -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"
index 0e887fc40eee396e9aa7955294d2c88f8f2322c6..d8477281ed2eea99b96fd2aad4a58d8102931f4f 100644 (file)
@@ -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
index 19fe958bfed25b0791518b2e736cb3be7886188a..60f86a10b8ab8af51151376366dba227e39c2c45 100644 (file)
@@ -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"
index 81fc4b36705d7f90803b1faf0e330782942c78b1..8ef363de41e4e2b8b884c6b257545d3c2331861f 100644 (file)
@@ -5,7 +5,7 @@
   save: false
   description: Boo!
   components:
-  - type: MindContainer
+  - type: Mind
   - type: Clickable
   - type: InteractionOutline
   - type: Physics
index d05950dd18e4ccca914354e99156c5ce06836ce4..4890c8b6a878473473eb55931cef0b433368357a 100644 (file)
@@ -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"
index 3764e686e1907a30762bff498faad1cb3ec946e0..054e50b9219f500420a584f2261c0163a0f4c5ba 100644 (file)
@@ -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"
index c56ae9a09279e63fe20e09acb6d682294f485f8d..c379eeb95e8ffe1e867fca6c92c4c8dcc3bce8a2 100644 (file)
@@ -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"
index 870297ae803bfcc899e3c17a68372de0335f9ac2..a74e95680c871c90f66d578375c95e65939bb5c3 100644 (file)
@@ -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
+