Fix error when disconnecting the client while a projectile is embedded (#36048)
* Add test for disconnecting the client while a projectile is embedded * Add check for non-terminating grid or map * Add test that an embeddable detaches when the target is deleted. * Remove Explicit tag from TestDisconnectWhileEmbedded
This commit is contained in:
91
Content.IntegrationTests/Tests/Embedding/EmbedTest.cs
Normal file
91
Content.IntegrationTests/Tests/Embedding/EmbedTest.cs
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
using Content.IntegrationTests.Tests.Interaction;
|
||||||
|
using Content.Shared.Projectiles;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
|
||||||
|
namespace Content.IntegrationTests.Tests.Embedding;
|
||||||
|
|
||||||
|
public sealed class EmbedTest : InteractionTest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Embeddable entity that will be thrown at the target.
|
||||||
|
/// </summary>
|
||||||
|
private const string EmbeddableProtoId = "SurvivalKnife";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Target entity that the thrown item will embed into.
|
||||||
|
/// </summary>
|
||||||
|
private const string TargetProtoId = "AirlockGlass";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Embeds an entity with a <see cref="EmbeddableProjectileComponent"/> into a target,
|
||||||
|
/// then disconnects the client. Intended to reveal any clientside issues that might
|
||||||
|
/// occur due to reparenting during cleanup.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public async Task TestDisconnectWhileEmbedded()
|
||||||
|
{
|
||||||
|
// Spawn the target we're going to throw at
|
||||||
|
await SpawnTarget(TargetProtoId);
|
||||||
|
|
||||||
|
// Give the player the embeddable to throw
|
||||||
|
var projectile = await PlaceInHands(EmbeddableProtoId);
|
||||||
|
Assert.That(TryComp<EmbeddableProjectileComponent>(projectile, out var embedComp),
|
||||||
|
$"{EmbeddableProtoId} does not have EmbeddableProjectileComponent");
|
||||||
|
// Make sure the projectile isn't already embedded into anything
|
||||||
|
Assert.That(embedComp.EmbeddedIntoUid, Is.Null,
|
||||||
|
$"Projectile already embedded into {SEntMan.ToPrettyString(embedComp.EmbeddedIntoUid)}");
|
||||||
|
|
||||||
|
// Have the player throw the embeddable at the target
|
||||||
|
await ThrowItem();
|
||||||
|
|
||||||
|
// Wait a moment for the item to hit and embed
|
||||||
|
await RunSeconds(0.5f);
|
||||||
|
|
||||||
|
// Make sure the projectile is embedded into the target
|
||||||
|
Assert.That(embedComp.EmbeddedIntoUid, Is.EqualTo(ToServer(Target)),
|
||||||
|
"Projectile not embedded into target");
|
||||||
|
|
||||||
|
// Disconnect the client
|
||||||
|
var cNetMgr = Client.ResolveDependency<IClientNetManager>();
|
||||||
|
await Client.WaitPost(Client.EntMan.FlushEntities);
|
||||||
|
await Pair.RunTicksSync(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Embeds an entity with a <see cref="EmbeddableProjectileComponent"/> into a target,
|
||||||
|
/// then deletes the target and makes sure the embeddable is not deleted.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public async Task TestEmbedDetach()
|
||||||
|
{
|
||||||
|
// Spawn the target we're going to throw at
|
||||||
|
await SpawnTarget(TargetProtoId);
|
||||||
|
|
||||||
|
// Give the player the embeddable to throw
|
||||||
|
var projectile = await PlaceInHands(EmbeddableProtoId);
|
||||||
|
Assert.That(TryComp<EmbeddableProjectileComponent>(projectile, out var embedComp),
|
||||||
|
$"{EmbeddableProtoId} does not have EmbeddableProjectileComponent");
|
||||||
|
// Make sure the projectile isn't already embedded into anything
|
||||||
|
Assert.That(embedComp.EmbeddedIntoUid, Is.Null,
|
||||||
|
$"Projectile already embedded into {SEntMan.ToPrettyString(embedComp.EmbeddedIntoUid)}");
|
||||||
|
|
||||||
|
// Have the player throw the embeddable at the target
|
||||||
|
await ThrowItem();
|
||||||
|
|
||||||
|
// Wait a moment for the item to hit and embed
|
||||||
|
await RunSeconds(0.5f);
|
||||||
|
|
||||||
|
// Make sure the projectile is embedded into the target
|
||||||
|
Assert.That(embedComp.EmbeddedIntoUid, Is.EqualTo(ToServer(Target)),
|
||||||
|
"Projectile not embedded into target");
|
||||||
|
|
||||||
|
// Delete the target
|
||||||
|
await Delete(Target.Value);
|
||||||
|
|
||||||
|
await RunTicks(1);
|
||||||
|
|
||||||
|
// Make sure the embeddable wasn't deleted with the target
|
||||||
|
AssertExists(projectile);
|
||||||
|
await AssertEntityLookup(EmbeddableProtoId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -143,6 +143,8 @@ public abstract partial class SharedProjectileSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
var xform = Transform(uid);
|
var xform = Transform(uid);
|
||||||
|
if (TerminatingOrDeleted(xform.GridUid) && TerminatingOrDeleted(xform.MapUid))
|
||||||
|
return;
|
||||||
TryComp<PhysicsComponent>(uid, out var physics);
|
TryComp<PhysicsComponent>(uid, out var physics);
|
||||||
_physics.SetBodyType(uid, BodyType.Dynamic, body: physics, xform: xform);
|
_physics.SetBodyType(uid, BodyType.Dynamic, body: physics, xform: xform);
|
||||||
_transform.AttachToGridOrMap(uid, xform);
|
_transform.AttachToGridOrMap(uid, xform);
|
||||||
|
|||||||
Reference in New Issue
Block a user