]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
remove Session from MindComponent (#34753)
authorMilon <milonpl.git@proton.me>
Fri, 18 Apr 2025 22:23:01 +0000 (00:23 +0200)
committerGitHub <noreply@github.com>
Fri, 18 Apr 2025 22:23:01 +0000 (00:23 +0200)
* yummy

* fix tests

25 files changed:
Content.IntegrationTests/Tests/Minds/MindTests.Helpers.cs
Content.IntegrationTests/Tests/Minds/MindTests.ReconnectTests.cs
Content.Server/Administration/Commands/AGhostCommand.cs
Content.Server/Administration/Systems/AdminSystem.cs
Content.Server/Anomaly/Effects/InnerBodyAnomalySystem.cs
Content.Server/Antag/AntagSelectionSystem.API.cs
Content.Server/Chat/Managers/ChatManager.cs
Content.Server/Cloning/CloningConsoleSystem.cs
Content.Server/GameTicking/GameTicker.Player.cs
Content.Server/GameTicking/Rules/RevolutionaryRuleSystem.cs
Content.Server/GameTicking/Rules/ZombieRuleSystem.cs
Content.Server/Ghost/GhostSystem.cs
Content.Server/Ghost/ReturnToBodyEui.cs
Content.Server/Medical/DefibrillatorSystem.cs
Content.Server/Mind/MindSystem.cs
Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs
Content.Server/Roles/Jobs/JobSystem.cs
Content.Server/Roles/RoleSystem.cs
Content.Server/Silicons/Borgs/BorgSystem.cs
Content.Server/Traitor/Systems/AutoTraitorSystem.cs
Content.Server/Zombies/ZombieSystem.Transform.cs
Content.Shared/Bed/Cryostorage/SharedCryostorageSystem.cs
Content.Shared/Mind/MindComponent.cs
Content.Shared/Mind/SharedMindSystem.cs
Content.Shared/Roles/SharedRoleSystem.cs

index b12c90e16e26e30181d1333111eb6950327d69c7..cebbed8ee8f2825300668a02100b9626881fa95e 100644 (file)
@@ -130,14 +130,14 @@ public sealed partial class MindTests
         ActorComponent actor = default!;
         Assert.Multiple(() =>
         {
-            Assert.That(player, Is.EqualTo(mind.Session), "Player session does not match mind session");
+            Assert.That(player.UserId, Is.EqualTo(mind.UserId), "Player UserId does not match mind UserId");
             Assert.That(entMan.System<MindSystem>().GetMind(player.UserId), Is.EqualTo(mindId));
             Assert.That(player.AttachedEntity, Is.EqualTo(mind.CurrentEntity), "Player is not attached to the mind's current entity.");
             Assert.That(entMan.EntityExists(mind.OwnedEntity), "The mind's current entity does not exist");
             Assert.That(mind.VisitingEntity == null || entMan.EntityExists(mind.VisitingEntity), "The minds visited entity does not exist.");
             Assert.That(entMan.TryGetComponent(mind.CurrentEntity, out actor));
         });
-        Assert.That(actor.PlayerSession, Is.EqualTo(mind.Session));
+        Assert.That(actor.PlayerSession.UserId, Is.EqualTo(mind.UserId));
 
         return (mindId, mind);
     }
@@ -161,7 +161,6 @@ public sealed partial class MindTests
         {
             Assert.That(player.Status, Is.EqualTo(SessionStatus.Disconnected));
             Assert.That(mind.UserId, Is.Not.Null);
-            Assert.That(mind.Session, Is.Null);
         });
     }
 
index a1fccfb68dbf9320ab9efae4f98593c35196c556..db87797553fed9f0ec9c02c2deab38864f7ca0b6 100644 (file)
@@ -67,7 +67,7 @@ public sealed partial class MindTests
         Assert.Multiple(() =>
         {
             Assert.That(entMan.Deleted(entity));
-            Assert.That(mind.Comp.OwnedEntity, Is.Null);
+            Assert.That(mind.Comp.OwnedEntity, Is.Not.EqualTo(entity));
         });
 
         // Reconnect
index 6acaadbf838cc4f1c43c55d445396693c18dc2b1..09c8d0eb5086b7f5b52070664873bc51d66866e0 100644 (file)
@@ -8,6 +8,7 @@ using Content.Shared.Mind;
 using Robust.Server.GameObjects;
 using Robust.Server.Player;
 using Robust.Shared.Console;
+using Robust.Shared.Player;
 
 namespace Content.Server.Administration.Commands;
 
@@ -15,7 +16,7 @@ namespace Content.Server.Administration.Commands;
 public sealed class AGhostCommand : LocalizedCommands
 {
     [Dependency] private readonly IEntityManager _entities = default!;
-    [Dependency] private readonly IPlayerManager _playerManager = default!;
+    [Dependency] private readonly ISharedPlayerManager _playerManager = default!;
 
     public override string Command => "aghost";
     public override string Help => "aghost";
@@ -104,8 +105,8 @@ public sealed class AGhostCommand : LocalizedCommands
             // TODO: Remove duplication between all this and "GamePreset.OnGhostAttempt()"...
             if (!string.IsNullOrWhiteSpace(mind.CharacterName))
                 metaDataSystem.SetEntityName(ghost, mind.CharacterName);
-            else if (!string.IsNullOrWhiteSpace(mind.Session?.Name))
-                metaDataSystem.SetEntityName(ghost, mind.Session.Name);
+            else if (!string.IsNullOrWhiteSpace(player.Name))
+                metaDataSystem.SetEntityName(ghost, player.Name);
 
             mindSystem.Visit(mindId, ghost, mind);
         }
