Fixes dropping item in container (#29900)
* Items droped in containers will end up in containers * Adds integration test for dropping entity while inside container * comment * comment * trim the diff --------- Co-authored-by: plykiya <plykiya@protonmail.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Server.Storage.EntitySystems;
|
||||||
using Content.Shared.Hands.Components;
|
using Content.Shared.Hands.Components;
|
||||||
using Content.Shared.Hands.EntitySystems;
|
using Content.Shared.Hands.EntitySystems;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
|
|
||||||
@@ -11,6 +13,19 @@ namespace Content.IntegrationTests.Tests.Hands;
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public sealed class HandTests
|
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]
|
[Test]
|
||||||
public async Task TestPickupDrop()
|
public async Task TestPickupDrop()
|
||||||
{
|
{
|
||||||
@@ -57,4 +72,69 @@ public sealed class HandTests
|
|||||||
await server.WaitPost(() => mapMan.DeleteMap(data.MapId));
|
await server.WaitPost(() => mapMan.DeleteMap(data.MapId));
|
||||||
await pair.CleanReturnAsync();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,7 +110,10 @@ public abstract partial class SharedHandsSystem
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
var entity = hand.HeldEntity!.Value;
|
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))
|
if (TerminatingOrDeleted(entity))
|
||||||
return true;
|
return true;
|
||||||
@@ -122,16 +125,18 @@ public abstract partial class SharedHandsSystem
|
|||||||
var userXform = Transform(uid);
|
var userXform = Transform(uid);
|
||||||
var isInContainer = ContainerSystem.IsEntityOrParentInContainer(uid, xform: userXform);
|
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 (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));
|
TransformSystem.DropNextTo((entity, itemXform), (uid, userXform));
|
||||||
return true;
|
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 (itemPos, itemRot) = TransformSystem.GetWorldPositionRotation(entity);
|
||||||
var origin = new MapCoordinates(itemPos, itemXform.MapID);
|
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);
|
TransformSystem.SetWorldPositionRotation(entity, GetFinalDropCoordinates(uid, origin, target), itemRot);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user