using System.Linq; using Content.Server.Storage.EntitySystems; using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Containers; using Robust.Shared.GameObjects; namespace Content.IntegrationTests.Tests.Hands; [TestFixture] public sealed class HandTests { [TestPrototypes] private const string Prototypes = @" - type: entity id: TestPickUpThenDropInContainerTestBox name: box components: - type: EntityStorage - type: ContainerContainer containers: entity_storage: !type:Container "; [Test] public async Task TestPickupDrop() { await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true, DummyTicker = false }); var server = pair.Server; var entMan = server.ResolveDependency(); var playerMan = server.ResolveDependency(); var mapSystem = server.System(); var sys = entMan.System(); var tSys = entMan.System(); var data = await pair.CreateTestMap(); await pair.RunTicksSync(5); EntityUid item = default; EntityUid player = default; HandsComponent hands = default!; await server.WaitPost(() => { player = playerMan.Sessions.First().AttachedEntity!.Value; var xform = entMan.GetComponent(player); item = entMan.SpawnEntity("Crowbar", tSys.GetMapCoordinates(player, xform: xform)); hands = entMan.GetComponent(player); sys.TryPickup(player, item, hands.ActiveHand!); }); // run ticks here is important, as errors may happen within the container system's frame update methods. await pair.RunTicksSync(5); Assert.That(hands.ActiveHandEntity, Is.EqualTo(item)); await server.WaitPost(() => { sys.TryDrop(player, item, null!); }); await pair.RunTicksSync(5); Assert.That(hands.ActiveHandEntity, Is.Null); await server.WaitPost(() => mapSystem.DeleteMap(data.MapId)); await pair.CleanReturnAsync(); } [Test] public async Task TestPickUpThenDropInContainer() { await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true, DummyTicker = false }); var server = pair.Server; var map = await pair.CreateTestMap(); await pair.RunTicksSync(5); var entMan = server.ResolveDependency(); var playerMan = server.ResolveDependency(); var mapSystem = server.System(); var sys = entMan.System(); var tSys = entMan.System(); var containerSystem = server.System(); EntityUid item = default; EntityUid box = default; EntityUid player = default; HandsComponent hands = default!; // spawn the elusive box and crowbar at the coordinates await server.WaitPost(() => box = server.EntMan.SpawnEntity("TestPickUpThenDropInContainerTestBox", map.GridCoords)); await server.WaitPost(() => item = server.EntMan.SpawnEntity("Crowbar", map.GridCoords)); // place the player at the exact same coordinates and have them grab the crowbar await server.WaitPost(() => { player = playerMan.Sessions.First().AttachedEntity!.Value; tSys.PlaceNextTo(player, item); hands = entMan.GetComponent(player); sys.TryPickup(player, item, hands.ActiveHand!); }); await pair.RunTicksSync(5); Assert.That(hands.ActiveHandEntity, Is.EqualTo(item)); // Open then close the box to place the player, who is holding the crowbar, inside of it var storage = server.System(); await server.WaitPost(() => { storage.OpenStorage(box); storage.CloseStorage(box); }); await pair.RunTicksSync(5); Assert.That(containerSystem.IsEntityInContainer(player), Is.True); // Dropping the item while the player is inside the box should cause the item // to also be inside the same container the player is in now, // with the item not being in the player's hands await server.WaitPost(() => { sys.TryDrop(player, item, null!); }); await pair.RunTicksSync(5); var xform = entMan.GetComponent(player); var itemXform = entMan.GetComponent(item); Assert.That(hands.ActiveHandEntity, Is.Not.EqualTo(item)); Assert.That(containerSystem.IsInSameOrNoContainer((player, xform), (item, itemXform))); await server.WaitPost(() => mapSystem.DeleteMap(map.MapId)); await pair.CleanReturnAsync(); } }