Fix unbuckling others when clicking on the strap entity (#29998)

* Add failing unbuckle InteractHand test

* Skip trybuckle if strap doesn't have space

* Unbuckle others not just user

* Fix test failing due to delay

* Change to raise event instead of calling OnInteractHand

* Add test for buckle and unbuckle on InteractHand

* Add tick delay

* Remove unneeded tick delay and clean up

* Comment code

* Cleanup

* Swap to fastest checks first

* Fix reading empty sequence when there are no buckled entities
This commit is contained in:
ShadowCommander
2024-09-18 16:55:26 -07:00
committed by GitHub
parent a8686b3597
commit d4a5bc8d6b
3 changed files with 129 additions and 7 deletions

View File

@@ -0,0 +1,108 @@
using Content.Shared.Buckle;
using Content.Shared.Buckle.Components;
using Content.Shared.Interaction;
using Robust.Server.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
namespace Content.IntegrationTests.Tests.Buckle;
public sealed partial class BuckleTest
{
[Test]
public async Task BuckleInteractUnbuckleOther()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var entMan = server.ResolveDependency<IServerEntityManager>();
var buckleSystem = entMan.System<SharedBuckleSystem>();
EntityUid user = default;
EntityUid victim = default;
EntityUid chair = default;
BuckleComponent buckle = null;
StrapComponent strap = null;
await server.WaitAssertion(() =>
{
user = entMan.SpawnEntity(BuckleDummyId, MapCoordinates.Nullspace);
victim = entMan.SpawnEntity(BuckleDummyId, MapCoordinates.Nullspace);
chair = entMan.SpawnEntity(StrapDummyId, MapCoordinates.Nullspace);
Assert.That(entMan.TryGetComponent(victim, out buckle));
Assert.That(entMan.TryGetComponent(chair, out strap));
#pragma warning disable RA0002
buckle.Delay = TimeSpan.Zero;
#pragma warning restore RA0002
// Buckle victim to chair
Assert.That(buckleSystem.TryBuckle(victim, user, chair, buckle));
Assert.Multiple(() =>
{
Assert.That(buckle.BuckledTo, Is.EqualTo(chair), "Victim did not get buckled to the chair.");
Assert.That(buckle.Buckled, "Victim is not buckled.");
Assert.That(strap.BuckledEntities, Does.Contain(victim), "Chair does not have victim buckled to it.");
});
// InteractHand with chair to unbuckle victim
entMan.EventBus.RaiseLocalEvent(chair, new InteractHandEvent(user, chair));
Assert.Multiple(() =>
{
Assert.That(buckle.BuckledTo, Is.Null);
Assert.That(buckle.Buckled, Is.False);
Assert.That(strap.BuckledEntities, Does.Not.Contain(victim));
});
});
await pair.CleanReturnAsync();
}
[Test]
public async Task BuckleInteractBuckleUnbuckleSelf()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var entMan = server.ResolveDependency<IServerEntityManager>();
EntityUid user = default;
EntityUid chair = default;
BuckleComponent buckle = null;
StrapComponent strap = null;
await server.WaitAssertion(() =>
{
user = entMan.SpawnEntity(BuckleDummyId, MapCoordinates.Nullspace);
chair = entMan.SpawnEntity(StrapDummyId, MapCoordinates.Nullspace);
Assert.That(entMan.TryGetComponent(user, out buckle));
Assert.That(entMan.TryGetComponent(chair, out strap));
#pragma warning disable RA0002
buckle.Delay = TimeSpan.Zero;
#pragma warning restore RA0002
// Buckle user to chair
entMan.EventBus.RaiseLocalEvent(chair, new InteractHandEvent(user, chair));
Assert.Multiple(() =>
{
Assert.That(buckle.BuckledTo, Is.EqualTo(chair), "Victim did not get buckled to the chair.");
Assert.That(buckle.Buckled, "Victim is not buckled.");
Assert.That(strap.BuckledEntities, Does.Contain(user), "Chair does not have victim buckled to it.");
});
// InteractHand with chair to unbuckle
entMan.EventBus.RaiseLocalEvent(chair, new InteractHandEvent(user, chair));
Assert.Multiple(() =>
{
Assert.That(buckle.BuckledTo, Is.Null);
Assert.That(buckle.Buckled, Is.False);
Assert.That(strap.BuckledEntities, Does.Not.Contain(user));
});
});
await pair.CleanReturnAsync();
}
}

View File

@@ -15,7 +15,7 @@ namespace Content.IntegrationTests.Tests.Buckle
[TestFixture] [TestFixture]
[TestOf(typeof(BuckleComponent))] [TestOf(typeof(BuckleComponent))]
[TestOf(typeof(StrapComponent))] [TestOf(typeof(StrapComponent))]
public sealed class BuckleTest public sealed partial class BuckleTest
{ {
private const string BuckleDummyId = "BuckleDummy"; private const string BuckleDummyId = "BuckleDummy";
private const string StrapDummyId = "StrapDummy"; private const string StrapDummyId = "StrapDummy";

View File

@@ -1,5 +1,5 @@
using System.Linq;
using Content.Shared.Buckle.Components; using Content.Shared.Buckle.Components;
using Content.Shared.Cuffs.Components;
using Content.Shared.DoAfter; using Content.Shared.DoAfter;
using Content.Shared.DragDrop; using Content.Shared.DragDrop;
using Content.Shared.IdentityManagement; using Content.Shared.IdentityManagement;
@@ -84,15 +84,29 @@ public abstract partial class SharedBuckleSystem
if (!TryComp(args.User, out BuckleComponent? buckle)) if (!TryComp(args.User, out BuckleComponent? buckle))
return; return;
if (buckle.BuckledTo == null && component.BuckleOnInteractHand) // Buckle self
if (buckle.BuckledTo == null && component.BuckleOnInteractHand && StrapHasSpace(uid, buckle, component))
{
TryBuckle(args.User, args.User, uid, buckle, popup: true); TryBuckle(args.User, args.User, uid, buckle, popup: true);
else if (buckle.BuckledTo == uid) args.Handled = true;
TryUnbuckle(args.User, args.User, buckle, popup: true);
else
return; return;
}
// Unbuckle self
if (buckle.BuckledTo == uid && TryUnbuckle(args.User, args.User, buckle, popup: true))
{
args.Handled = true;
return;
}
// Unbuckle others
if (component.BuckledEntities.TryFirstOrNull(out var buckled) && TryUnbuckle(buckled.Value, args.User))
{
args.Handled = true;
return;
}
// TODO BUCKLE add out bool for whether a pop-up was generated or not. // TODO BUCKLE add out bool for whether a pop-up was generated or not.
args.Handled = true;
} }
private void OnBuckleInteractHand(Entity<BuckleComponent> ent, ref InteractHandEvent args) private void OnBuckleInteractHand(Entity<BuckleComponent> ent, ref InteractHandEvent args)