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;
using Robust.Shared.Map;
[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 server.WaitPost(() => mapMan.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<IEntityManager>();
+ var playerMan = server.ResolveDependency<IPlayerManager>();
+ var mapMan = server.ResolveDependency<IMapManager>();
+ var sys = entMan.System<SharedHandsSystem>();
+ var tSys = entMan.System<TransformSystem>();
+ var containerSystem = server.System<SharedContainerSystem>();
+
+ 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<HandsComponent>(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<EntityStorageSystem>();
+ 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<TransformComponent>(player);
+ var itemXform = entMan.GetComponent<TransformComponent>(item);
+ Assert.That(hands.ActiveHandEntity, Is.Not.EqualTo(item));
+ Assert.That(containerSystem.IsInSameOrNoContainer((player, xform), (item, itemXform)));
+
+ await server.WaitPost(() => mapMan.DeleteMap(map.MapId));
+ await pair.CleanReturnAsync();
+ }
}
return false;
var entity = hand.HeldEntity!.Value;
- DoDrop(uid, hand, doDropInteraction: doDropInteraction, handsComp);
+
+ // if item is a fake item (like with pulling), just delete it rather than bothering with trying to drop it into the world
+ if (TryComp(entity, out VirtualItemComponent? @virtual))
+ _virtualSystem.DeleteVirtualItem((entity, @virtual), uid);
if (TerminatingOrDeleted(entity))
return true;
var userXform = Transform(uid);
var isInContainer = ContainerSystem.IsEntityOrParentInContainer(uid, xform: userXform);
+ // drop the item inside the container if the user is in a container
if (targetDropLocation == null || isInContainer)
{
- // If user is in a container, drop item into that container. Otherwise, attach to grid or map.
TransformSystem.DropNextTo((entity, itemXform), (uid, userXform));
return true;
}
+ // otherwise, remove the item from their hands and place it at the calculated interaction range position
+ DoDrop(uid, hand, doDropInteraction: doDropInteraction, handsComp);
var (itemPos, itemRot) = TransformSystem.GetWorldPositionRotation(entity);
var origin = new MapCoordinates(itemPos, itemXform.MapID);
- var target = targetDropLocation.Value.ToMap(EntityManager, TransformSystem);
+ var target = TransformSystem.ToMapCoordinates(targetDropLocation.Value);
TransformSystem.SetWorldPositionRotation(entity, GetFinalDropCoordinates(uid, origin, target), itemRot);
return true;
}