From fc80a18c35c0ffce989cd5e9dd38c0b0ba932c68 Mon Sep 17 00:00:00 2001 From: Errant <35878406+Errant-4@users.noreply.github.com> Date: Wed, 5 Feb 2025 14:13:06 +0100 Subject: [PATCH] Revert "Storage UI V2 (#33045)" This reverts commit fd25dac720b6e7e98336e63a1cc4fa7fb831aa53. --- .../Storage/StorageBoundUserInterface.cs | 65 +--- .../Storage/Systems/StorageSystem.cs | 150 ++++---- .../Systems/Hotbar/HotbarUIController.cs | 3 +- .../Systems/Hotbar/Widgets/HotbarGui.xaml | 5 +- .../Systems/Hotbar/Widgets/HotbarGui.xaml.cs | 2 +- .../Systems/Storage/Controls/ItemGridPiece.cs | 7 +- .../{StorageWindow.cs => StorageContainer.cs} | 328 ++++------------ .../Systems/Storage/StorageUIController.cs | 358 +++++++++--------- Content.Shared/CCVar/CCVars.Interactions.cs | 19 - .../EntitySystems/SharedStorageSystem.cs | 268 ++++--------- Content.Shared/Storage/StorageComponent.cs | 33 -- 11 files changed, 422 insertions(+), 816 deletions(-) rename Content.Client/UserInterface/Systems/Storage/Controls/{StorageWindow.cs => StorageContainer.cs} (64%) diff --git a/Content.Client/Storage/StorageBoundUserInterface.cs b/Content.Client/Storage/StorageBoundUserInterface.cs index bacc90eabf..b90977cbb4 100644 --- a/Content.Client/Storage/StorageBoundUserInterface.cs +++ b/Content.Client/Storage/StorageBoundUserInterface.cs @@ -1,80 +1,39 @@ -using Content.Client.UserInterface.Systems.Storage; -using Content.Client.UserInterface.Systems.Storage.Controls; +using Content.Client.Storage.Systems; using Content.Shared.Storage; using JetBrains.Annotations; -using Robust.Client.UserInterface; namespace Content.Client.Storage; [UsedImplicitly] public sealed class StorageBoundUserInterface : BoundUserInterface { - private StorageWindow? _window; + [Dependency] private readonly IEntityManager _entManager = default!; + + private readonly StorageSystem _storage; + + [Obsolete] public override bool DeferredClose => false; public StorageBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { + IoCManager.InjectDependencies(this); + _storage = _entManager.System(); } protected override void Open() { base.Open(); - _window = IoCManager.Resolve() - .GetUIController() - .CreateStorageWindow(Owner); - - if (EntMan.TryGetComponent(Owner, out StorageComponent? storage)) - { - _window.UpdateContainer((Owner, storage)); - } - - _window.OnClose += Close; - _window.FlagDirty(); - } - - public void Refresh() - { - _window?.FlagDirty(); - } - - public void Reclaim() - { - if (_window == null) - return; - - _window.OnClose -= Close; - _window.Orphan(); - _window = null; + if (_entManager.TryGetComponent(Owner, out var comp)) + _storage.OpenStorageWindow((Owner, comp)); } protected override void Dispose(bool disposing) { base.Dispose(disposing); - - Reclaim(); - } - - public void Hide() - { - if (_window == null) + if (!disposing) return; - _window.Visible = false; - } - - public void Show() - { - if (_window == null) - return; - - _window.Visible = true; - } - - public void ReOpen() - { - _window?.Orphan(); - _window = null; - Open(); + _storage.CloseStorageWindow(Owner); } } diff --git a/Content.Client/Storage/Systems/StorageSystem.cs b/Content.Client/Storage/Systems/StorageSystem.cs index ab4d9407b2..eea7b9ec79 100644 --- a/Content.Client/Storage/Systems/StorageSystem.cs +++ b/Content.Client/Storage/Systems/StorageSystem.cs @@ -4,8 +4,7 @@ using Content.Client.Animations; using Content.Shared.Hands; using Content.Shared.Storage; using Content.Shared.Storage.EntitySystems; -using Robust.Client.Player; -using Robust.Shared.GameStates; +using Robust.Shared.Collections; using Robust.Shared.Map; using Robust.Shared.Timing; @@ -14,95 +13,114 @@ namespace Content.Client.Storage.Systems; public sealed class StorageSystem : SharedStorageSystem { [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly IPlayerManager _player = default!; [Dependency] private readonly EntityPickupAnimationSystem _entityPickupAnimation = default!; - private Dictionary _oldStoredItems = new(); + private readonly List> _openStorages = new(); + public int OpenStorageAmount => _openStorages.Count; + + public event Action>? StorageUpdated; + public event Action?>? StorageOrderChanged; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnStorageHandleState); + SubscribeLocalEvent(OnShutdown); SubscribeNetworkEvent(HandlePickupAnimation); SubscribeAllEvent(HandleAnimatingInsertingEntities); } - private void OnStorageHandleState(EntityUid uid, StorageComponent component, ref ComponentHandleState args) + public override void UpdateUI(Entity entity) { - if (args.Current is not StorageComponentState state) - return; + if (Resolve(entity.Owner, ref entity.Comp)) + StorageUpdated?.Invoke((entity, entity.Comp)); + } - component.Grid.Clear(); - component.Grid.AddRange(state.Grid); - component.MaxItemSize = state.MaxItemSize; - component.Whitelist = state.Whitelist; - component.Blacklist = state.Blacklist; - - _oldStoredItems.Clear(); - - foreach (var item in component.StoredItems) + public void OpenStorageWindow(Entity entity) + { + if (_openStorages.Contains(entity)) { - _oldStoredItems.Add(item.Key, item.Value); - } - - component.StoredItems.Clear(); - - foreach (var (nent, location) in state.StoredItems) - { - var ent = EnsureEntity(nent, uid); - component.StoredItems[ent] = location; - } - - component.SavedLocations.Clear(); - - foreach (var loc in state.SavedLocations) - { - component.SavedLocations[loc.Key] = new(loc.Value); - } - - var uiDirty = !component.StoredItems.SequenceEqual(_oldStoredItems); - - if (uiDirty && UI.TryGetOpenUi(uid, StorageComponent.StorageUiKey.Key, out var storageBui)) - { - storageBui.Refresh(); - // Make sure nesting still updated. - var player = _player.LocalEntity; - - if (NestedStorage && player != null && ContainerSystem.TryGetContainingContainer((uid, null, null), out var container) && - UI.TryGetOpenUi(container.Owner, StorageComponent.StorageUiKey.Key, out var containerBui)) + if (_openStorages.LastOrDefault() == entity) { - containerBui.Hide(); + CloseStorageWindow((entity, entity.Comp)); } else { - storageBui.Show(); + var storages = new ValueList>(_openStorages); + var reverseStorages = storages.Reverse(); + + foreach (var storageEnt in reverseStorages) + { + if (storageEnt == entity) + break; + + CloseStorageBoundUserInterface(storageEnt.Owner); + _openStorages.Remove(entity); + } } + return; + } + + ClearNonParentStorages(entity); + _openStorages.Add(entity); + Entity? last = _openStorages.LastOrDefault(); + StorageOrderChanged?.Invoke(last); + } + + public void CloseStorageWindow(Entity entity) + { + if (!Resolve(entity, ref entity.Comp, false)) + return; + + if (!_openStorages.Contains((entity, entity.Comp))) + return; + + var storages = new ValueList>(_openStorages); + var reverseStorages = storages.Reverse(); + + foreach (var storage in reverseStorages) + { + CloseStorageBoundUserInterface(storage.Owner); + _openStorages.Remove(storage); + if (storage.Owner == entity.Owner) + break; + } + + Entity? last = null; + if (_openStorages.Any()) + last = _openStorages.LastOrDefault(); + StorageOrderChanged?.Invoke(last); + } + + private void ClearNonParentStorages(EntityUid uid) + { + var storages = new ValueList>(_openStorages); + var reverseStorages = storages.Reverse(); + + foreach (var storage in reverseStorages) + { + if (storage.Comp.Container.Contains(uid)) + break; + + CloseStorageBoundUserInterface(storage.Owner); + _openStorages.Remove(storage); } } - public override void UpdateUI(Entity entity) + private void CloseStorageBoundUserInterface(Entity entity) { - if (UI.TryGetOpenUi(entity.Owner, StorageComponent.StorageUiKey.Key, out var sBui)) - { - sBui.Refresh(); - } + if (!Resolve(entity, ref entity.Comp, false)) + return; + + if (entity.Comp.ClientOpenInterfaces.GetValueOrDefault(StorageComponent.StorageUiKey.Key) is not { } bui) + return; + + bui.Close(); } - protected override void HideStorageWindow(EntityUid uid, EntityUid actor) + private void OnShutdown(Entity ent, ref ComponentShutdown args) { - if (UI.TryGetOpenUi(uid, StorageComponent.StorageUiKey.Key, out var storageBui)) - { - storageBui.Hide(); - } - } - - protected override void ShowStorageWindow(EntityUid uid, EntityUid actor) - { - if (UI.TryGetOpenUi(uid, StorageComponent.StorageUiKey.Key, out var storageBui)) - { - storageBui.Show(); - } + CloseStorageWindow((ent, ent.Comp)); } /// @@ -124,7 +142,7 @@ public sealed class StorageSystem : SharedStorageSystem { if (!_timing.IsFirstTimePredicted) return; - + if (TransformSystem.InRange(finalCoords, initialCoords, 0.1f) || !Exists(initialCoords.EntityId) || !Exists(finalCoords.EntityId)) { diff --git a/Content.Client/UserInterface/Systems/Hotbar/HotbarUIController.cs b/Content.Client/UserInterface/Systems/Hotbar/HotbarUIController.cs index b89115da86..2f266cfdd6 100644 --- a/Content.Client/UserInterface/Systems/Hotbar/HotbarUIController.cs +++ b/Content.Client/UserInterface/Systems/Hotbar/HotbarUIController.cs @@ -31,12 +31,13 @@ public sealed class HotbarUIController : UIController ReloadHotbar(); } - public void Setup(HandsContainer handsContainer) + public void Setup(HandsContainer handsContainer, StorageContainer storageContainer) { _inventory = UIManager.GetUIController(); _hands = UIManager.GetUIController(); _storage = UIManager.GetUIController(); _hands.RegisterHandContainer(handsContainer); + _storage.RegisterStorageContainer(storageContainer); } public void ReloadHotbar() diff --git a/Content.Client/UserInterface/Systems/Hotbar/Widgets/HotbarGui.xaml b/Content.Client/UserInterface/Systems/Hotbar/Widgets/HotbarGui.xaml index 153e02bd55..00ba1878b4 100644 --- a/Content.Client/UserInterface/Systems/Hotbar/Widgets/HotbarGui.xaml +++ b/Content.Client/UserInterface/Systems/Hotbar/Widgets/HotbarGui.xaml @@ -1,6 +1,7 @@  + (); - hotbarController.Setup(HandContainer); + hotbarController.Setup(HandContainer, StoragePanel); LayoutContainer.SetGrowVertical(this, LayoutContainer.GrowDirection.Begin); } diff --git a/Content.Client/UserInterface/Systems/Storage/Controls/ItemGridPiece.cs b/Content.Client/UserInterface/Systems/Storage/Controls/ItemGridPiece.cs index f4c4158b5c..dd9986e4c6 100644 --- a/Content.Client/UserInterface/Systems/Storage/Controls/ItemGridPiece.cs +++ b/Content.Client/UserInterface/Systems/Storage/Controls/ItemGridPiece.cs @@ -59,7 +59,7 @@ public sealed class ItemGridPiece : Control, IEntityControl Location = location; Visible = true; - MouseFilter = MouseFilterMode.Stop; + MouseFilter = MouseFilterMode.Pass; TooltipSupplier = SupplyTooltip; @@ -105,11 +105,8 @@ public sealed class ItemGridPiece : Control, IEntityControl return; } - if (_storageController.IsDragging && _storageController.DraggingGhost?.Entity == Entity && - _storageController.DraggingGhost != this) - { + if (_storageController.IsDragging && _storageController.DraggingGhost?.Entity == Entity && _storageController.DraggingGhost != this) return; - } var adjustedShape = _entityManager.System().GetAdjustedItemShape((Entity, itemComponent), Location.Rotation, Vector2i.Zero); var boundingGrid = adjustedShape.GetBoundingBox(); diff --git a/Content.Client/UserInterface/Systems/Storage/Controls/StorageWindow.cs b/Content.Client/UserInterface/Systems/Storage/Controls/StorageContainer.cs similarity index 64% rename from Content.Client/UserInterface/Systems/Storage/Controls/StorageWindow.cs rename to Content.Client/UserInterface/Systems/Storage/Controls/StorageContainer.cs index 4527ffd59a..a9d7e09826 100644 --- a/Content.Client/UserInterface/Systems/Storage/Controls/StorageWindow.cs +++ b/Content.Client/UserInterface/Systems/Storage/Controls/StorageContainer.cs @@ -3,9 +3,7 @@ using System.Linq; using System.Numerics; using Content.Client.Hands.Systems; using Content.Client.Items.Systems; -using Content.Client.Storage; using Content.Client.Storage.Systems; -using Content.Shared.IdentityManagement; using Content.Shared.Input; using Content.Shared.Item; using Content.Shared.Storage; @@ -13,14 +11,12 @@ using Robust.Client.Graphics; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; -using Robust.Shared.Collections; -using Robust.Shared.Containers; using Robust.Shared.Timing; using Robust.Shared.Utility; namespace Content.Client.UserInterface.Systems.Storage.Controls; -public sealed class StorageWindow : BaseWindow +public sealed class StorageContainer : BaseWindow { [Dependency] private readonly IEntityManager _entity = default!; private readonly StorageUIController _storageController; @@ -31,20 +27,6 @@ public sealed class StorageWindow : BaseWindow private readonly GridContainer _backgroundGrid; private readonly GridContainer _sidebar; - private Control _titleContainer; - private Label _titleLabel; - - // Needs to be nullable in case a piece is in default spot. - private readonly Dictionary _pieces = new(); - private readonly List _controlGrid = new(); - - private ValueList _contained = new(); - private ValueList _toRemove = new(); - - private TextureButton? _backButton; - - private bool _isDirty; - public event Action? OnPiecePressed; public event Action? OnPieceUnpressed; @@ -69,10 +51,9 @@ public sealed class StorageWindow : BaseWindow private readonly string _sidebarFatTexturePath = "Storage/sidebar_fat"; private Texture? _sidebarFatTexture; - public StorageWindow() + public StorageContainer() { IoCManager.InjectDependencies(this); - Resizable = false; _storageController = UserInterfaceManager.GetUIController(); @@ -82,7 +63,6 @@ public sealed class StorageWindow : BaseWindow _sidebar = new GridContainer { - Name = "SideBar", HSeparationOverride = 0, VSeparationOverride = 0, Columns = 1 @@ -90,48 +70,21 @@ public sealed class StorageWindow : BaseWindow _pieceGrid = new GridContainer { - Name = "PieceGrid", HSeparationOverride = 0, VSeparationOverride = 0 }; _backgroundGrid = new GridContainer { - Name = "BackgroundGrid", HSeparationOverride = 0, VSeparationOverride = 0 }; - _titleLabel = new Label() - { - HorizontalExpand = true, - Name = "StorageLabel", - ClipText = true, - Text = "Dummy", - StyleClasses = - { - "FancyWindowTitle", - } - }; - - _titleContainer = new PanelContainer() - { - StyleClasses = - { - "WindowHeadingBackground" - }, - Children = - { - _titleLabel - } - }; - var container = new BoxContainer { Orientation = BoxContainer.LayoutOrientation.Vertical, Children = { - _titleContainer, new BoxContainer { Orientation = BoxContainer.LayoutOrientation.Horizontal, @@ -177,22 +130,12 @@ public sealed class StorageWindow : BaseWindow if (entity == null) return; - if (UserInterfaceManager.GetUIController().WindowTitle) - { - _titleLabel.Text = Identity.Name(entity.Value, _entity); - _titleContainer.Visible = true; - } - else - { - _titleContainer.Visible = false; - } - BuildGridRepresentation(); } private void BuildGridRepresentation() { - if (!_entity.TryGetComponent(StorageEntity, out var comp) || comp.Grid.Count == 0) + if (!_entity.TryGetComponent(StorageEntity, out var comp) || !comp.Grid.Any()) return; var boundingGrid = comp.Grid.GetBoundingBox(); @@ -202,11 +145,11 @@ public sealed class StorageWindow : BaseWindow #region Sidebar _sidebar.Children.Clear(); _sidebar.Rows = boundingGrid.Height + 1; - var exitButton = new TextureButton { - Name = "ExitButton", - TextureNormal = _exitTexture, + TextureNormal = _entity.System().OpenStorageAmount == 1 + ?_exitTexture + : _backTexture, Scale = new Vector2(2, 2), }; exitButton.OnPressed += _ => @@ -222,10 +165,8 @@ public sealed class StorageWindow : BaseWindow args.Handle(); } }; - var exitContainer = new BoxContainer { - Name = "ExitContainer", Children = { new TextureRect @@ -241,61 +182,8 @@ public sealed class StorageWindow : BaseWindow } } }; - _sidebar.AddChild(exitContainer); - var offset = 1; - - if (_entity.System().NestedStorage && boundingGrid.Height > 0) - { - offset += 1; - - _backButton = new TextureButton - { - TextureNormal = _backTexture, - Scale = new Vector2(2, 2), - }; - _backButton.OnPressed += _ => - { - var containerSystem = _entity.System(); - - if (containerSystem.TryGetContainingContainer(StorageEntity.Value, out var container) && - _entity.TryGetComponent(container.Owner, out StorageComponent? storage)) - { - Close(); - - if (_entity.System() - .TryGetOpenUi(container.Owner, - StorageComponent.StorageUiKey.Key, - out var parentBui)) - { - parentBui.Show(); - } - } - }; - - var backContainer = new BoxContainer - { - Name = "ExitContainer", - Children = - { - new TextureRect - { - Texture = boundingGrid.Height > 2 ? _sidebarMiddleTexture : _sidebarBottomTexture, - TextureScale = new Vector2(2, 2), - Children = - { - _backButton, - } - } - } - }; - - _sidebar.AddChild(backContainer); - } - - var rows = boundingGrid.Height - offset; - - for (var i = 0; i < rows; i++) + for (var i = 0; i < boundingGrid.Height - 1; i++) { _sidebar.AddChild(new TextureRect { @@ -304,7 +192,7 @@ public sealed class StorageWindow : BaseWindow }); } - if (rows > 0) + if (boundingGrid.Height > 0) { _sidebar.AddChild(new TextureRect { @@ -315,7 +203,7 @@ public sealed class StorageWindow : BaseWindow #endregion - FlagDirty(); + BuildItemPieces(); } public void BuildBackground() @@ -352,127 +240,70 @@ public sealed class StorageWindow : BaseWindow } } - public void Reclaim(ItemStorageLocation location, ItemGridPiece draggingGhost) - { - draggingGhost.OnPiecePressed += OnPiecePressed; - draggingGhost.OnPieceUnpressed += OnPieceUnpressed; - _pieces[draggingGhost.Entity] = (location, draggingGhost); - draggingGhost.Location = location; - var controlIndex = GetGridIndex(draggingGhost); - _controlGrid[controlIndex].AddChild(draggingGhost); - } - - private int GetGridIndex(ItemGridPiece piece) - { - return piece.Location.Position.X + piece.Location.Position.Y * _pieceGrid.Columns; - } - - public void FlagDirty() - { - _isDirty = true; - } - - public void RemoveGrid(ItemGridPiece control) - { - control.Orphan(); - _pieces.Remove(control.Entity); - control.OnPiecePressed -= OnPiecePressed; - control.OnPieceUnpressed -= OnPieceUnpressed; - } - public void BuildItemPieces() { if (!_entity.TryGetComponent(StorageEntity, out var storageComp)) return; - if (storageComp.Grid.Count == 0) + if (!storageComp.Grid.Any()) return; var boundingGrid = storageComp.Grid.GetBoundingBox(); var size = _emptyTexture!.Size * 2; - _contained.Clear(); - _contained.AddRange(storageComp.Container.ContainedEntities.Reverse()); + var containedEntities = storageComp.Container.ContainedEntities.Reverse().ToArray(); - // Build the grid representation - if (_pieceGrid.Rows - 1 != boundingGrid.Height || _pieceGrid.Columns - 1 != boundingGrid.Width) + //todo. at some point, we may want to only rebuild the pieces that have actually received new data. + + _pieceGrid.RemoveAllChildren(); + _pieceGrid.Rows = boundingGrid.Height + 1; + _pieceGrid.Columns = boundingGrid.Width + 1; + for (var y = boundingGrid.Bottom; y <= boundingGrid.Top; y++) { - _pieceGrid.Rows = boundingGrid.Height + 1; - _pieceGrid.Columns = boundingGrid.Width + 1; - _controlGrid.Clear(); - - for (var y = boundingGrid.Bottom; y <= boundingGrid.Top; y++) + for (var x = boundingGrid.Left; x <= boundingGrid.Right; x++) { - for (var x = boundingGrid.Left; x <= boundingGrid.Right; x++) + var control = new Control { - var control = new Control - { - MinSize = size - }; - - _controlGrid.Add(control); - _pieceGrid.AddChild(control); - } - } - } - - _toRemove.Clear(); - - // Remove entities no longer relevant / Update existing ones - foreach (var (ent, data) in _pieces) - { - if (storageComp.StoredItems.TryGetValue(ent, out var updated)) - { - if (data.Loc.Equals(updated)) - { - DebugTools.Assert(data.Control.Location == updated); - continue; - } - - // Update - data.Control.Location = updated; - var index = GetGridIndex(data.Control); - data.Control.Orphan(); - _controlGrid[index].AddChild(data.Control); - _pieces[ent] = (updated, data.Control); - continue; - } - - _toRemove.Add(ent); - } - - foreach (var ent in _toRemove) - { - _pieces.Remove(ent, out var data); - data.Control.Orphan(); - } - - // Add new ones - foreach (var (ent, loc) in storageComp.StoredItems) - { - if (_pieces.TryGetValue(ent, out var existing)) - { - DebugTools.Assert(existing.Loc == loc); - continue; - } - - if (_entity.TryGetComponent(ent, out var itemEntComponent)) - { - var gridPiece = new ItemGridPiece((ent, itemEntComponent), loc, _entity) - { - MinSize = size, - Marked = _contained.IndexOf(ent) switch - { - 0 => ItemGridPieceMarks.First, - 1 => ItemGridPieceMarks.Second, - _ => null, - } + MinSize = size }; - gridPiece.OnPiecePressed += OnPiecePressed; - gridPiece.OnPieceUnpressed += OnPieceUnpressed; - var controlIndex = loc.Position.X + loc.Position.Y * (boundingGrid.Width + 1); - _controlGrid[controlIndex].AddChild(gridPiece); - _pieces[ent] = (loc, gridPiece); + var currentPosition = new Vector2i(x, y); + + foreach (var (itemEnt, itemPos) in storageComp.StoredItems) + { + if (itemPos.Position != currentPosition) + continue; + + if (_entity.TryGetComponent(itemEnt, out var itemEntComponent)) + { + ItemGridPiece gridPiece; + + if (_storageController.CurrentlyDragging?.Entity is { } dragging + && dragging == itemEnt) + { + _storageController.CurrentlyDragging.Orphan(); + gridPiece = _storageController.CurrentlyDragging; + } + else + { + gridPiece = new ItemGridPiece((itemEnt, itemEntComponent), itemPos, _entity) + { + MinSize = size, + Marked = Array.IndexOf(containedEntities, itemEnt) switch + { + 0 => ItemGridPieceMarks.First, + 1 => ItemGridPieceMarks.Second, + _ => null, + } + }; + gridPiece.OnPiecePressed += OnPiecePressed; + gridPiece.OnPieceUnpressed += OnPieceUnpressed; + } + + control.AddChild(gridPiece); + } + } + + _pieceGrid.AddChild(control); } } } @@ -484,35 +315,6 @@ public sealed class StorageWindow : BaseWindow if (!IsOpen) return; - if (_isDirty) - { - _isDirty = false; - BuildItemPieces(); - } - - var containerSystem = _entity.System(); - - if (_backButton != null) - { - if (StorageEntity != null && _entity.System().NestedStorage) - { - if (containerSystem.TryGetContainingContainer(StorageEntity.Value, out var container) && - _entity.HasComponent(container.Owner)) - { - _backButton.Visible = true; - } - else - { - _backButton.Visible = false; - } - } - // Hide the button. - else - { - _backButton.Visible = false; - } - } - var itemSystem = _entity.System(); var storageSystem = _entity.System(); var handsSystem = _entity.System(); @@ -522,7 +324,7 @@ public sealed class StorageWindow : BaseWindow child.ModulateSelfOverride = Color.FromHex("#222222"); } - if (UserInterfaceManager.CurrentlyHovered is StorageWindow con && con != this) + if (UserInterfaceManager.CurrentlyHovered is StorageContainer con && con != this) return; if (!_entity.TryGetComponent(StorageEntity, out var storageComponent)) @@ -571,7 +373,7 @@ public sealed class StorageWindow : BaseWindow continue; float spot = 0; - var marked = new ValueList(); + var marked = new List(); foreach (var location in locations.Value) { @@ -698,4 +500,14 @@ public sealed class StorageWindow : BaseWindow } } } + + public override void Close() + { + base.Close(); + + if (StorageEntity == null) + return; + + _entity.System().CloseStorageWindow(StorageEntity.Value); + } } diff --git a/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs b/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs index cbcf4293e8..1e61ad9838 100644 --- a/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs +++ b/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs @@ -2,7 +2,6 @@ using System.Numerics; using Content.Client.Examine; using Content.Client.Hands.Systems; using Content.Client.Interaction; -using Content.Client.Storage; using Content.Client.Storage.Systems; using Content.Client.UserInterface.Systems.Hotbar.Widgets; using Content.Client.UserInterface.Systems.Storage.Controls; @@ -10,9 +9,9 @@ using Content.Client.Verbs.UI; using Content.Shared.CCVar; using Content.Shared.Input; using Content.Shared.Interaction; +using Content.Shared.Item; using Content.Shared.Storage; using Robust.Client.Input; -using Robust.Client.Player; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controllers; using Robust.Client.UserInterface.Controls; @@ -24,28 +23,19 @@ namespace Content.Client.UserInterface.Systems.Storage; public sealed class StorageUIController : UIController, IOnSystemChanged { - /* - * Things are a bit over the shop but essentially - * - Clicking into storagewindow is handled via storagewindow - * - Clicking out of it is via ItemGridPiece - * - Dragging around is handled here - * - Drawing is handled via ItemGridPiece - * - StorageSystem handles any sim stuff around open windows. - */ - [Dependency] private readonly IConfigurationManager _configuration = default!; + [Dependency] private readonly IEntityManager _entity = default!; [Dependency] private readonly IInputManager _input = default!; - [Dependency] private readonly IPlayerManager _player = default!; - [UISystemDependency] private readonly StorageSystem _storage = default!; - - /// - /// Cached positions for opening nested storage. - /// - private readonly Dictionary _reservedStorage = new(); + [Dependency] private readonly IUserInterfaceManager _ui = default!; private readonly DragDropHelper _menuDragHelper; + private StorageContainer? _container; - public ItemGridPiece? DraggingGhost => _menuDragHelper.Dragged; + private Vector2? _lastContainerPosition; + + private HotbarGui? Hotbar => UIManager.GetActiveUIWidgetOrNull(); + + public ItemGridPiece? DraggingGhost; public Angle DraggingRotation = Angle.Zero; public bool StaticStorageUIEnabled; public bool OpaqueStorageWindow; @@ -53,8 +43,6 @@ public sealed class StorageUIController : UIController, IOnSystemChanged _menuDragHelper.IsDragging; public ItemGridPiece? CurrentlyDragging => _menuDragHelper.Dragged; - public bool WindowTitle { get; private set; } = false; - public StorageUIController() { _menuDragHelper = new DragDropHelper(OnMenuBeginDrag, OnMenuContinueDrag, OnMenuEndDrag); @@ -64,93 +52,106 @@ public sealed class StorageUIController : UIController, IOnSystemChanged(); - - foreach (var bui in uiSystem.GetActorUis((_player.LocalEntity.Value, userComp))) - { - if (!uiSystem.TryGetOpenUi(bui.Entity, StorageComponent.StorageUiKey.Key, out var storageBui)) - continue; - - storageBui.ReOpen(); - } - } - - private void OnStorageWindowTitle(bool obj) - { - WindowTitle = obj; - } - - private void OnOpaqueWindowChanged(bool obj) - { - OpaqueStorageWindow = obj; - } - - private void OnStaticStorageChanged(bool obj) - { - StaticStorageUIEnabled = obj; - } - - public StorageWindow CreateStorageWindow(EntityUid uid) - { - var window = new StorageWindow(); - window.MouseFilter = Control.MouseFilterMode.Pass; - - window.OnPiecePressed += (args, piece) => - { - OnPiecePressed(args, window, piece); - }; - window.OnPieceUnpressed += (args, piece) => - { - OnPieceUnpressed(args, window, piece); - }; - - if (StaticStorageUIEnabled) - { - UIManager.GetActiveUIWidgetOrNull()?.StorageContainer.AddChild(window); - } - else - { - window.OpenCenteredLeft(); - - if (_reservedStorage.Remove(uid, out var pos)) - { - LayoutContainer.SetPosition(window, pos); - } - } - - return window; } public void OnSystemLoaded(StorageSystem system) { _input.FirstChanceOnKeyEvent += OnMiddleMouse; + system.StorageUpdated += OnStorageUpdated; + system.StorageOrderChanged += OnStorageOrderChanged; } public void OnSystemUnloaded(StorageSystem system) { _input.FirstChanceOnKeyEvent -= OnMiddleMouse; + system.StorageUpdated -= OnStorageUpdated; + system.StorageOrderChanged -= OnStorageOrderChanged; + } + + private void OnStorageOrderChanged(Entity? nullEnt) + { + if (_container == null) + return; + + if (IsDragging) + _menuDragHelper.EndDrag(); + + _container.UpdateContainer(nullEnt); + + if (nullEnt is not null) + { + // center it if we knock it off screen somehow. + if (!StaticStorageUIEnabled && + (_lastContainerPosition == null || + _lastContainerPosition.Value.X < 0 || + _lastContainerPosition.Value.Y < 0 || + _lastContainerPosition.Value.X > _ui.WindowRoot.Width || + _lastContainerPosition.Value.Y > _ui.WindowRoot.Height)) + { + _container.OpenCenteredAt(new Vector2(0.5f, 0.75f)); + } + else + { + _container.Open(); + + var pos = !StaticStorageUIEnabled && _lastContainerPosition != null + ? _lastContainerPosition.Value + : Vector2.Zero; + + LayoutContainer.SetPosition(_container, pos); + } + + if (StaticStorageUIEnabled) + { + // we have to orphan it here because Open() sets the parent. + _container.Orphan(); + Hotbar?.StorageContainer.AddChild(_container); + } + _lastContainerPosition = _container.GlobalPosition; + } + else + { + _lastContainerPosition = _container.GlobalPosition; + _container.Close(); + } + } + + private void OnStaticStorageChanged(bool obj) + { + if (StaticStorageUIEnabled == obj) + return; + + StaticStorageUIEnabled = obj; + _lastContainerPosition = null; + + if (_container == null) + return; + + if (!_container.IsOpen) + return; + + _container.Orphan(); + if (StaticStorageUIEnabled) + { + Hotbar?.StorageContainer.AddChild(_container); + } + else + { + _ui.WindowRoot.AddChild(_container); + } + + if (_entity.TryGetComponent(_container.StorageEntity, out var comp)) + OnStorageOrderChanged((_container.StorageEntity.Value, comp)); + } + + private void OnOpaqueWindowChanged(bool obj) + { + if (OpaqueStorageWindow == obj) + return; + OpaqueStorageWindow = obj; + _container?.BuildBackground(); } /// One might ask, Hey Emo, why are you parsing raw keyboard input just to rotate a rectangle? @@ -189,7 +190,7 @@ public sealed class StorageUIController : UIController, IOnSystemChanged().GetActiveHandEntity() == null) + if (!IsDragging && _entity.System().GetActiveHandEntity() == null) return; //clamp it to a cardinal. @@ -197,18 +198,43 @@ public sealed class StorageUIController : UIController, IOnSystemChanged uid) { - if (IsDragging || !window.IsOpen) + if (_container?.StorageEntity != uid) + return; + + _container.BuildItemPieces(); + } + + public void RegisterStorageContainer(StorageContainer container) + { + if (_container != null) + { + container.OnPiecePressed -= OnPiecePressed; + container.OnPieceUnpressed -= OnPieceUnpressed; + } + + _container = container; + container.OnPiecePressed += OnPiecePressed; + container.OnPieceUnpressed += OnPieceUnpressed; + + if (!StaticStorageUIEnabled) + _container.Orphan(); + } + + private void OnPiecePressed(GUIBoundKeyEventArgs args, ItemGridPiece control) + { + if (IsDragging || !_container?.IsOpen == true) return; if (args.Function == ContentKeyFunctions.MoveStoredItem) { DraggingRotation = control.Location.Rotation; + _menuDragHelper.MouseDown(control); _menuDragHelper.Update(0f); @@ -216,17 +242,17 @@ public sealed class StorageUIController : UIController, IOnSystemChanged().DoExamine(control.Entity); + _entity.System().DoExamine(control.Entity); args.Handle(); } else if (args.Function == EngineKeyFunctions.UseSecondary) @@ -236,102 +262,62 @@ public sealed class StorageUIController : UIController, IOnSystemChanged(storageEnt, out var storageComp)) return; - } - if (_menuDragHelper.IsDragging && DraggingGhost is { } draggingGhost) + if (DraggingGhost is { } draggingGhost) { var dragEnt = draggingGhost.Entity; var dragLoc = draggingGhost.Location; + var itemSys = _entity.System(); - // Dragging in the same storage - // The existing ItemGridPiece just stops rendering but still exists so check if it's hovered. - if (targetStorage == window) + 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 = targetStorage.GetMouseGridPieceLocation(dragEnt, dragLoc); - var newLocation = new ItemStorageLocation(DraggingRotation, position); - - EntityManager.RaisePredictiveEvent(new StorageSetItemLocationEvent( - EntityManager.GetNetEntity(draggingGhost.Entity), - EntityManager.GetNetEntity(sourceStorage), - newLocation)); - - window.Reclaim(newLocation, control); - } - // Dragging to new storage - else if (targetStorage?.StorageEntity != null && targetStorage != window) - { - var position = targetStorage.GetMouseGridPieceLocation(dragEnt, dragLoc); - var newLocation = new ItemStorageLocation(DraggingRotation, position); - - // Check it fits and we can move to hand (no free transfers). - if (_storage.ItemFitsInGridLocation( - (dragEnt, null), - (targetStorage.StorageEntity.Value, null), - newLocation)) - { - // Can drop and move. - EntityManager.RaisePredictiveEvent(new StorageTransferItemEvent( - EntityManager.GetNetEntity(dragEnt), - EntityManager.GetNetEntity(targetStorage.StorageEntity.Value), - newLocation)); - - targetStorage.Reclaim(newLocation, control); - DraggingRotation = Angle.Zero; - } - else - { - // Cancel it (rather than dropping). - window.Reclaim(dragLoc, control); - } + _entity.RaisePredictiveEvent(new StorageSetItemLocationEvent( + _entity.GetNetEntity(draggingGhost.Entity), + _entity.GetNetEntity(storageEnt), + new ItemStorageLocation(DraggingRotation, position))); } - targetStorage?.FlagDirty(); + _menuDragHelper.EndDrag(); + _container?.BuildItemPieces(); } - // If we just clicked, then take it out of the bag. - else + else //if we just clicked, then take it out of the bag. { - EntityManager.RaisePredictiveEvent(new StorageInteractWithItemEvent( - EntityManager.GetNetEntity(control.Entity), - EntityManager.GetNetEntity(sourceStorage))); + _menuDragHelper.EndDrag(); + _entity.RaisePredictiveEvent(new StorageInteractWithItemEvent( + _entity.GetNetEntity(control.Entity), + _entity.GetNetEntity(storageEnt))); } - - _menuDragHelper.EndDrag(); args.Handle(); } @@ -340,8 +326,14 @@ public sealed class StorageUIController : UIController, IOnSystemChanged(dragged.Entity)), + dragged.Location, + _entity); + DraggingGhost.MouseFilter = Control.MouseFilterMode.Ignore; + DraggingGhost.Visible = true; + DraggingGhost.Orphan(); UIManager.PopupRoot.AddChild(DraggingGhost); SetDraggingRotation(); @@ -352,7 +344,6 @@ public sealed class StorageUIController : UIController, IOnSystemChanged public static readonly CVarDef OpaqueStorageWindow = CVarDef.Create("control.opaque_storage_background", false, CVar.CLIENTONLY | CVar.ARCHIVE); - - /// - /// Whether or not the storage window has a title of the entity name. - /// - public static readonly CVarDef StorageWindowTitle = - CVarDef.Create("control.storage_window_title", false, CVar.CLIENTONLY | CVar.ARCHIVE); - - /// - /// How many storage windows are allowed to be open at once. - /// Recommended that you utilise this in conjunction with - /// - public static readonly CVarDef StorageLimit = - CVarDef.Create("control.storage_limit", 1, CVar.REPLICATED | CVar.SERVER); - - /// - /// Whether or not storage can be opened recursively. - /// - public static readonly CVarDef NestedStorage = - CVarDef.Create("control.nested_storage", true, CVar.REPLICATED | CVar.SERVER); } diff --git a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs index f156db506a..123282fbdb 100644 --- a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs @@ -3,7 +3,6 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using Content.Shared.ActionBlocker; using Content.Shared.Administration.Logs; -using Content.Shared.CCVar; using Content.Shared.Containers.ItemSlots; using Content.Shared.Database; using Content.Shared.Destructible; @@ -28,7 +27,6 @@ using Content.Shared.Verbs; using Content.Shared.Whitelist; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; -using Robust.Shared.Configuration; using Robust.Shared.Containers; using Robust.Shared.GameStates; using Robust.Shared.Input.Binding; @@ -37,46 +35,36 @@ using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Serialization; -using Robust.Shared.Timing; using Robust.Shared.Utility; namespace Content.Shared.Storage.EntitySystems; public abstract class SharedStorageSystem : EntitySystem { - [Dependency] private readonly IConfigurationManager _cfg = default!; - [Dependency] protected readonly IGameTiming Timing = default!; - [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] protected readonly IRobustRandom Random = default!; - [Dependency] private readonly ISharedAdminLogManager _adminLog = default!; - [Dependency] protected readonly ActionBlockerSystem ActionBlocker = default!; - [Dependency] private readonly EntityLookupSystem _entityLookupSystem = default!; - [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; - [Dependency] private readonly InventorySystem _inventory = default!; - [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly EntityLookupSystem _entityLookupSystem = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] protected readonly SharedAudioSystem Audio = default!; - [Dependency] protected readonly SharedContainerSystem ContainerSystem = default!; - [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly SharedContainerSystem _containerSystem = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; [Dependency] protected readonly SharedEntityStorageSystem EntityStorage = default!; - [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; + [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; + [Dependency] private readonly InventorySystem _inventory = default!; [Dependency] protected readonly SharedItemSystem ItemSystem = default!; - [Dependency] private readonly SharedPopupSystem _popupSystem = default!; - [Dependency] private readonly SharedHandsSystem _sharedHandsSystem = default!; - [Dependency] private readonly SharedStackSystem _stack = default!; + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + [Dependency] private readonly SharedHandsSystem _sharedHandsSystem = default!; + [Dependency] private readonly SharedStackSystem _stack = default!; [Dependency] protected readonly SharedTransformSystem TransformSystem = default!; - [Dependency] protected readonly SharedUserInterfaceSystem UI = default!; + [Dependency] private readonly SharedUserInterfaceSystem _ui = default!; [Dependency] protected readonly UseDelaySystem UseDelay = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLog = default!; private EntityQuery _itemQuery; private EntityQuery _stackQuery; private EntityQuery _xformQuery; - private EntityQuery _userQuery; - - /// - /// Whether we're allowed to go up-down storage via UI. - /// - public bool NestedStorage = true; [ValidatePrototypeId] public const string DefaultStorageMaxItemSize = "Normal"; @@ -88,15 +76,10 @@ public abstract class SharedStorageSystem : EntitySystem private ItemSizePrototype _defaultStorageMaxItemSize = default!; - /// - /// Flag for whether we're checking for nested storage interactions. - /// - private bool _nestedCheck; - public bool CheckingCanInsert; - private readonly List _entList = new(); - private readonly HashSet _entSet = new(); + private List _entList = new(); + private HashSet _entSet = new(); private readonly List _sortedSizes = new(); private FrozenDictionary _nextSmallest = FrozenDictionary.Empty; @@ -104,11 +87,6 @@ public abstract class SharedStorageSystem : EntitySystem private const string QuickInsertUseDelayID = "quickInsert"; private const string OpenUiUseDelayID = "storage"; - /// - /// How many storage windows are allowed to be open at once. - /// - private int _openStorageLimit = -1; - protected readonly List CantFillReasons = []; /// @@ -119,11 +97,8 @@ public abstract class SharedStorageSystem : EntitySystem _itemQuery = GetEntityQuery(); _stackQuery = GetEntityQuery(); _xformQuery = GetEntityQuery(); - _userQuery = GetEntityQuery(); _prototype.PrototypesReloaded += OnPrototypesReloaded; - Subs.CVar(_cfg, CCVars.StorageLimit, OnStorageLimitChanged, true); - Subs.BuiEvents(StorageComponent.StorageUiKey.Key, subs => { subs.Event(OnBoundUIClosed); @@ -133,6 +108,7 @@ public abstract class SharedStorageSystem : EntitySystem SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent>(AddUiVerb); SubscribeLocalEvent(OnStorageGetState); + SubscribeLocalEvent(OnStorageHandleState); SubscribeLocalEvent(OnComponentInit, before: new[] { typeof(SharedContainerSystem) }); SubscribeLocalEvent>(AddTransferVerbs); SubscribeLocalEvent(OnInteractUsing, after: new[] { typeof(ItemSlotsSystem) }); @@ -140,7 +116,6 @@ public abstract class SharedStorageSystem : EntitySystem SubscribeLocalEvent(OnImplantActivate); SubscribeLocalEvent(AfterInteract); SubscribeLocalEvent(OnDestroy); - SubscribeLocalEvent(OnBoundUIAttempt); SubscribeLocalEvent(OnBoundUIOpen); SubscribeLocalEvent(OnLockToggled); SubscribeLocalEvent(OnStackCountChanged); @@ -151,8 +126,6 @@ public abstract class SharedStorageSystem : EntitySystem SubscribeLocalEvent(OnDoAfter); - SubscribeAllEvent(OnStorageNested); - SubscribeAllEvent(OnStorageTransfer); SubscribeAllEvent(OnInteractWithItem); SubscribeAllEvent(OnSetItemLocation); SubscribeAllEvent(OnInsertItemIntoLocation); @@ -165,24 +138,12 @@ public abstract class SharedStorageSystem : EntitySystem .Bind(ContentKeyFunctions.OpenBelt, InputCmdHandler.FromDelegate(HandleOpenBelt, handle: false)) .Register(); - Subs.CVar(_cfg, CCVars.NestedStorage, OnNestedStorageCvar, true); - UpdatePrototypeCache(); } - private void OnNestedStorageCvar(bool obj) - { - NestedStorage = obj; - } - - private void OnStorageLimitChanged(int obj) - { - _openStorageLimit = obj; - } - private void OnRemove(Entity entity, ref ComponentRemove args) { - UI.CloseUi(entity.Owner, StorageComponent.StorageUiKey.Key); + _ui.CloseUi(entity.Owner, StorageComponent.StorageUiKey.Key); } private void OnMapInit(Entity entity, ref MapInitEvent args) @@ -211,6 +172,28 @@ public abstract class SharedStorageSystem : EntitySystem }; } + private void OnStorageHandleState(EntityUid uid, StorageComponent component, ref ComponentHandleState args) + { + if (args.Current is not StorageComponentState state) + return; + + component.Grid.Clear(); + component.Grid.AddRange(state.Grid); + component.MaxItemSize = state.MaxItemSize; + component.Whitelist = state.Whitelist; + component.Blacklist = state.Blacklist; + + component.StoredItems.Clear(); + + foreach (var (nent, location) in state.StoredItems) + { + var ent = EnsureEntity(nent, uid); + component.StoredItems[ent] = location; + } + + component.SavedLocations = state.SavedLocations; + } + public override void Shutdown() { _prototype.PrototypesReloaded -= OnPrototypesReloaded; @@ -245,7 +228,7 @@ public abstract class SharedStorageSystem : EntitySystem private void OnComponentInit(EntityUid uid, StorageComponent storageComp, ComponentInit args) { - storageComp.Container = ContainerSystem.EnsureContainer(uid, StorageComponent.ContainerId); + storageComp.Container = _containerSystem.EnsureContainer(uid, StorageComponent.ContainerId); UpdateAppearance((uid, storageComp, null)); } @@ -264,7 +247,7 @@ public abstract class SharedStorageSystem : EntitySystem // close ui foreach (var entity in storageComp.Container.ContainedEntities) { - UI.CloseUis(entity, actor); + _ui.CloseUis(entity, actor); } } @@ -273,7 +256,7 @@ public abstract class SharedStorageSystem : EntitySystem CloseNestedInterfaces(uid, args.Actor, storageComp); // If UI is closed for everyone - if (!UI.IsUiOpen(uid, args.UiKey)) + if (!_ui.IsUiOpen(uid, args.UiKey)) { UpdateAppearance((uid, storageComp, null)); Audio.PlayPredicted(storageComp.StorageCloseSound, uid, args.Actor); @@ -286,7 +269,7 @@ public abstract class SharedStorageSystem : EntitySystem return; // Does this player currently have the storage UI open? - var uiOpen = UI.IsUiOpen(uid, StorageComponent.StorageUiKey.Key, args.User); + var uiOpen = _ui.IsUiOpen(uid, StorageComponent.StorageUiKey.Key, args.User); ActivationVerb verb = new() { @@ -294,7 +277,7 @@ public abstract class SharedStorageSystem : EntitySystem { if (uiOpen) { - UI.CloseUi(uid, StorageComponent.StorageUiKey.Key, args.User); + _ui.CloseUi(uid, StorageComponent.StorageUiKey.Key, args.User); } else { @@ -332,16 +315,16 @@ public abstract class SharedStorageSystem : EntitySystem if (!CanInteract(entity, (uid, storageComp), silent: silent)) return; - if (!UI.TryOpenUi(uid, StorageComponent.StorageUiKey.Key, entity)) - return; - if (!silent) { - Audio.PlayPredicted(storageComp.StorageOpenSound, uid, entity); + if (!_ui.IsUiOpen(uid, StorageComponent.StorageUiKey.Key)) + Audio.PlayPredicted(storageComp.StorageOpenSound, uid, entity); if (useDelay != null) UseDelay.TryResetDelay((uid, useDelay), id: OpenUiUseDelayID); } + + _ui.OpenUi(uid, StorageComponent.StorageUiKey.Key, entity); } public virtual void UpdateUI(Entity entity) {} @@ -401,43 +384,18 @@ public abstract class SharedStorageSystem : EntitySystem return; // Toggle - if (UI.IsUiOpen(uid, StorageComponent.StorageUiKey.Key, args.User)) + if (_ui.IsUiOpen(uid, StorageComponent.StorageUiKey.Key, args.User)) { - UI.CloseUi(uid, StorageComponent.StorageUiKey.Key, args.User); + _ui.CloseUi(uid, StorageComponent.StorageUiKey.Key, args.User); } else { - // Handle recursively opening nested storages. - if (ContainerSystem.TryGetContainingContainer((args.Target, null, null), out var container) && - UI.IsUiOpen(container.Owner, StorageComponent.StorageUiKey.Key, args.User)) - { - _nestedCheck = true; - HideStorageWindow(container.Owner, args.User); - OpenStorageUI(uid, args.User, storageComp, silent: true); - _nestedCheck = false; - } - else - { - // If you need something more sophisticated for multi-UI you'll need to code some smarter - // interactions. - if (_openStorageLimit == 1) - UI.CloseUserUis(args.User); - - OpenStorageUI(uid, args.User, storageComp, silent: false); - } + OpenStorageUI(uid, args.User, storageComp, false); } args.Handled = true; } - protected virtual void HideStorageWindow(EntityUid uid, EntityUid actor) - { - } - - protected virtual void ShowStorageWindow(EntityUid uid, EntityUid actor) - { - } - /// /// Specifically for storage implants. /// @@ -446,10 +404,10 @@ public abstract class SharedStorageSystem : EntitySystem if (args.Handled) return; - var uiOpen = UI.IsUiOpen(uid, StorageComponent.StorageUiKey.Key, args.Performer); + var uiOpen = _ui.IsUiOpen(uid, StorageComponent.StorageUiKey.Key, args.Performer); if (uiOpen) - UI.CloseUi(uid, StorageComponent.StorageUiKey.Key, args.Performer); + _ui.CloseUi(uid, StorageComponent.StorageUiKey.Key, args.Performer); else OpenStorageUI(uid, args.Performer, storageComp, false); @@ -516,7 +474,7 @@ public abstract class SharedStorageSystem : EntitySystem if (args.Target is not { Valid: true } target) return; - if (ContainerSystem.IsEntityInContainer(target) + if (_containerSystem.IsEntityInContainer(target) || target == args.User || !_itemQuery.HasComponent(target)) { @@ -567,7 +525,7 @@ public abstract class SharedStorageSystem : EntitySystem var entity = GetEntity(args.Entities[i]); // Check again, situation may have changed for some entities, but we'll still pick up any that are valid - if (ContainerSystem.IsEntityInContainer(entity) + if (_containerSystem.IsEntityInContainer(entity) || entity == args.Args.User || !_itemQuery.HasComponent(entity)) { @@ -612,7 +570,7 @@ public abstract class SharedStorageSystem : EntitySystem private void OnReclaimed(EntityUid uid, StorageComponent storageComp, GotReclaimedEvent args) { - ContainerSystem.EmptyContainer(storageComp.Container, destination: args.ReclaimerCoordinates); + _containerSystem.EmptyContainer(storageComp.Container, destination: args.ReclaimerCoordinates); } private void OnDestroy(EntityUid uid, StorageComponent storageComp, DestructionEventArgs args) @@ -620,7 +578,7 @@ public abstract class SharedStorageSystem : EntitySystem var coordinates = TransformSystem.GetMoverCoordinates(uid); // Being destroyed so need to recalculate. - ContainerSystem.EmptyContainer(storageComp.Container, destination: coordinates); + _containerSystem.EmptyContainer(storageComp.Container, destination: coordinates); } /// @@ -680,54 +638,6 @@ public abstract class SharedStorageSystem : EntitySystem TrySetItemStorageLocation(item!, storage!, msg.Location); } - private void OnStorageNested(OpenNestedStorageEvent msg, EntitySessionEventArgs args) - { - if (!NestedStorage) - return; - - if (!TryGetEntity(msg.InteractedItemUid, out var itemEnt)) - return; - - _nestedCheck = true; - - var result = ValidateInput(args, - msg.StorageUid, - msg.InteractedItemUid, - out var player, - out var storage, - out var item); - - if (!result) - { - _nestedCheck = false; - return; - } - - HideStorageWindow(storage.Owner, player.Owner); - OpenStorageUI(item.Owner, player.Owner, silent: true); - _nestedCheck = false; - } - - private void OnStorageTransfer(StorageTransferItemEvent msg, EntitySessionEventArgs args) - { - if (!TryGetEntity(msg.ItemEnt, out var itemEnt)) - return; - - var localPlayer = args.SenderSession.AttachedEntity; - - if (!TryComp(localPlayer, out HandsComponent? handsComp) || !_sharedHandsSystem.TryPickup(localPlayer.Value, itemEnt.Value, handsComp: handsComp, animate: false)) - return; - - if (!ValidateInput(args, msg.StorageEnt, msg.ItemEnt, out var player, out var storage, out var item, held: true)) - return; - - _adminLog.Add( - LogType.Storage, - LogImpact.Low, - $"{ToPrettyString(player):player} is inserting {ToPrettyString(item):item} into {ToPrettyString(storage):storage}"); - InsertAt(storage!, item!, msg.Location, out _, player, stackAutomatically: false); - } - private void OnInsertItemIntoLocation(StorageInsertItemIntoLocationEvent msg, EntitySessionEventArgs args) { if (!ValidateInput(args, msg.StorageEnt, msg.ItemEnt, out var player, out var storage, out var item, held: true)) @@ -748,46 +658,9 @@ public abstract class SharedStorageSystem : EntitySystem SaveItemLocation(storage!, item.Owner); } - private void OnBoundUIOpen(Entity ent, ref BoundUIOpenedEvent args) + private void OnBoundUIOpen(EntityUid uid, StorageComponent storageComp, BoundUIOpenedEvent args) { - UpdateAppearance((ent.Owner, ent.Comp, null)); - } - - private void OnBoundUIAttempt(BoundUserInterfaceMessageAttempt args) - { - if (args.UiKey is not StorageComponent.StorageUiKey.Key || - _openStorageLimit == -1 || - _nestedCheck || - args.Message is not OpenBoundInterfaceMessage) - return; - - var uid = args.Target; - var actor = args.Actor; - var count = 0; - - if (_userQuery.TryComp(actor, out var userComp)) - { - foreach (var (ui, keys) in userComp.OpenInterfaces) - { - if (ui == uid) - continue; - - foreach (var key in keys) - { - if (key is not StorageComponent.StorageUiKey) - continue; - - count++; - - if (count >= _openStorageLimit) - { - args.Cancel(); - } - - break; - } - } - } + UpdateAppearance((uid, storageComp, null)); } private void OnEntInserted(Entity entity, ref EntInsertedIntoContainerMessage args) @@ -803,7 +676,7 @@ public abstract class SharedStorageSystem : EntitySystem { if (!TryGetAvailableGridSpace((entity.Owner, entity.Comp), (args.Entity, null), out var location)) { - ContainerSystem.Remove(args.Entity, args.Container, force: true); + _containerSystem.Remove(args.Entity, args.Container, force: true); return; } @@ -865,7 +738,7 @@ public abstract class SharedStorageSystem : EntitySystem var capacity = storage.Grid.GetArea(); var used = GetCumulativeItemAreas((uid, storage)); - var isOpen = UI.IsUiOpen(entity.Owner, StorageComponent.StorageUiKey.Key); + var isOpen = _ui.IsUiOpen(entity.Owner, StorageComponent.StorageUiKey.Key); _appearance.SetData(uid, StorageVisuals.StorageUsed, used, appearance); _appearance.SetData(uid, StorageVisuals.Capacity, capacity, appearance); @@ -975,7 +848,7 @@ public abstract class SharedStorageSystem : EntitySystem } CheckingCanInsert = true; - if (!ContainerSystem.CanInsert(insertEnt, storageComp.Container)) + if (!_containerSystem.CanInsert(insertEnt, storageComp.Container)) { CheckingCanInsert = false; reason = null; @@ -1076,7 +949,7 @@ public abstract class SharedStorageSystem : EntitySystem if (!stackAutomatically || !_stackQuery.TryGetComponent(insertEnt, out var insertStack)) { - if (!ContainerSystem.Insert(insertEnt, storageComp.Container)) + if (!_containerSystem.Insert(insertEnt, storageComp.Container)) return false; if (playSound) @@ -1102,7 +975,7 @@ public abstract class SharedStorageSystem : EntitySystem // Still stackable remaining if (insertStack.Count > 0 - && !ContainerSystem.Insert(insertEnt, storageComp.Container) + && !_containerSystem.Insert(insertEnt, storageComp.Container) && toInsertCount == insertStack.Count) { // Failed to insert anything. @@ -1181,7 +1054,6 @@ public abstract class SharedStorageSystem : EntitySystem return false; storageEnt.Comp.StoredItems[itemEnt] = location; - UpdateUI(storageEnt); Dirty(storageEnt, storageEnt.Comp); return true; } @@ -1485,16 +1357,16 @@ public abstract class SharedStorageSystem : EntitySystem return; // Gets everyone looking at the UI - foreach (var actor in UI.GetActors(uid, StorageComponent.StorageUiKey.Key).ToList()) + foreach (var actor in _ui.GetActors(uid, StorageComponent.StorageUiKey.Key).ToList()) { if (!CanInteract(actor, (uid, component))) - UI.CloseUi(uid, StorageComponent.StorageUiKey.Key, actor); + _ui.CloseUi(uid, StorageComponent.StorageUiKey.Key, actor); } } private void OnStackCountChanged(EntityUid uid, MetaDataComponent component, StackCountChangedEvent args) { - if (ContainerSystem.TryGetContainingContainer((uid, null, component), out var container) && + if (_containerSystem.TryGetContainingContainer((uid, null, component), out var container) && container.ID == StorageComponent.ContainerId) { UpdateAppearance(container.Owner); @@ -1526,13 +1398,13 @@ public abstract class SharedStorageSystem : EntitySystem if (!ActionBlocker.CanInteract(playerEnt, storageEnt)) return; - if (!UI.IsUiOpen(storageEnt.Value, StorageComponent.StorageUiKey.Key, playerEnt)) + if (!_ui.IsUiOpen(storageEnt.Value, StorageComponent.StorageUiKey.Key, playerEnt)) { OpenStorageUI(storageEnt.Value, playerEnt, silent: false); } else { - UI.CloseUi(storageEnt.Value, StorageComponent.StorageUiKey.Key, playerEnt); + _ui.CloseUi(storageEnt.Value, StorageComponent.StorageUiKey.Key, playerEnt); } } @@ -1587,7 +1459,7 @@ public abstract class SharedStorageSystem : EntitySystem // TODO STORAGE use BUI events // This would automatically validate that the UI is open & that the user can interact. // However, we still need to manually validate that items being used are in the users hands or in the storage. - if (!UI.IsUiOpen(storageUid.Value, StorageComponent.StorageUiKey.Key, playerUid)) + if (!_ui.IsUiOpen(storageUid.Value, StorageComponent.StorageUiKey.Key, playerUid)) return false; if (!ActionBlocker.CanInteract(playerUid, storageUid)) diff --git a/Content.Shared/Storage/StorageComponent.cs b/Content.Shared/Storage/StorageComponent.cs index c59f7ab00e..52547454a0 100644 --- a/Content.Shared/Storage/StorageComponent.cs +++ b/Content.Shared/Storage/StorageComponent.cs @@ -148,19 +148,6 @@ namespace Content.Shared.Storage } } - [Serializable, NetSerializable] - public sealed class OpenNestedStorageEvent : EntityEventArgs - { - public readonly NetEntity InteractedItemUid; - public readonly NetEntity StorageUid; - - public OpenNestedStorageEvent(NetEntity interactedItemUid, NetEntity storageUid) - { - InteractedItemUid = interactedItemUid; - StorageUid = storageUid; - } - } - [Serializable, NetSerializable] public sealed class StorageInteractWithItemEvent : EntityEventArgs { @@ -192,26 +179,6 @@ namespace Content.Shared.Storage } } - [Serializable, NetSerializable] - public sealed class StorageTransferItemEvent : EntityEventArgs - { - public readonly NetEntity ItemEnt; - - /// - /// Target storage to receive the transfer. - /// - public readonly NetEntity StorageEnt; - - public readonly ItemStorageLocation Location; - - public StorageTransferItemEvent(NetEntity itemEnt, NetEntity storageEnt, ItemStorageLocation location) - { - ItemEnt = itemEnt; - StorageEnt = storageEnt; - Location = location; - } - } - [Serializable, NetSerializable] public sealed class StorageInsertItemIntoLocationEvent : EntityEventArgs {