diff --git a/Content.Client/UserInterface/Systems/Storage/Controls/ItemGridPiece.cs b/Content.Client/UserInterface/Systems/Storage/Controls/ItemGridPiece.cs index a7298213e8..0ca1797965 100644 --- a/Content.Client/UserInterface/Systems/Storage/Controls/ItemGridPiece.cs +++ b/Content.Client/UserInterface/Systems/Storage/Controls/ItemGridPiece.cs @@ -6,7 +6,6 @@ using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.UserInterface; using Robust.Client.UserInterface.CustomControls; -using YamlDotNet.Core; namespace Content.Client.UserInterface.Systems.Storage.Controls; @@ -103,7 +102,7 @@ public sealed class ItemGridPiece : Control return; } - if (_storageController.IsDragging && _storageController.CurrentlyDragging == this) + if (_storageController.IsDragging && _storageController.DraggingGhost?.Entity == Entity && _storageController.DraggingGhost != this) return; var adjustedShape = _entityManager.System().GetAdjustedItemShape((Entity, itemComponent), Location.Rotation, Vector2i.Zero); @@ -177,7 +176,7 @@ public sealed class ItemGridPiece : Control handle.SetTransform(pos, iconRotation); var box = new UIBox2(root, root + sprite.Size * scale); handle.DrawTextureRect(sprite, box); - handle.SetTransform(Matrix3.Identity); + handle.SetTransform(GlobalPixelPosition, Angle.Zero); } else { diff --git a/Content.Client/UserInterface/Systems/Storage/Controls/StorageContainer.cs b/Content.Client/UserInterface/Systems/Storage/Controls/StorageContainer.cs index f40a20f2d2..8dfe2fff63 100644 --- a/Content.Client/UserInterface/Systems/Storage/Controls/StorageContainer.cs +++ b/Content.Client/UserInterface/Systems/Storage/Controls/StorageContainer.cs @@ -445,6 +445,7 @@ public sealed class StorageContainer : BaseWindow _entity.GetNetEntity(handEntity), _entity.GetNetEntity(StorageEntity.Value), insertLocation)); + _storageController.DraggingRotation = Angle.Zero; args.Handle(); } } diff --git a/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs b/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs index 85631f1aa8..c83a80b4a5 100644 --- a/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs +++ b/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs @@ -263,29 +263,55 @@ public sealed class StorageUIController : UIController, IOnSystemChanged(storageEnt, out var storageComp)) + return; + + if (DraggingGhost is { } draggingGhost) { - if (DraggingGhost is { } draggingGhost) + var dragEnt = draggingGhost.Entity; + var dragLoc = draggingGhost.Location; + var itemSys = _entity.System(); + + var position = _container.GetMouseGridPieceLocation(dragEnt, dragLoc); + var itemBounding = itemSys.GetAdjustedItemShape(dragEnt, dragLoc).GetBoundingBox(); + var gridBounding = storageComp.Grid.GetBoundingBox(); + + // The extended bounding box for if this is out of the window is the grid bounding box dimensions combined + // with the item shape bounding box dimensions. Plus 1 on the left for the sidebar. This makes it so that. + // dropping an item on the floor requires dragging it all the way out of the window. + var left = gridBounding.Left - itemBounding.Width - 1; + var bottom = gridBounding.Bottom - itemBounding.Height; + var top = gridBounding.Top; + var right = gridBounding.Right; + var lenientBounding = new Box2i(left, bottom, right, top); + + if (lenientBounding.Contains(position)) { - var position = _container.GetMouseGridPieceLocation(draggingGhost.Entity, draggingGhost.Location); _entity.RaisePredictiveEvent(new StorageSetItemLocationEvent( _entity.GetNetEntity(draggingGhost.Entity), _entity.GetNetEntity(storageEnt), new ItemStorageLocation(DraggingRotation, position))); - _container?.BuildItemPieces(); } - else //if we just clicked, then take it out of the bag. + else { - _entity.RaisePredictiveEvent(new StorageInteractWithItemEvent( - _entity.GetNetEntity(control.Entity), + _entity.RaisePredictiveEvent(new StorageRemoveItemEvent( + _entity.GetNetEntity(draggingGhost.Entity), _entity.GetNetEntity(storageEnt))); } - _menuDragHelper.EndDrag(); - args.Handle(); + + _container?.BuildItemPieces(); } + else //if we just clicked, then take it out of the bag. + { + _entity.RaisePredictiveEvent(new StorageInteractWithItemEvent( + _entity.GetNetEntity(control.Entity), + _entity.GetNetEntity(storageEnt))); + } + _menuDragHelper.EndDrag(); + args.Handle(); } private bool OnMenuBeginDrag() diff --git a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs index 57b25e0dd6..c5a130495d 100644 --- a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs @@ -83,6 +83,7 @@ public abstract class SharedStorageSystem : EntitySystem SubscribeAllEvent(OnInteractWithItem); SubscribeAllEvent(OnSetItemLocation); SubscribeAllEvent(OnInsertItemIntoLocation); + SubscribeAllEvent(OnRemoveItem); } private void OnComponentInit(EntityUid uid, StorageComponent storageComp, ComponentInit args) @@ -385,6 +386,34 @@ public abstract class SharedStorageSystem : EntitySystem TrySetItemStorageLocation((itemEnt, null), (storageEnt, storageComp), msg.Location); } + private void OnRemoveItem(StorageRemoveItemEvent msg, EntitySessionEventArgs args) + { + if (args.SenderSession.AttachedEntity is not { } player) + return; + + var storageEnt = GetEntity(msg.StorageEnt); + var itemEnt = GetEntity(msg.ItemEnt); + + if (!TryComp(storageEnt, out var storageComp)) + return; + + if (!_ui.TryGetUi(storageEnt, StorageComponent.StorageUiKey.Key, out var bui) || + !bui.SubscribedSessions.Contains(args.SenderSession)) + return; + + if (!Exists(itemEnt)) + { + Log.Error($"Player {args.SenderSession} set location of non-existent item {msg.ItemEnt} stored in {ToPrettyString(storageEnt)}"); + return; + } + + if (!ActionBlocker.CanInteract(player, itemEnt)) + return; + + TransformSystem.DropNextTo(itemEnt, player); + Audio.PlayPredicted(storageComp.StorageRemoveSound, storageEnt, player); + } + private void OnInsertItemIntoLocation(StorageInsertItemIntoLocationEvent msg, EntitySessionEventArgs args) { if (args.SenderSession.AttachedEntity is not { } player) diff --git a/Content.Shared/Storage/StorageComponent.cs b/Content.Shared/Storage/StorageComponent.cs index f150a3e8fb..e3287b20ad 100644 --- a/Content.Shared/Storage/StorageComponent.cs +++ b/Content.Shared/Storage/StorageComponent.cs @@ -132,6 +132,20 @@ namespace Content.Shared.Storage } } + [Serializable, NetSerializable] + public sealed class StorageRemoveItemEvent : EntityEventArgs + { + public readonly NetEntity ItemEnt; + + public readonly NetEntity StorageEnt; + + public StorageRemoveItemEvent(NetEntity itemEnt, NetEntity storageEnt) + { + ItemEnt = itemEnt; + StorageEnt = storageEnt; + } + } + [Serializable, NetSerializable] public sealed class StorageInsertItemIntoLocationEvent : EntityEventArgs {