Fix ghost respawn bug (#17511)

This commit is contained in:
Leon Friedrich
2023-06-21 13:04:07 +12:00
committed by GitHub
parent 1e9d2e388b
commit 1dde5f39ab
11 changed files with 139 additions and 104 deletions

View File

@@ -18,6 +18,38 @@ namespace Content.IntegrationTests.Tests.Minds;
[TestFixture]
public sealed partial class MindTests
{
/// <summary>
/// Gets a server-client pair and ensures that the client is attached to a simple mind test entity.
/// </summary>
public async Task<PairTracker> SetupPair()
{
var pairTracker = await PoolManager.GetServerClient(new PoolSettings{ ExtraPrototypes = Prototypes });
var pair = pairTracker.Pair;
var entMan = pair.Server.ResolveDependency<IServerEntityManager>();
var playerMan = pair.Server.ResolveDependency<IPlayerManager>();
var mindSys = entMan.System<MindSystem>();
var player = playerMan.ServerSessions.Single();
EntityUid entity = default;
await pair.Server.WaitPost(() =>
{
entity = entMan.SpawnEntity("MindTestEntity", MapCoordinates.Nullspace);
mindSys.TransferTo(mindSys.CreateMind(player.UserId), entity);
});
await PoolManager.RunTicksSync(pair, 5);
var mind = player.ContentData()?.Mind;
Assert.NotNull(mind);
Assert.That(player.AttachedEntity, Is.EqualTo(entity));
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.");
return pairTracker;
}
public async Task<EntityUid> BecomeGhost(Pair pair, bool visit = false)
{
var entMan = pair.Server.ResolveDependency<IServerEntityManager>();
@@ -74,9 +106,9 @@ public sealed partial class MindTests
var mind = player.ContentData()!.Mind;
Assert.NotNull(mind);
Assert.That(player.AttachedEntity, Is.EqualTo(mind.CurrentEntity));
Assert.That(entMan.EntityExists(mind.OwnedEntity));
Assert.That(entMan.EntityExists(mind.CurrentEntity));
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.");
return mind;
}

View File

@@ -20,21 +20,19 @@ public sealed partial class MindTests
[Test]
public async Task TestGhostsCanReconnect()
{
await using var pairTracker = await PoolManager.GetServerClient();
await using var pairTracker = await SetupPair();
var pair = pairTracker.Pair;
var entMan = pair.Server.ResolveDependency<IEntityManager>();
await PoolManager.RunTicksSync(pair, 5);
var mind = GetMind(pair);
var ghost = await BecomeGhost(pair);
await DisconnectReconnect(pair);
// Player in control of a NEW entity
var newMind = GetMind(pair);
Assert.That(newMind != mind);
// Player in control of a new ghost, but with the same mind
Assert.That(GetMind(pair) == mind);
Assert.That(entMan.Deleted(ghost));
Assert.Null(newMind.VisitingEntity);
Assert.That(entMan.HasComponent<GhostComponent>(mind.OwnedEntity));
Assert.Null(mind.VisitingEntity);
await pairTracker.CleanReturnAsync();
}
@@ -47,11 +45,9 @@ public sealed partial class MindTests
[Test]
public async Task TestDeletedCanReconnect()
{
await using var pairTracker = await PoolManager.GetServerClient();
await using var pairTracker = await SetupPair();
var pair = pairTracker.Pair;
var entMan = pair.Server.ResolveDependency<IEntityManager>();
await PoolManager.RunTicksSync(pair, 5);
var mind = GetMind(pair);
var playerMan = pair.Server.ResolveDependency<IPlayerManager>();
@@ -76,15 +72,12 @@ public sealed partial class MindTests
// Reconnect
await Connect(pair, name);
player = playerMan.ServerSessions.Single();
Assert.That(user == player.UserId);
Assert.That(user, Is.EqualTo(player.UserId));
// Player is now a new entity
var newMind = GetMind(pair);
Assert.That(newMind != mind);
Assert.Null(mind.UserId);
Assert.Null(mind.CurrentEntity);
Assert.NotNull(newMind.OwnedEntity);
Assert.That(entMan.EntityExists(newMind.OwnedEntity));
// Player is now a new ghost entity
Assert.That(GetMind(pair), Is.EqualTo(mind));
Assert.That(mind.OwnedEntity, Is.Not.EqualTo(entity));
Assert.That(entMan.HasComponent<GhostComponent>(mind.OwnedEntity));
await pairTracker.CleanReturnAsync();
}
@@ -97,11 +90,10 @@ public sealed partial class MindTests
[Test]
public async Task TestVisitingGhostReconnect()
{
await using var pairTracker = await PoolManager.GetServerClient();
await using var pairTracker = await SetupPair();
var pair = pairTracker.Pair;
var entMan = pair.Server.ResolveDependency<IEntityManager>();
await PoolManager.RunTicksSync(pair, 5);
var mind = GetMind(pair);
var original = mind.CurrentEntity;
@@ -109,8 +101,8 @@ public sealed partial class MindTests
await DisconnectReconnect(pair);
// Player now controls their original mob, mind was preserved
Assert.That(mind == GetMind(pair));
Assert.That(mind.CurrentEntity == original);
Assert.That(mind, Is.EqualTo(GetMind(pair)));
Assert.That(mind.CurrentEntity, Is.EqualTo(original));
Assert.That(!entMan.Deleted(original));
Assert.That(entMan.Deleted(ghost));
@@ -125,7 +117,7 @@ public sealed partial class MindTests
[Test]
public async Task TestVisitingReconnect()
{
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{ ExtraPrototypes = Prototypes });
await using var pairTracker = await SetupPair();
var pair = pairTracker.Pair;
var entMan = pair.Server.ResolveDependency<IEntityManager>();

View File

@@ -61,26 +61,6 @@ public sealed partial class MindTests
- !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()
{
@@ -382,11 +362,11 @@ public sealed partial class MindTests
await pairTracker.CleanReturnAsync();
}
[Test]
// TODO Implement
/*[Test]
public async Task TestPlayerCanReturnFromGhostWhenDead()
{
// TODO Implement
}
}*/
[Test]
public async Task TestGhostDoesNotInfiniteLoop()