diff --git a/Content.IntegrationTests/Tests/Buckle/BuckleTest.Interact.cs b/Content.IntegrationTests/Tests/Buckle/BuckleTest.Interact.cs new file mode 100644 index 0000000000..d9cce764ab --- /dev/null +++ b/Content.IntegrationTests/Tests/Buckle/BuckleTest.Interact.cs @@ -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(); + var buckleSystem = entMan.System(); + + 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(); + + 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(); + } +} diff --git a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs index 156f42aac3..1b31fe38c2 100644 --- a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs +++ b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs @@ -15,7 +15,7 @@ namespace Content.IntegrationTests.Tests.Buckle [TestFixture] [TestOf(typeof(BuckleComponent))] [TestOf(typeof(StrapComponent))] - public sealed class BuckleTest + public sealed partial class BuckleTest { private const string BuckleDummyId = "BuckleDummy"; private const string StrapDummyId = "StrapDummy"; diff --git a/Content.Shared/Buckle/SharedBuckleSystem.Interaction.cs b/Content.Shared/Buckle/SharedBuckleSystem.Interaction.cs index 7677e800fe..1a15e52a3c 100644 --- a/Content.Shared/Buckle/SharedBuckleSystem.Interaction.cs +++ b/Content.Shared/Buckle/SharedBuckleSystem.Interaction.cs @@ -1,5 +1,5 @@ +using System.Linq; using Content.Shared.Buckle.Components; -using Content.Shared.Cuffs.Components; using Content.Shared.DoAfter; using Content.Shared.DragDrop; using Content.Shared.IdentityManagement; @@ -84,15 +84,29 @@ public abstract partial class SharedBuckleSystem if (!TryComp(args.User, out BuckleComponent? buckle)) 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); - else if (buckle.BuckledTo == uid) - TryUnbuckle(args.User, args.User, buckle, popup: true); - else + args.Handled = true; 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. - args.Handled = true; } private void OnBuckleInteractHand(Entity ent, ref InteractHandEvent args)