Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misc mind tweaks and fixes #20614

Merged
merged 3 commits into from
Oct 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Content.IntegrationTests/Pair/TestPair.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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!;

Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}
4 changes: 2 additions & 2 deletions Content.Server/Ghost/Ghost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public void Execute(IConsoleShell shell, string argStr, string[] args)
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))
Expand Down
25 changes: 22 additions & 3 deletions Content.Server/Mind/MindSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,25 @@ public override void Initialize()
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)
Expand Down Expand Up @@ -195,11 +214,11 @@ public override void UnVisit(EntityUid mindId, MindComponent? mind = null)
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;

Expand Down
3 changes: 1 addition & 2 deletions Content.Shared/Mind/MindComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ public sealed partial class MindComponent : Component
/// 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.
Expand Down
15 changes: 10 additions & 5 deletions Content.Shared/Mind/SharedMindSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@
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;
Expand All @@ -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();
Expand Down Expand Up @@ -132,12 +131,11 @@ private void OnSuicide(EntityUid uid, MindContainerComponent component, SuicideE
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;
}

Expand Down Expand Up @@ -343,7 +341,14 @@ public bool TryGetMind(
{
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>
Expand Down