]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Misc mind tweaks and fixes (#20614)
authorLeon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Sat, 7 Oct 2023 01:00:48 +0000 (12:00 +1100)
committerGitHub <noreply@github.com>
Sat, 7 Oct 2023 01:00:48 +0000 (18:00 -0700)
Content.IntegrationTests/Pair/TestPair.cs
Content.IntegrationTests/Tests/Minds/MindTest.DeleteAllThenGhost.cs [new file with mode: 0644]
Content.Server/Ghost/Ghost.cs
Content.Server/Mind/MindSystem.cs
Content.Shared/Mind/MindComponent.cs
Content.Shared/Mind/SharedMindSystem.cs

index bd79c0f86ba3386a09ab2b46a41f73df2dc1bec1..2971573ff28ebafbcef25fb791c947e975b298b4 100644 (file)
@@ -1,7 +1,12 @@
 #nullable enable
 using System.Collections.Generic;
 using System.IO;
+using System.Linq;
 using Content.Server.GameTicking;
+using Content.Server.Players;
+using Content.Shared.Mind;
+using Content.Shared.Players;
+using Robust.Server.Player;
 using Robust.Shared.GameObjects;
 using Robust.Shared.IoC;
 using Robust.Shared.Network;
@@ -25,6 +30,9 @@ public sealed partial class TestPair
     public RobustIntegrationTest.ServerIntegrationInstance Server { get; private set; } = default!;
     public RobustIntegrationTest.ClientIntegrationInstance Client { get;  private set; } = default!;
 
+    public IPlayerSession? Player => (IPlayerSession?) Server.PlayerMan.Sessions.FirstOrDefault();
+    public PlayerData? PlayerData => Player?.Data.ContentData();
+
     public PoolTestLogHandler ServerLogHandler { get;  private set; } = default!;
     public PoolTestLogHandler ClientLogHandler { get;  private set; } = default!;
 
diff --git a/Content.IntegrationTests/Tests/Minds/MindTest.DeleteAllThenGhost.cs b/Content.IntegrationTests/Tests/Minds/MindTest.DeleteAllThenGhost.cs
new file mode 100644 (file)
index 0000000..0c9bfbf
--- /dev/null
@@ -0,0 +1,55 @@
+#nullable enable
+using Robust.Shared.Console;
+using Robust.Shared.Map;
+
+namespace Content.IntegrationTests.Tests.Minds;
+
+[TestFixture]
+public sealed partial class MindTests
+{
+    [Test]
+    public async Task DeleteAllThenGhost()
+    {
+        var settings = new PoolSettings
+        {
+            Dirty = true,
+            DummyTicker = false,
+            Connected = true
+        };
+        await using var pair = await PoolManager.GetServerClient(settings);
+
+        // Client is connected with a valid entity & mind
+        Assert.That(pair.Client.EntMan.EntityExists(pair.Client.Player?.ControlledEntity));
+        Assert.That(pair.Server.EntMan.EntityExists(pair.PlayerData?.Mind));
+
+        // Delete **everything**
+        var conHost = pair.Server.ResolveDependency<IConsoleHost>();
+        await pair.Server.WaitPost(() => conHost.ExecuteCommand("entities delete"));
+        await pair.RunTicksSync(5);
+
+        Assert.That(pair.Server.EntMan.EntityCount, Is.EqualTo(0));
+        Assert.That(pair.Client.EntMan.EntityCount, Is.EqualTo(0));
+
+        // Create a new map.
+        int mapId = 1;
+        await pair.Server.WaitPost(() => conHost.ExecuteCommand($"addmap {mapId}"));
+        await pair.RunTicksSync(5);
+
+        // Client is not attached to anything
+        Assert.Null(pair.Client.Player?.ControlledEntity);
+        Assert.Null(pair.PlayerData?.Mind);
+
+        // Attempt to ghost
+        var cConHost = pair.Client.ResolveDependency<IConsoleHost>();
+        await pair.Client.WaitPost(() => cConHost.ExecuteCommand("ghost"));
+        await pair.RunTicksSync(10);
+
+        // Client should be attached to a ghost placed on the new map.
+        Assert.That(pair.Client.EntMan.EntityExists(pair.Client.Player?.ControlledEntity));
+        Assert.That(pair.Server.EntMan.EntityExists(pair.PlayerData?.Mind));
+        var xform = pair.Client.Transform(pair.Client.Player!.ControlledEntity!.Value);
+        Assert.That(xform.MapID, Is.EqualTo(new MapId(mapId)));
+
+        await pair.CleanReturnAsync();
+    }
+}
index 0462d1bc943e9e8e01e932ae438a2c27136c2416..d04b1197afa95c6d83d5876b4b00104ae2049250 100644 (file)
@@ -27,8 +27,8 @@ namespace Content.Server.Ghost
             var minds = _entities.System<SharedMindSystem>();
             if (!minds.TryGetMind(player, out var mindId, out var mind))
             {
-                shell.WriteLine("You have no Mind, you can't ghost.");
-                return;
+                mindId = minds.CreateMind(player.UserId);
+                mind = _entities.GetComponent<MindComponent>(mindId);
             }
 
             if (!EntitySystem.Get<GameTicker>().OnGhostAttempt(mindId, true, true, mind))
index aca5a9d485da309231f23855ee564207448b3ed8..06f97bd3b9f67654c15bf15da1b6cebe5c8b6c95 100644 (file)
@@ -31,6 +31,25 @@ public sealed class MindSystem : SharedMindSystem
         base.Initialize();
 
         SubscribeLocalEvent<MindContainerComponent, EntityTerminatingEvent>(OnMindContainerTerminating);
+        SubscribeLocalEvent<MindComponent, ComponentShutdown>(OnMindShutdown);
+    }
+
+    private void OnMindShutdown(EntityUid uid, MindComponent mind, ComponentShutdown args)
+    {
+        if (mind.UserId is {} user)
+        {
+            UserMinds.Remove(user);
+            if (_players.GetPlayerData(user).ContentData() is { } oldData)
+                oldData.Mind = null;
+            mind.UserId = null;
+        }
+
+        if (!TryComp(mind.OwnedEntity, out MetaDataComponent? meta) || meta.EntityLifeStage >= EntityLifeStage.Terminating)
+            return;
+
+        RaiseLocalEvent(mind.OwnedEntity.Value, new MindRemovedMessage(uid, mind), true);
+        mind.OwnedEntity = null;
+        mind.OwnedComponent = null;
     }
 
     private void OnMindContainerTerminating(EntityUid uid, MindContainerComponent component, ref EntityTerminatingEvent args)