index 0868157f6ecacd21f02fa59e631c26d5ca6ffd2c..b9916bc5b255cc6c4093009f26f0b84b342ee1f2 100644 (file)
@@ -153,9 +153,7 @@ public sealed class AdminSystem : EntitySystem
 
     private void OnRoleEvent(RoleEvent ev)
     {
-        var session = _minds.GetSession(ev.Mind);
-
-        if (!ev.RoleTypeUpdate || session == null)
+        if (!ev.RoleTypeUpdate || !_playerManager.TryGetSessionById(ev.Mind.UserId, out var session))
             return;
 
         UpdatePlayerList(session);
index b647e026e30191f13e8d1b9181cfc13bae75ddd7..ff644ad3e00a7a4eca06506ebe3547564ff0e0ff 100644 (file)
@@ -15,6 +15,7 @@ using Content.Shared.Popups;
 using Content.Shared.Whitelist;
 using Robust.Shared.Audio.Systems;
 using Robust.Shared.Physics.Events;
+using Robust.Shared.Player;
 using Robust.Shared.Prototypes;
 
 namespace Content.Server.Anomaly.Effects;
@@ -26,6 +27,7 @@ public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
     [Dependency] private readonly SharedAudioSystem _audio = default!;
     [Dependency] private readonly BodySystem _body = default!;
     [Dependency] private readonly IChatManager _chat = default!;
+    [Dependency] private readonly ISharedPlayerManager _player = default!;
     [Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
     [Dependency] private readonly JitteringSystem _jitter = default!;
     [Dependency] private readonly MindSystem _mind = default!;
@@ -102,7 +104,7 @@ public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
 
         if (ent.Comp.StartMessage is not null &&
             _mind.TryGetMind(ent, out _, out var mindComponent) &&
-            mindComponent.Session != null)
+            _player.TryGetSessionById(mindComponent.UserId, out var session))
         {
             var message = Loc.GetString(ent.Comp.StartMessage);
             var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
@@ -111,7 +113,7 @@ public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
                 wrappedMessage,
                 default,
                 false,
-                mindComponent.Session.Channel,
+                session.Channel,
                 _messageColor);
 
             _popup.PopupEntity(message, ent, ent, PopupType.MediumCaution);
@@ -137,7 +139,8 @@ public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
 
     private void OnSeverityChanged(Entity<InnerBodyAnomalyComponent> ent, ref AnomalySeverityChangedEvent args)
     {
-        if (!_mind.TryGetMind(ent, out _, out var mindComponent) || mindComponent.Session == null)
+        if (!_mind.TryGetMind(ent, out _, out var mindComponent) ||
+            !_player.TryGetSessionById(mindComponent.UserId, out var session))
             return;
 
         var message = string.Empty;
@@ -172,7 +175,7 @@ public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
             wrappedMessage,
             default,
             false,
-            mindComponent.Session.Channel,
+            session.Channel,
             _messageColor);
 
         _popup.PopupEntity(message, ent, ent, PopupType.MediumCaution);
@@ -214,7 +217,7 @@ public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
 
         if (ent.Comp.EndMessage is not null &&
             _mind.TryGetMind(ent, out _, out var mindComponent) &&
-            mindComponent.Session != null)
+            _player.TryGetSessionById(mindComponent.UserId, out var session))
         {
             var message = Loc.GetString(ent.Comp.EndMessage);
             var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
@@ -223,7 +226,7 @@ public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
                 wrappedMessage,
                 default,
                 false,
-                mindComponent.Session.Channel,
+                session.Channel,
                 _messageColor);
 
 
index 93b5fa6136516e2c13bfc444771e50541d652a55..975c802eedd1672d22a1d94faafbf237b3057fec 100644 (file)
@@ -264,10 +264,10 @@ public sealed partial class AntagSelectionSystem
         if (!_mind.TryGetMind(entity, out _, out var mindComponent))
             return;
 
-        if (mindComponent.Session == null)
+        if (!_playerManager.TryGetSessionById(mindComponent.UserId, out var session))
             return;
 
-        SendBriefing(mindComponent.Session, briefing, briefingColor, briefingSound);
+        SendBriefing(session, briefing, briefingColor, briefingSound);
     }
 
     /// <summary>
index c86ff802ce7067711c5368e3391346723d230630..535ca8658d22e7ed866ec498f767763f14edd9ad 100644 (file)
@@ -44,6 +44,7 @@ internal sealed partial class ChatManager : IChatManager
     [Dependency] private readonly INetConfigurationManager _netConfigManager = default!;
     [Dependency] private readonly IEntityManager _entityManager = default!;
     [Dependency] private readonly PlayerRateLimitManager _rateLimitManager = default!;
+    [Dependency] private readonly ISharedPlayerManager _player = default!;
 
     /// <summary>
     /// The maximum length a player-sent message can be sent
@@ -179,7 +180,12 @@ internal sealed partial class ChatManager : IChatManager
         var adminSystem = _entityManager.System<AdminSystem>();
         var antag = mind.UserId != null && (adminSystem.GetCachedPlayerInfo(mind.UserId.Value)?.Antag ?? false);
 
-        SendAdminAlert($"{mind.Session?.Name}{(antag ? " (ANTAG)" : "")} {message}");
+        // We shouldn't be repeating this but I don't want to touch any more chat code than necessary
+        var playerName = mind.UserId is { } userId && _player.TryGetSessionById(userId, out var session)
+            ? session.Name
+            : "Unknown";
+
+        SendAdminAlert($"{playerName}{(antag ? " (ANTAG)" : "")} {message}");
     }
 
     public void SendHookOOC(string sender, string message)
index 39eac842f0a57e7e2855f9986f43c6d5479238e5..b5cf2dbb8a4840c18ea3fb9d4882b18084acec14 100644 (file)
@@ -165,7 +165,7 @@ namespace Content.Server.Cloning
             if (!_mindSystem.TryGetMind(body.Value, out var mindId, out var mind))
                 return;
 
