#nullable enable annotations using System.Threading.Tasks; using Content.Server.Hands.Components; using Content.Server.Interaction; using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; using Content.Shared.Weapons.Melee; using NUnit.Framework; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Reflection; using ItemComponent = Content.Server.Clothing.Components.ItemComponent; namespace Content.IntegrationTests.Tests.Interaction.Click { [TestFixture] [TestOf(typeof(InteractionSystem))] public sealed class InteractionSystemTests { private const string Prototypes = @" - type: entity id: DummyDebugWall components: - type: Physics bodyType: Dynamic - type: Fixtures fixtures: - shape: !type:PhysShapeAabb bounds: ""-0.25,-0.25,0.25,0.25"" layer: - MobMask mask: - MobMask "; [Test] public async Task InteractionTest() { await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); var mapManager = server.ResolveDependency(); var sysMan = server.ResolveDependency(); var handSys = sysMan.GetEntitySystem(); var mapId = MapId.Nullspace; var coords = MapCoordinates.Nullspace; await server.WaitAssertion(() => { mapId = mapManager.CreateMap(); coords = new MapCoordinates(Vector2.Zero, mapId); }); await server.WaitIdleAsync(); EntityUid user = default; EntityUid target = default; EntityUid item = default; await server.WaitAssertion(() => { user = sEntities.SpawnEntity(null, coords); user.EnsureComponent(); handSys.AddHand(user, "hand", HandLocation.Left); target = sEntities.SpawnEntity(null, coords); item = sEntities.SpawnEntity(null, coords); item.EnsureComponent(); }); await server.WaitRunTicks(1); var entitySystemManager = server.ResolveDependency(); Assert.That(entitySystemManager.TryGetEntitySystem(out var interactionSystem)); Assert.That(entitySystemManager.TryGetEntitySystem(out var testInteractionSystem)); var attack = false; var interactUsing = false; var interactHand = false; await server.WaitAssertion(() => { testInteractionSystem.AttackEvent = (_, _, ev) => { Assert.That(ev.Target, Is.EqualTo(target)); attack = true; }; testInteractionSystem.InteractUsingEvent = (ev) => { Assert.That(ev.Target, Is.EqualTo(target)); interactUsing = true; }; testInteractionSystem.InteractHandEvent = (ev) => { Assert.That(ev.Target, Is.EqualTo(target)); interactHand = true; }; interactionSystem.DoAttack(user, sEntities.GetComponent(target).Coordinates, false, target); interactionSystem.UserInteraction(user, sEntities.GetComponent(target).Coordinates, target); Assert.That(attack); Assert.That(interactUsing, Is.False); Assert.That(interactHand); Assert.That(handSys.TryPickup(user, item)); interactionSystem.UserInteraction(user, sEntities.GetComponent(target).Coordinates, target); Assert.That(interactUsing); }); await pairTracker.CleanReturnAsync(); } [Test] public async Task InteractionObstructionTest() { await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); var mapManager = server.ResolveDependency(); var sysMan = server.ResolveDependency(); var handSys = sysMan.GetEntitySystem(); var mapId = MapId.Nullspace; var coords = MapCoordinates.Nullspace; await server.WaitAssertion(() => { mapId = mapManager.CreateMap(); coords = new MapCoordinates(Vector2.Zero, mapId); }); await server.WaitIdleAsync(); EntityUid user = default; EntityUid target = default; EntityUid item = default; EntityUid wall = default; await server.WaitAssertion(() => { user = sEntities.SpawnEntity(null, coords); user.EnsureComponent(); handSys.AddHand(user, "hand", HandLocation.Left); target = sEntities.SpawnEntity(null, new MapCoordinates((1.9f, 0), mapId)); item = sEntities.SpawnEntity(null, coords); item.EnsureComponent(); wall = sEntities.SpawnEntity("DummyDebugWall", new MapCoordinates((1, 0), sEntities.GetComponent(user).MapID)); }); await server.WaitRunTicks(1); var entitySystemManager = server.ResolveDependency(); Assert.That(entitySystemManager.TryGetEntitySystem(out var interactionSystem)); Assert.That(entitySystemManager.TryGetEntitySystem(out var testInteractionSystem)); var attack = false; var interactUsing = false; var interactHand = false; await server.WaitAssertion(() => { testInteractionSystem.AttackEvent = (_, _, ev) => { Assert.That(ev.Target, Is.EqualTo(target)); attack = true; }; testInteractionSystem.InteractUsingEvent = (ev) => { Assert.That(ev.Target, Is.EqualTo(target)); interactUsing = true; }; testInteractionSystem.InteractHandEvent = (ev) => { Assert.That(ev.Target, Is.EqualTo(target)); interactHand = true; }; interactionSystem.DoAttack(user, sEntities.GetComponent(target).Coordinates, false, target); interactionSystem.UserInteraction(user, sEntities.GetComponent(target).Coordinates, target); Assert.That(attack, Is.False); Assert.That(interactUsing, Is.False); Assert.That(interactHand, Is.False); Assert.That(handSys.TryPickup(user, item)); interactionSystem.UserInteraction(user, sEntities.GetComponent(target).Coordinates, target); Assert.That(interactUsing, Is.False); }); await pairTracker.CleanReturnAsync(); } [Test] public async Task InteractionInRangeTest() { await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); var mapManager = server.ResolveDependency(); var sysMan = server.ResolveDependency(); var handSys = sysMan.GetEntitySystem(); var mapId = MapId.Nullspace; var coords = MapCoordinates.Nullspace; await server.WaitAssertion(() => { mapId = mapManager.CreateMap(); coords = new MapCoordinates(Vector2.Zero, mapId); }); await server.WaitIdleAsync(); EntityUid user = default; EntityUid target = default; EntityUid item = default; await server.WaitAssertion(() => { user = sEntities.SpawnEntity(null, coords); user.EnsureComponent(); handSys.AddHand(user, "hand", HandLocation.Left); target = sEntities.SpawnEntity(null, new MapCoordinates((InteractionSystem.InteractionRange - 0.1f, 0), mapId)); item = sEntities.SpawnEntity(null, coords); item.EnsureComponent(); }); await server.WaitRunTicks(1); var entitySystemManager = server.ResolveDependency(); Assert.That(entitySystemManager.TryGetEntitySystem(out var interactionSystem)); Assert.That(entitySystemManager.TryGetEntitySystem(out var testInteractionSystem)); var attack = false; var interactUsing = false; var interactHand = false; await server.WaitAssertion(() => { testInteractionSystem.AttackEvent = (_, _, ev) => { Assert.That(ev.Target, Is.EqualTo(target)); attack = true; }; testInteractionSystem.InteractUsingEvent = (ev) => { Assert.That(ev.Target, Is.EqualTo(target)); interactUsing = true; }; testInteractionSystem.InteractHandEvent = (ev) => { Assert.That(ev.Target, Is.EqualTo(target)); interactHand = true; }; interactionSystem.DoAttack(user, sEntities.GetComponent(target).Coordinates, false, target); interactionSystem.UserInteraction(user, sEntities.GetComponent(target).Coordinates, target); Assert.That(attack); Assert.That(interactUsing, Is.False); Assert.That(interactHand); Assert.That(handSys.TryPickup(user, item)); interactionSystem.UserInteraction(user, sEntities.GetComponent(target).Coordinates, target); Assert.That(interactUsing); }); await pairTracker.CleanReturnAsync(); } [Test] public async Task InteractionOutOfRangeTest() { await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); var mapManager = server.ResolveDependency(); var sysMan = server.ResolveDependency(); var handSys = sysMan.GetEntitySystem(); var mapId = MapId.Nullspace; var coords = MapCoordinates.Nullspace; await server.WaitAssertion(() => { mapId = mapManager.CreateMap(); coords = new MapCoordinates(Vector2.Zero, mapId); }); await server.WaitIdleAsync(); EntityUid user = default; EntityUid target = default; EntityUid item = default; await server.WaitAssertion(() => { user = sEntities.SpawnEntity(null, coords); user.EnsureComponent(); handSys.AddHand(user, "hand", HandLocation.Left); target = sEntities.SpawnEntity(null, new MapCoordinates((SharedInteractionSystem.InteractionRange + 0.01f, 0), mapId)); item = sEntities.SpawnEntity(null, coords); item.EnsureComponent(); }); await server.WaitRunTicks(1); var entitySystemManager = server.ResolveDependency(); Assert.That(entitySystemManager.TryGetEntitySystem(out var interactionSystem)); Assert.That(entitySystemManager.TryGetEntitySystem(out var testInteractionSystem)); var attack = false; var interactUsing = false; var interactHand = false; await server.WaitAssertion(() => { testInteractionSystem.AttackEvent = (_, _, ev) => { Assert.That(ev.Target, Is.EqualTo(target)); attack = true; }; testInteractionSystem.InteractUsingEvent = (ev) => { Assert.That(ev.Target, Is.EqualTo(target)); interactUsing = true; }; testInteractionSystem.InteractHandEvent = (ev) => { Assert.That(ev.Target, Is.EqualTo(target)); interactHand = true; }; interactionSystem.DoAttack(user, sEntities.GetComponent(target).Coordinates, false, target); interactionSystem.UserInteraction(user, sEntities.GetComponent(target).Coordinates, target); Assert.That(attack, Is.False); Assert.That(interactUsing, Is.False); Assert.That(interactHand, Is.False); Assert.That(handSys.TryPickup(user, item)); interactionSystem.UserInteraction(user, sEntities.GetComponent(target).Coordinates, target); Assert.That(interactUsing, Is.False); }); await pairTracker.CleanReturnAsync(); } [Test] public async Task InsideContainerInteractionBlockTest() { await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); var mapManager = server.ResolveDependency(); var sysMan = server.ResolveDependency(); var handSys = sysMan.GetEntitySystem(); var mapId = MapId.Nullspace; var coords = MapCoordinates.Nullspace; await server.WaitAssertion(() => { mapId = mapManager.CreateMap(); coords = new MapCoordinates(Vector2.Zero, mapId); }); await server.WaitIdleAsync(); EntityUid user = default; EntityUid target = default; EntityUid item = default; EntityUid containerEntity = default; IContainer container = null; await server.WaitAssertion(() => { user = sEntities.SpawnEntity(null, coords); user.EnsureComponent(); handSys.AddHand(user, "hand", HandLocation.Left); target = sEntities.SpawnEntity(null, coords); item = sEntities.SpawnEntity(null, coords); item.EnsureComponent(); containerEntity = sEntities.SpawnEntity(null, coords); container = containerEntity.EnsureContainer("InteractionTestContainer"); }); await server.WaitRunTicks(1); var entitySystemManager = server.ResolveDependency(); Assert.That(entitySystemManager.TryGetEntitySystem(out var interactionSystem)); Assert.That(entitySystemManager.TryGetEntitySystem(out var testInteractionSystem)); await server.WaitIdleAsync(); var attack = false; var interactUsing = false; var interactHand = false; await server.WaitAssertion(() => { Assert.That(container.Insert(user)); Assert.That(sEntities.GetComponent(user).Parent.Owner, Is.EqualTo(containerEntity)); testInteractionSystem.AttackEvent = (_, _, ev) => { Assert.That(ev.Target, Is.EqualTo(containerEntity)); attack = true; }; testInteractionSystem.InteractUsingEvent = (ev) => { Assert.That(ev.Target, Is.EqualTo(containerEntity)); interactUsing = true; }; testInteractionSystem.InteractHandEvent = (ev) => { Assert.That(ev.Target, Is.EqualTo(containerEntity)); interactHand = true; }; interactionSystem.DoAttack(user, sEntities.GetComponent(target).Coordinates, false, target); interactionSystem.UserInteraction(user, sEntities.GetComponent(target).Coordinates, target); Assert.That(attack, Is.False); Assert.That(interactUsing, Is.False); Assert.That(interactHand, Is.False); interactionSystem.DoAttack(user, sEntities.GetComponent(containerEntity).Coordinates, false, containerEntity); interactionSystem.UserInteraction(user, sEntities.GetComponent(containerEntity).Coordinates, containerEntity); Assert.That(attack); Assert.That(interactUsing, Is.False); Assert.That(interactHand); Assert.That(handSys.TryPickup(user, item)); interactionSystem.UserInteraction(user, sEntities.GetComponent(target).Coordinates, target); Assert.That(interactUsing, Is.False); interactionSystem.UserInteraction(user, sEntities.GetComponent(containerEntity).Coordinates, containerEntity); Assert.That(interactUsing, Is.True); }); await pairTracker.CleanReturnAsync(); } [Reflect(false)] public sealed class TestInteractionSystem : EntitySystem { public ComponentEventHandler? AttackEvent; public EntityEventHandler? InteractUsingEvent; public EntityEventHandler? InteractHandEvent; public override void Initialize() { base.Initialize(); SubscribeLocalEvent((u, c, e) => AttackEvent?.Invoke(u, c, e)); SubscribeLocalEvent((e) => InteractUsingEvent?.Invoke(e)); SubscribeLocalEvent((e) => InteractHandEvent?.Invoke(e)); } } } }