@@ -195,11 +214,11 @@ public sealed class MindSystem : SharedMindSystem
     public override void TransferTo(EntityUid mindId, EntityUid? entity, bool ghostCheckOverride = false, bool createGhost = true,
         MindComponent? mind = null)
     {
-        base.TransferTo(mindId, entity, ghostCheckOverride, createGhost, mind);
-
-        if (!Resolve(mindId, ref mind))
+        if (mind == null && !Resolve(mindId, ref mind))
             return;
 
+        base.TransferTo(mindId, entity, ghostCheckOverride, createGhost, mind);
+
         if (entity == mind.OwnedEntity)
             return;
 
index d6e30130e7d1f654d975779225eb9be10e0c13fb..3ea92c3ce7296c427c6c6f382b94e9dc53dda475 100644 (file)
@@ -65,8 +65,7 @@ namespace Content.Shared.Mind
         ///     The component currently owned by this mind.
         ///     Can be null.
         /// </summary>
-        [ViewVariables]
-        public MindContainerComponent? OwnedComponent { get; internal set; }
+        [ViewVariables] public MindContainerComponent? OwnedComponent;
 
         /// <summary>
         ///     The entity currently owned by this mind.
index 91f68b024543a2398861581eecdc7e7e1ee7e525..b7cd30e9621962c4b332e6d839326b479ba1a29c 100644 (file)
@@ -8,13 +8,11 @@ using Content.Shared.Interaction.Events;
 using Content.Shared.Mind.Components;
 using Content.Shared.Mobs.Components;
 using Content.Shared.Mobs.Systems;
-using Content.Shared.Objectives;
 using Content.Shared.Objectives.Systems;
 using Content.Shared.Players;
 using Robust.Shared.Map;
 using Robust.Shared.Network;
 using Robust.Shared.Players;
-using Robust.Shared.Prototypes;
 using Robust.Shared.Utility;
 
 namespace Content.Shared.Mind;
@@ -25,6 +23,7 @@ public abstract class SharedMindSystem : EntitySystem
     [Dependency] private readonly MobStateSystem _mobState = default!;
     [Dependency] private readonly SharedObjectivesSystem _objectives = default!;
     [Dependency] private readonly SharedPlayerSystem _player = default!;
+    [Dependency] private readonly MetaDataSystem _metadata = default!;
 
     // This is dictionary is required to track the minds of disconnected players that may have had their entity deleted.
     protected readonly Dictionary<NetUserId, EntityUid> UserMinds = new();
@@ -132,12 +131,11 @@ public abstract class SharedMindSystem : EntitySystem
     public EntityUid CreateMind(NetUserId? userId, string? name = null)
     {
         var mindId = Spawn(null, MapCoordinates.Nullspace);
+        _metadata.SetEntityName(mindId, name == null ? "mind" : $"mind ({name})");
         var mind = EnsureComp<MindComponent>(mindId);
         mind.CharacterName = name;
         SetUserId(mindId, userId, mind);
 
-        Dirty(mindId, MetaData(mindId));
-
         return mindId;
     }
 
@@ -343,7 +341,14 @@ public abstract class SharedMindSystem : EntitySystem
     {
         mindId = default;
         mind = null;
-        return _player.ContentData(player) is { } data && TryGetMind(data, out mindId, out mind);
+        if (_player.ContentData(player) is not { } data)
+            return false;
+
+        if (TryGetMind(data, out mindId, out mind))
+            return true;
+
+        DebugTools.AssertNull(data.Mind);
+        return false;
     }
 
     /// <summary>