-            if (mind.UserId.HasValue == false || mind.Session == null)
+            if (mind.UserId.HasValue == false || !_playerManager.ValidSessionId(mind.UserId.Value))
                 return;
 
             if (_cloningPodSystem.TryCloning(cloningPodUid, body.Value, (mindId, mind), cloningPod, scannerComp.CloningFailChanceMultiplier))
index 2c3dcaba43362c494a54828dc4dbef1033c2fafb..63821d9251cd82fcf58fac344e93adc180f9bec1 100644 (file)
@@ -32,11 +32,8 @@ namespace Content.Server.GameTicking
             {
                 if (args.NewStatus != SessionStatus.Disconnected)
                 {
-                    mind.Session = session;
                     _pvsOverride.AddSessionOverride(mindId.Value, session);
                 }
-
-                DebugTools.Assert(mind.Session == session);
             }
 
             DebugTools.Assert(session.GetMind() == mindId);
@@ -126,10 +123,9 @@ namespace Content.Server.GameTicking
                 case SessionStatus.Disconnected:
                 {
                     _chatManager.SendAdminAnnouncement(Loc.GetString("player-leave-message", ("name", args.Session.Name)));
-                    if (mind != null)
+                    if (mindId != null)
                     {
-                        _pvsOverride.ClearOverride(GetNetEntity(mindId!.Value));
-                        mind.Session = null;
+                        _pvsOverride.RemoveSessionOverride(mindId.Value, session);
                     }
 
                     _userDb.ClientDisconnected(session);
index 9ec932b06fcbf12a9206f1d17c5204221d88178b..311e78d0094fb7072987addc13f1d76d7c3fd937 100644 (file)
@@ -28,6 +28,7 @@ using Content.Shared.Zombies;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Timing;
 using Content.Shared.Cuffs.Components;
+using Robust.Shared.Player;
 
 namespace Content.Server.GameTicking.Rules;
 
@@ -36,19 +37,20 @@ namespace Content.Server.GameTicking.Rules;
 /// </summary>
 public sealed class RevolutionaryRuleSystem : GameRuleSystem<RevolutionaryRuleComponent>
 {
-    [Dependency] private readonly IAdminLogManager _adminLogManager = default!;
     [Dependency] private readonly AntagSelectionSystem _antag = default!;
     [Dependency] private readonly EmergencyShuttleSystem _emergencyShuttle = default!;
     [Dependency] private readonly EuiManager _euiMan = default!;
+    [Dependency] private readonly IAdminLogManager _adminLogManager = default!;
+    [Dependency] private readonly IGameTiming _timing = default!;
+    [Dependency] private readonly ISharedPlayerManager _player = default!;
     [Dependency] private readonly MindSystem _mind = default!;
     [Dependency] private readonly MobStateSystem _mobState = default!;
     [Dependency] private readonly NpcFactionSystem _npcFaction = default!;
     [Dependency] private readonly PopupSystem _popup = default!;
     [Dependency] private readonly RoleSystem _role = default!;
-    [Dependency] private readonly SharedStunSystem _stun = default!;
     [Dependency] private readonly RoundEndSystem _roundEnd = default!;
+    [Dependency] private readonly SharedStunSystem _stun = default!;
     [Dependency] private readonly StationSystem _stationSystem = default!;
-    [Dependency] private readonly IGameTiming _timing = default!;
 
     //Used in OnPostFlash, no reference to the rule component is available
     public readonly ProtoId<NpcFactionPrototype> RevolutionaryNpcFaction = "Revolutionary";
@@ -165,8 +167,8 @@ public sealed class RevolutionaryRuleSystem : GameRuleSystem<RevolutionaryRuleCo
             _role.MindAddRole(mindId, "MindRoleRevolutionary");
         }
 
-        if (mind?.Session != null)
-            _antag.SendBriefing(mind.Session, Loc.GetString("rev-role-greeting"), Color.Red, revComp.RevStartSound);
+        if (mind is { UserId: not null } && _player.TryGetSessionById(mind.UserId, out var session))
+            _antag.SendBriefing(session, Loc.GetString("rev-role-greeting"), Color.Red, revComp.RevStartSound);
     }
 
     //TODO: Enemies of the revolution
@@ -228,7 +230,7 @@ public sealed class RevolutionaryRuleSystem : GameRuleSystem<RevolutionaryRuleCo
                 _popup.PopupEntity(Loc.GetString("rev-break-control", ("name", Identity.Entity(uid, EntityManager))), uid);
                 _adminLogManager.Add(LogType.Mind, LogImpact.Medium, $"{ToPrettyString(uid)} was deconverted due to all Head Revolutionaries dying.");
 
-                if (!_mind.TryGetMind(uid, out var mindId, out _, mc))
+                if (!_mind.TryGetMind(uid, out var mindId, out var mind, mc))
                     continue;
 
                 // remove their antag role
@@ -236,7 +238,7 @@ public sealed class RevolutionaryRuleSystem : GameRuleSystem<RevolutionaryRuleCo
 
                 // make it very obvious to the rev they've been deconverted since
                 // they may not see the popup due to antag and/or new player tunnel vision
-                if (_mind.TryGetSession(mindId, out var session))
+                if (_player.TryGetSessionById(mind.UserId, out var session))
                     _euiMan.OpenEui(new DeconvertedEui(), session);
             }
             return true;
index bb76721340dc292a6df315d92f4331a0142cc33e..a38940c667e2f44deff5d7a05c51b0039a7ac876 100644 (file)
@@ -25,13 +25,14 @@ public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
 {
     [Dependency] private readonly AntagSelectionSystem _antag = default!;
     [Dependency] private readonly ChatSystem _chat = default!;
-    [Dependency] private readonly SharedMindSystem _mindSystem = default!;
+    [Dependency] private readonly IGameTiming _timing = default!;
+    [Dependency] private readonly ISharedPlayerManager _player = default!;
     [Dependency] private readonly MobStateSystem _mobState = default!;
     [Dependency] private readonly PopupSystem _popup = default!;
-    [Dependency] private readonly SharedRoleSystem _roles = default!;
     [Dependency] private readonly RoundEndSystem _roundEnd = default!;
+    [Dependency] private readonly SharedMindSystem _mindSystem = default!;
+    [Dependency] private readonly SharedRoleSystem _roles = default!;
     [Dependency] private readonly StationSystem _station = default!;
-    [Dependency] private readonly IGameTiming _timing = default!;
     [Dependency] private readonly ZombieSystem _zombie = default!;
 
     public override void Initialize()
@@ -95,9 +96,10 @@ public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
         {
             var meta = MetaData(survivor);
             var username = string.Empty;
-            if (_mindSystem.TryGetMind(survivor, out _, out var mind) && mind.Session != null)
+            if (_mindSystem.TryGetMind(survivor, out _, out var mind) &&
+                _player.TryGetSessionById(mind.UserId, out var session))
             {
-                username = mind.Session.Name;
+                username = session.Name;
             }
 
             args.AddLine(Loc.GetString("zombie-round-end-user-was-survivor",
index df4d998128dba521bf6a9f1ccbed64433b3d0077..0cccab64b69fa24603ce6ac87ce105a060dd1f6a 100644 (file)
@@ -53,7 +53,7 @@ namespace Content.Server.Ghost
         [Dependency] private readonly MindSystem _minds = default!;
         [Dependency] private readonly MobStateSystem _mobState = default!;
         [Dependency] private readonly SharedPhysicsSystem _physics = default!;
-        [Dependency] private readonly IPlayerManager _playerManager = default!;
+        [Dependency] private readonly ISharedPlayerManager _player = default!;
         [Dependency] private readonly TransformSystem _transformSystem = default!;
         [Dependency] private readonly VisibilitySystem _visibilitySystem = default!;
         [Dependency] private readonly MetaDataSystem _metaData = default!;
@@ -364,7 +364,7 @@ namespace Content.Server.Ghost
 
         private IEnumerable<GhostWarp> GetPlayerWarps(EntityUid except)
         {
-            foreach (var player in _playerManager.Sessions)
+            foreach (var player in _player.Sessions)
             {
                 if (player.AttachedEntity is not {Valid: true} attached)
                     continue;
@@ -484,8 +484,8 @@ namespace Content.Server.Ghost
             // However, that should rarely happen.
             if (!string.IsNullOrWhiteSpace(mind.Comp.CharacterName))
                 _metaData.SetEntityName(ghost, mind.Comp.CharacterName);
-            else if (!string.IsNullOrWhiteSpace(mind.Comp.Session?.Name))
-                _metaData.SetEntityName(ghost, mind.Comp.Session.Name);
+            else if (mind.Comp.UserId is { } userId && _player.TryGetSessionById(userId, out var session))
+                _metaData.SetEntityName(ghost, session.Name);
 
             if (mind.Comp.TimeOfDeath.HasValue)
             {
@@ -530,9 +530,9 @@ namespace Content.Server.Ghost
 
             if (mind.PreventGhosting && !forced)
             {
-                if (mind.Session != null) // Logging is suppressed to prevent spam from ghost attempts caused by movement attempts
+                if (_player.TryGetSessionById(mind.UserId, out var session)) // Logging is suppressed to prevent spam from ghost attempts caused by movement attempts
                 {
-                    _chatManager.DispatchServerMessage(mind.Session, Loc.GetString("comp-mind-ghosting-prevented"),
+                    _chatManager.DispatchServerMessage(session, Loc.GetString("comp-mind-ghosting-prevented"),
                         true);
                 }
 
index 77b143f7df91f7dc6f0622c89645bd5d09e30d32..50664b30d1bf5da73fa45c06bcbf38176b0ccbc5 100644 (file)
@@ -2,19 +2,22 @@ using Content.Server.EUI;
 using Content.Shared.Eui;
 using Content.Shared.Ghost;
 using Content.Shared.Mind;
+using Robust.Shared.Network;
+using Robust.Shared.Player;
 
 namespace Content.Server.Ghost;
 
 public sealed class ReturnToBodyEui : BaseEui
 {
     private readonly SharedMindSystem _mindSystem;
+    private readonly ISharedPlayerManager _player;
+    private readonly NetUserId? _userId;
 
-    private readonly MindComponent _mind;
-
-    public ReturnToBodyEui(MindComponent mind, SharedMindSystem mindSystem)
+    public ReturnToBodyEui(MindComponent mind, SharedMindSystem mindSystem, ISharedPlayerManager player)
     {
-        _mind = mind;
         _mindSystem = mindSystem;
+        _player = player;
+        _userId = mind.UserId;
     }
 
     public override void HandleMessage(EuiMessageBase msg)
@@ -28,7 +31,8 @@ public sealed class ReturnToBodyEui : BaseEui
             return;
         }
 
-        _mindSystem.UnVisit(_mind.Session);
+        if (_userId is { } userId && _player.TryGetSessionById(userId, out var session))
+            _mindSystem.UnVisit(session);
 
         Close();
     }
index ba272c92f51d46532bc727ca92512191ffdf38e5..94d62641cec35be40e96b86ab3a0efdb041eef2a 100644 (file)
@@ -36,12 +36,13 @@ public sealed class DefibrillatorSystem : EntitySystem
     [Dependency] private readonly DoAfterSystem _doAfter = default!;
     [Dependency] private readonly ElectrocutionSystem _electrocution = default!;
     [Dependency] private readonly EuiManager _euiManager = default!;
+    [Dependency] private readonly ISharedPlayerManager _player = default!;
     [Dependency] private readonly ItemToggleSystem _toggle = default!;
-    [Dependency] private readonly RottingSystem _rotting = default!;
     [Dependency] private readonly MobStateSystem _mobState = default!;
     [Dependency] private readonly MobThresholdSystem _mobThreshold = default!;
     [Dependency] private readonly PopupSystem _popup = default!;
     [Dependency] private readonly PowerCellSystem _powerCell = default!;
+    [Dependency] private readonly RottingSystem _rotting = default!;
     [Dependency] private readonly SharedAudioSystem _audio = default!;
     [Dependency] private readonly SharedMindSystem _mind = default!;
     [Dependency] private readonly UseDelaySystem _useDelay = default!;
@@ -212,13 +213,13 @@ public sealed class DefibrillatorSystem : EntitySystem
             }
 
             if (_mind.TryGetMind(target, out _, out var mind) &&
-                mind.Session is { } playerSession)
+                _player.TryGetSessionById(mind.UserId, out var playerSession))
             {
                 session = playerSession;
                 // notify them they're being revived.
                 if (mind.CurrentEntity != target)
                 {
-                    _euiManager.OpenEui(new ReturnToBodyEui(mind, _mind), session);
+                    _euiManager.OpenEui(new ReturnToBodyEui(mind, _mind, _player), session);
                 }
             }
             else
index 0d3c0c750c00f9da41ee64f10cc0199e0965706e..5601f19e5888493c9aead4edba4f28ecba535632 100644 (file)
@@ -69,7 +69,7 @@ public sealed class MindSystem : SharedMindSystem
         TransferTo(mindId, null, createGhost: false, mind: mind);
         DebugTools.AssertNull(mind.OwnedEntity);
 
-        if (!component.GhostOnShutdown || mind.Session == null || _gameTicker.RunLevel == GameRunLevel.PreRoundLobby)
+        if (!component.GhostOnShutdown || _gameTicker.RunLevel == GameRunLevel.PreRoundLobby)
             return;
 
         var ghost = _ghosts.SpawnGhost((mindId, mind), uid);
@@ -93,16 +93,6 @@ public sealed class MindSystem : SharedMindSystem
         return false;
     }
 
-    public ICommonSession? GetSession(MindComponent mind)
-    {
-        return mind.Session;
-    }
-
-    public bool TryGetSession(MindComponent mind, [NotNullWhen(true)] out ICommonSession? session)
-    {
-        return (session = GetSession(mind)) != null;
-    }
-
     public override void WipeAllMinds()
     {
         base.WipeAllMinds();
@@ -144,10 +134,10 @@ public sealed class MindSystem : SharedMindSystem
 
         // Do this AFTER the entity changes above as this will fire off a player-detached event
         // which will run ghosting twice.
-        if (GetSession(mind) is { } session)
+        if (_players.TryGetSessionById(mind.UserId, out var session))
             _players.SetAttachedEntity(session, entity);
 
-        Log.Info($"Session {mind.Session?.Name} visiting entity {entity}.");
+        Log.Info($"Session {session?.Name} visiting entity {entity}.");
     }
 
     public override void UnVisit(EntityUid mindId, MindComponent? mind = null)
@@ -162,17 +152,19 @@ public sealed class MindSystem : SharedMindSystem
 
         RemoveVisitingEntity(mindId, mind);
 
-        if (mind.Session == null || mind.Session.AttachedEntity == mind.VisitingEntity)
+        if (mind.UserId == null || !_players.TryGetSessionById(mind.UserId.Value, out var session))
+            return;
+
+        if (session.AttachedEntity == mind.VisitingEntity)
             return;
 
         var owned = mind.OwnedEntity;
-        if (GetSession(mind) is { } session)
-            _players.SetAttachedEntity(session, owned);
+        _players.SetAttachedEntity(session, owned);
 
         if (owned.HasValue)
         {
             _adminLogger.Add(LogType.Mind, LogImpact.Low,
-                $"{mind.Session.Name} returned to {ToPrettyString(owned.Value)}");
+                $"{session.Name} returned to {ToPrettyString(owned.Value)}");
         }
     }
 
@@ -199,7 +191,8 @@ public sealed class MindSystem : SharedMindSystem
             if (TryComp<ActorComponent>(entity.Value, out var actor))
             {
                 // Happens when transferring to your currently visited entity.
-                if (actor.PlayerSession != mind.Session)
+                if (!_players.TryGetSessionByEntity(entity.Value, out var session) ||
+                    mind.UserId == null || actor.PlayerSession != session )
                 {
                     throw new ArgumentException("Visit target already has a session.", nameof(entity));
                 }
@@ -253,12 +246,12 @@ public sealed class MindSystem : SharedMindSystem
         }
 
         // Player is CURRENTLY connected.
-        var session = GetSession(mind);
-        if (session != null && !alreadyAttached && mind.VisitingEntity == null)
+        if (mind.UserId != null && _players.TryGetSessionById(mind.UserId.Value, out var userSession)
+                                && !alreadyAttached && mind.VisitingEntity == null)
         {
-            _players.SetAttachedEntity(session, entity, true);
-            DebugTools.Assert(session.AttachedEntity == entity, $"Failed to attach entity.");
-            Log.Info($"Session {session.Name} transferred to entity {entity}.");
+            _players.SetAttachedEntity(userSession, entity, true);
+            DebugTools.Assert(userSession.AttachedEntity == entity, "Failed to attach entity.");
+            Log.Info($"Session {userSession.Name} transferred to entity {entity}.");
         }
 
         if (entity != null)
@@ -288,18 +281,18 @@ public sealed class MindSystem : SharedMindSystem
             return;
 
         Dirty(mindId, mind);
-        var netMind = GetNetEntity(mindId);
-        _pvsOverride.ClearOverride(netMind);
+
         if (userId != null && !_players.TryGetPlayerData(userId.Value, out _))
         {
             Log.Error($"Attempted to set mind user to invalid value {userId}");
             return;
         }
 
-        if (mind.Session != null)
+        // Clear any existing entity attachment
+        if (_players.TryGetSessionById(mind.UserId, out var oldSession))
         {
-            _players.SetAttachedEntity(GetSession(mind), null);
-            mind.Session = null;
+            _players.SetAttachedEntity(oldSession, null);
+            _pvsOverride.RemoveSessionOverride(mindId, oldSession);
         }
 
         if (mind.UserId != null)
@@ -311,10 +304,7 @@ public sealed class MindSystem : SharedMindSystem
         }
 
         if (userId == null)
-        {
-            DebugTools.AssertNull(mind.Session);
             return;
-        }
 
         if (UserMinds.TryGetValue(userId.Value, out var oldMindId) &&
             TryComp(oldMindId, out MindComponent? oldMind))
@@ -333,11 +323,10 @@ public sealed class MindSystem : SharedMindSystem
         if (_players.GetPlayerData(userId.Value).ContentData() is { } data)
             data.Mind = mindId;
 
-        if (_players.TryGetSessionById(userId.Value, out var ret))
+        if (_players.TryGetSessionById(userId.Value, out var session))
         {
-            mind.Session = ret;
-            _pvsOverride.AddSessionOverride(mindId, ret);
-            _players.SetAttachedEntity(ret, mind.CurrentEntity);
+            _pvsOverride.AddSessionOverride(mindId, session);
+            _players.SetAttachedEntity(session, mind.CurrentEntity);
         }
     }
 
index b8c0d3f45009e43eabf703685eb8ef67498f7dcd..9f4b6599b8f3b66546281ed96a912dd6c5da9226 100644 (file)
@@ -123,7 +123,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
 
     private void OnRoleEvent(RoleEvent ev)
     {
-        if (_minds.TryGetSession(ev.Mind, out var session))
+        if (_playerManager.TryGetSessionById(ev.Mind.UserId, out var session))
             _tracking.QueueRefreshTrackers(session);
     }
 
index 28cfbe76b51c066ce9dcad46e533b44cadc7f0ef..3603225dfb13c3748fb2d7c153450ddb66386ff2 100644 (file)
@@ -4,6 +4,7 @@ using Content.Server.Mind;
 using Content.Shared.Mind;
 using Content.Shared.Roles;
 using Content.Shared.Roles.Jobs;
+using Robust.Shared.Player;
 
 namespace Content.Server.Roles.Jobs;
 
@@ -14,6 +15,7 @@ public sealed class JobSystem : SharedJobSystem
 {
     [Dependency] private readonly IChatManager _chat = default!;
     [Dependency] private readonly MindSystem _mind = default!;
+    [Dependency] private readonly ISharedPlayerManager _player = default!;
     [Dependency] private readonly RoleSystem _roles = default!;
 
     public override void Initialize()
@@ -42,7 +44,7 @@ public sealed class JobSystem : SharedJobSystem
         if (args.Silent)
             return;
 
-        if (!_mind.TryGetSession(mindId, out var session))
+        if (!_player.TryGetSessionById(component.UserId, out var session))
             return;
 
         if (!MindTryGetJob(mindId, out var prototype))
index 278ac485797368ce0df5f3befe2a033fb33eee75..6cbd039c7307ae056774f27fb3910428e2ca11e9 100644 (file)
@@ -46,7 +46,7 @@ public sealed class RoleSystem : SharedRoleSystem
 
     public void RoleUpdateMessage(MindComponent mind)
     {
-        if (mind.Session is null)
+        if (!Player.TryGetSessionById(mind.UserId, out var session))
             return;
 
         if (!_proto.TryIndex(mind.RoleType, out var proto))
@@ -55,8 +55,6 @@ public sealed class RoleSystem : SharedRoleSystem
         var roleText = Loc.GetString(proto.Name);
         var color = proto.Color;
 
-        var session = mind.Session;
-
         //TODO add audio? Would need to be optional so it does not play on role changes that already come with their own audio
         // _audio.PlayGlobal(Sound, session);
 
index d8fa1f300bec4e971a5bb44d6b4928cb77c5c06c..82e247cb0b5246c75f4d78372fac32dfbb43c843 100644 (file)
@@ -54,7 +54,7 @@ public sealed partial class BorgSystem : SharedBorgSystem
     [Dependency] private readonly UserInterfaceSystem _ui = default!;
     [Dependency] private readonly SharedContainerSystem _container = default!;
     [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
-
+    [Dependency] private readonly ISharedPlayerManager _player = default!;
 
     [ValidatePrototypeId<JobPrototype>]
     public const string BorgJobId = "Borg";
@@ -110,9 +110,10 @@ public sealed partial class BorgSystem : SharedBorgSystem
         if (component.BrainEntity == null && brain != null &&
             _whitelistSystem.IsWhitelistPassOrNull(component.BrainWhitelist, used))
         {
-            if (_mind.TryGetMind(used, out _, out var mind) && mind.Session != null)
+            if (_mind.TryGetMind(used, out _, out var mind) &&
+                _player.TryGetSessionById(mind.UserId, out var session))
             {
-                if (!CanPlayerBeBorged(mind.Session))
+                if (!CanPlayerBeBorged(session))
                 {
                     Popup.PopupEntity(Loc.GetString("borg-player-not-allowed"), used, args.User);
                     return;
@@ -245,10 +246,11 @@ public sealed partial class BorgSystem : SharedBorgSystem
             container.ID != chassisComponent.BrainContainerId)
             return;
 
-        if (!_mind.TryGetMind(uid, out var mindId, out var mind) || mind.Session == null)
+        if (!_mind.TryGetMind(uid, out var mindId, out var mind) ||
+            !_player.TryGetSessionById(mind.UserId, out var session))
             return;
 
-        if (!CanPlayerBeBorged(mind.Session))
+        if (!CanPlayerBeBorged(session))
         {
             Popup.PopupEntity(Loc.GetString("borg-player-not-allowed-eject"), uid);
             Container.RemoveEntity(containerEnt, uid);
index d5a4db591a7063b69692ed823f1f474c8a5a95aa..3343fec7ab2e7a3e0cc5aa6281ca86204366a355 100644 (file)
@@ -1,6 +1,7 @@
 using Content.Server.Antag;
 using Content.Server.Traitor.Components;
 using Content.Shared.Mind.Components;
+using Robust.Shared.Player;
 using Robust.Shared.Prototypes;
 
 namespace Content.Server.Traitor.Systems;
@@ -11,6 +12,7 @@ namespace Content.Server.Traitor.Systems;
 public sealed class AutoTraitorSystem : EntitySystem
 {
     [Dependency] private readonly AntagSelectionSystem _antag = default!;
+    [Dependency] private readonly ISharedPlayerManager _player = default!;
 
     public override void Initialize()
     {
@@ -21,6 +23,9 @@ public sealed class AutoTraitorSystem : EntitySystem
 
     private void OnMindAdded(EntityUid uid, AutoTraitorComponent comp, MindAddedMessage args)
     {
-        _antag.ForceMakeAntag<AutoTraitorComponent>(args.Mind.Comp.Session, comp.Profile);
+        if (!_player.TryGetSessionById(args.Mind.Comp.UserId, out var session))
+            return;
+
+        _antag.ForceMakeAntag<AutoTraitorComponent>(session, comp.Profile);
     }
 }
index a7a22c417528463118806b4a6e9f314b250068fd..7be4570160e1f26c1e343cb5d0c827e25815c434 100644 (file)
@@ -35,7 +35,9 @@ using Content.Shared.Prying.Components;
 using Content.Shared.Traits.Assorted;
 using Robust.Shared.Audio.Systems;
 using Content.Shared.Ghost.Roles.Components;
+using Content.Shared.Roles;
 using Content.Shared.Tag;
+using Robust.Shared.Player;
 using Robust.Shared.Prototypes;
 
 namespace Content.Server.Zombies;
@@ -61,6 +63,8 @@ public sealed partial class ZombieSystem
     [Dependency] private readonly NPCSystem _npc = default!;
     [Dependency] private readonly TagSystem _tag = default!;
     [Dependency] private readonly NameModifierSystem _nameMod = default!;
+    [Dependency] private readonly SharedRoleSystem _roles = default!;
+    [Dependency] private readonly ISharedPlayerManager _player = default!;
 
     private static readonly ProtoId<TagPrototype> InvalidForGlobalSpawnSpellTag = "InvalidForGlobalSpawnSpell";
     private static readonly ProtoId<TagPrototype> CannotSuicideTag = "CannotSuicide";
@@ -234,8 +238,8 @@ public sealed partial class ZombieSystem
         _npc.SleepNPC(target, htn);
 
         //He's gotta have a mind
-        var hasMind = _mind.TryGetMind(target, out var mindId, out _);
-        if (hasMind && _mind.TryGetSession(mindId, out var session))
+        var hasMind = _mind.TryGetMind(target, out var mindId, out var mind);
+        if (hasMind && mind != null && _player.TryGetSessionById(mind.UserId, out var session))
         {
             //Zombie role for player manifest
             _role.MindAddRole(mindId, "MindRoleZombie", mind: null, silent: true);
index f6b7a34785294484623625880a953cfeac75a5ab..e17a0a9167fe9d2385c8861fa17bcead1b637d44 100644 (file)
@@ -8,6 +8,7 @@ using Content.Shared.Mobs.Systems;
 using Robust.Shared.Configuration;
 using Robust.Shared.Containers;
 using Robust.Shared.Map;
+using Robust.Shared.Player;
 using Robust.Shared.Timing;
 
 namespace Content.Shared.Bed.Cryostorage;
@@ -17,13 +18,14 @@ namespace Content.Shared.Bed.Cryostorage;
 /// </summary>
 public abstract class SharedCryostorageSystem : EntitySystem
 {
-    [Dependency] protected readonly ISharedAdminLogManager AdminLog = default!;
-    [Dependency] private readonly IConfigurationManager _configuration = default!;
+    [Dependency] private   readonly IConfigurationManager _configuration = default!;
+    [Dependency] private   readonly IMapManager _mapManager = default!;
+    [Dependency] private   readonly ISharedPlayerManager _player = default!;
+    [Dependency] private   readonly MobStateSystem _mobState = default!;
+    [Dependency] private   readonly SharedAppearanceSystem _appearance = default!;
     [Dependency] protected readonly IGameTiming Timing = default!;
-    [Dependency] private readonly IMapManager _mapManager = default!;
-    [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+    [Dependency] protected readonly ISharedAdminLogManager AdminLog = default!;
     [Dependency] protected readonly SharedMindSystem Mind = default!;
-    [Dependency] private readonly MobStateSystem _mobState = default!;
 
     protected EntityUid? PausedMap { get; private set; }
 
@@ -123,7 +125,8 @@ public abstract class SharedCryostorageSystem : EntitySystem
         if (args.Dragged == args.User)
             return;
 
-        if (!Mind.TryGetMind(args.Dragged, out _, out var mindComp) || mindComp.Session?.AttachedEntity != args.Dragged)
+        if (!_player.TryGetSessionByEntity(args.Dragged, out var session) ||
+            session.AttachedEntity != args.Dragged)
             return;
 
         args.CanDrop = false;
index 3b2b9344787e6c30dfcc9d998e3507e18990ffa1..7864d61a8cca6925a456e28d4d07b6d3a7066451 100644 (file)
@@ -113,12 +113,4 @@ public sealed partial class MindComponent : Component
     /// </summary>
     [DataField]
     public LocId? Subtype;
-
-    /// <summary>
-    ///     The session of the player owning this mind.
-    ///     Can be null, in which case the player is currently not logged in.
-    /// </summary>
-    [ViewVariables, Access(typeof(SharedMindSystem), typeof(SharedGameTicker))]
-    // TODO remove this after moving IPlayerManager functions to shared
-    public ICommonSession? Session { get; set; }
 }
index 1b1fcabc981cece9b80486de468d797e79a9bd34..ab17a4221ea7b87ab0e4f8d607b7817e09706fa4 100644 (file)
@@ -26,6 +26,7 @@ public abstract partial class SharedMindSystem : EntitySystem
     [Dependency] private readonly MobStateSystem _mobState = default!;
     [Dependency] private readonly SharedObjectivesSystem _objectives = default!;
     [Dependency] private readonly SharedPlayerSystem _player = default!;
+    [Dependency] private readonly ISharedPlayerManager _playerManager = default!;
     [Dependency] private readonly MetaDataSystem _metadata = default!;
     [Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
 
@@ -153,23 +154,31 @@ public abstract partial class SharedMindSystem : EntitySystem
         if (!mindContainer.ShowExamineInfo || !args.IsInDetailsRange)
             return;
 
-        // TODO predict we can't right now because session stuff isnt networked
+        // TODO: Move this out of the SharedMindSystem into its own comp and predict it
         if (_net.IsClient)
             return;
 
         var dead = _mobState.IsDead(uid);
-        var hasUserId = CompOrNull<MindComponent>(mindContainer.Mind)?.UserId;
-        var hasSession = CompOrNull<MindComponent>(mindContainer.Mind)?.Session;
+        var mind = CompOrNull<MindComponent>(mindContainer.Mind);
+        var hasUserId = mind?.UserId;
+        var hasActiveSession = hasUserId != null && _playerManager.ValidSessionId(hasUserId.Value);
+
+        // Scenarios:
+        // 1. Dead + No User ID: Entity is permanently dead with no player ever attached
+        // 2. Dead + Has User ID + No Session: Player died and disconnected
+        // 3. Dead + Has Session: Player is dead but still connected
+        // 4. Alive + No User ID: Entity was never controlled by a player
+        // 5. Alive + No Session: Player disconnected while alive (SSD)
 
         if (dead && hasUserId == null)
             args.PushMarkup($"[color=mediumpurple]{Loc.GetString("comp-mind-examined-dead-and-irrecoverable", ("ent", uid))}[/color]");
-        else if (dead && hasSession == null)
+        else if (dead && !hasActiveSession)
             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 (hasUserId == null)
             args.PushMarkup($"[color=mediumpurple]{Loc.GetString("comp-mind-examined-catatonic", ("ent", uid))}[/color]");
-        else if (hasSession == null)
+        else if (!hasActiveSession)
             args.PushMarkup($"[color=yellow]{Loc.GetString("comp-mind-examined-ssd", ("ent", uid))}[/color]");
     }
 
@@ -460,12 +469,6 @@ public abstract partial class SharedMindSystem : EntitySystem
         return false;
     }
 
-    public bool TryGetSession(EntityUid? mindId, [NotNullWhen(true)] out ICommonSession? session)
-    {
-        session = null;
-        return TryComp(mindId, out MindComponent? mind) && (session = mind.Session) != null;
-    }
-
     /// <summary>
     /// Gets a mind from uid and/or MindContainerComponent. Used for null checks.
     /// </summary>
index 83ef6cbf239a4ce3fa3c922d50b73233e6e59e82..0407251414d8fa70c83d68788abdd898c96baecd 100644 (file)
@@ -10,6 +10,7 @@ using Robust.Shared.Audio;
 using Robust.Shared.Audio.Systems;
 using Robust.Shared.Configuration;
 using Robust.Shared.Map;
+using Robust.Shared.Player;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Serialization;
 using Robust.Shared.Utility;
@@ -18,12 +19,13 @@ namespace Content.Shared.Roles;
 
 public abstract class SharedRoleSystem : EntitySystem
 {
-    [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
-    [Dependency] private readonly SharedAudioSystem _audio = default!;
-    [Dependency] private readonly IConfigurationManager _cfg = default!;
-    [Dependency] private readonly IEntityManager _entityManager = default!;
-    [Dependency] private readonly SharedMindSystem _minds = default!;
-    [Dependency] private readonly IPrototypeManager _prototypes = default!;
+    [Dependency] private   readonly IConfigurationManager _cfg = default!;
+    [Dependency] private   readonly IEntityManager _entityManager = default!;
+    [Dependency] private   readonly IPrototypeManager _prototypes = default!;
+    [Dependency] private   readonly ISharedAdminLogManager _adminLogger = default!;
+    [Dependency] protected readonly ISharedPlayerManager Player = default!;
+    [Dependency] private   readonly SharedAudioSystem _audio = default!;
+    [Dependency] private   readonly SharedMindSystem _minds = default!;
 
     private JobRequirementOverridePrototype? _requirementOverride;
 
@@ -256,7 +258,7 @@ public abstract class SharedRoleSystem : EntitySystem
         Dirty(mind, comp);
 
         // Update player character window
-        if (_minds.TryGetSession(mind, out var session))
+        if (Player.TryGetSessionById(comp.UserId, out var session))
             RaiseNetworkEvent(new MindRoleTypeChangedEvent(), session.Channel);
         else
         {
@@ -589,8 +591,11 @@ public abstract class SharedRoleSystem : EntitySystem
     /// </summary>
     public void MindPlaySound(EntityUid mindId, SoundSpecifier? sound, MindComponent? mind = null)
     {
-        if (Resolve(mindId, ref mind) && mind.Session != null)
-            _audio.PlayGlobal(sound, mind.Session);
+        if (!Resolve(mindId, ref mind))
+            return;
+
+        if (Player.TryGetSessionById(mind.UserId, out var session))
+            _audio.PlayGlobal(sound, session);
     }
 
     // TODO ROLES Change to readonly.