]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Storage fixes (#36533)
authormetalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Fri, 18 Apr 2025 02:11:31 +0000 (12:11 +1000)
committerGitHub <noreply@github.com>
Fri, 18 Apr 2025 02:11:31 +0000 (12:11 +1000)
* Storage fixes

- Add size event.
- Fix reclaim not running always.

* Block the toggles

* Standardise and popup explaining

* Disable item toggles in bags

* Fix verb popping up even if we can't activate

* Conflicts

* Validate

* Stop drags if source closes

* Really fixes

* Real fix

* Revert this

Content.Client/UserInterface/Systems/Storage/StorageUIController.cs
Content.Shared/Item/ItemSizeChangedEvent.cs [new file with mode: 0644]
Content.Shared/Item/ItemToggle/Components/ItemToggleComponent.cs
Content.Shared/Item/ItemToggle/Components/ItemToggleSizeComponent.cs
Content.Shared/Item/ItemToggle/ItemToggleSystem.cs
Content.Shared/Item/SharedItemSystem.cs
Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs
Resources/Locale/en-US/items/toggle.ftl

index f0c8cfeb2150ae35b56a728e9ab778d2abf24eac..ca2bc5729b48b2ac3832218575bb7fc49bc2f5e8 100644 (file)
@@ -269,12 +269,19 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
                 var position = targetStorage.GetMouseGridPieceLocation(dragEnt, dragLoc);
                 var newLocation = new ItemStorageLocation(DraggingRotation, position);
 
-                EntityManager.RaisePredictiveEvent(new StorageSetItemLocationEvent(
-                    EntityManager.GetNetEntity(draggingGhost.Entity),
-                    EntityManager.GetNetEntity(sourceStorage),
-                    newLocation));
+                if (!_storage.ItemFitsInGridLocation(dragEnt, sourceStorage, newLocation))
+                {
+                    window.Reclaim(control.Location, control);
+                }
+                else
+                {
+                    EntityManager.RaisePredictiveEvent(new StorageSetItemLocationEvent(
+                        EntityManager.GetNetEntity(draggingGhost.Entity),
+                        EntityManager.GetNetEntity(sourceStorage),
+                        newLocation));
 
-                window.Reclaim(newLocation, control);
+                    window.Reclaim(newLocation, control);
+                }
             }
             // Dragging to new storage
             else if (targetStorage?.StorageEntity != null && targetStorage != window)
@@ -336,6 +343,17 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
         if (DraggingGhost == null)
             return false;
 
+        var player = _player.LocalEntity;
+
+        // If the attached storage is closed then stop dragging
+        if (player == null ||
+            !_storage.TryGetStorageLocation(DraggingGhost.Entity, out var container, out _, out _) ||
+            !_ui.IsUiOpen(container.Owner, StorageComponent.StorageUiKey.Key, player.Value))
+        {
+            DraggingGhost.Orphan();
+            return false;
+        }
+
         SetDraggingRotation();
         return true;
     }
diff --git a/Content.Shared/Item/ItemSizeChangedEvent.cs b/Content.Shared/Item/ItemSizeChangedEvent.cs
new file mode 100644 (file)
index 0000000..b7c7d0b
--- /dev/null
@@ -0,0 +1,10 @@
+namespace Content.Shared.Item;
+
+/// <summary>
+/// Raised directed on an entity when its item size / shape changes.
+/// </summary>
+[ByRefEvent]
+public struct ItemSizeChangedEvent(EntityUid Entity)
+{
+    public EntityUid Entity = Entity;
+}
index 110ae80626e32f732675c38f3c3c13b29f74836a..cb6470f5d63202acf3bd76e6b06dead9924395e0 100644 (file)
@@ -78,13 +78,18 @@ public sealed partial class ItemToggleComponent : Component
 [ByRefEvent]
 public record struct ItemToggleActivateAttemptEvent(EntityUid? User)
 {
+    /// <summary>
+    /// Should we silently fail.
+    /// </summary>
+    public bool Silent = false;
+
     public bool Cancelled = false;
     public readonly EntityUid? User = User;
 
     /// <summary>
     /// Pop-up that gets shown to users explaining why the attempt was cancelled.
     /// </summary>
-    public string? Popup { get; set; }
+    public string? Popup;
 }
 
 /// <summary>
@@ -93,8 +98,18 @@ public record struct ItemToggleActivateAttemptEvent(EntityUid? User)
 [ByRefEvent]
 public record struct ItemToggleDeactivateAttemptEvent(EntityUid? User)
 {
+    /// <summary>
+    /// Should we silently fail.
+    /// </summary>
+    public bool Silent = false;
+
     public bool Cancelled = false;
     public readonly EntityUid? User = User;
+
+    /// <summary>
+    /// Pop-up that gets shown to users explaining why the attempt was cancelled.
+    /// </summary>
+    public string? Popup;
 }
 
 /// <summary>
index b7b47a073223c49d23bca58f16214ca89880d75a..2870f9ef011e5d1c06e38e5185551468f757bf44 100644 (file)
@@ -15,24 +15,24 @@ public sealed partial class ItemToggleSizeComponent : Component
     /// <summary>
     ///     Item's size when activated
     /// </summary>
-    [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+    [DataField, AutoNetworkedField]
     public ProtoId<ItemSizePrototype>? ActivatedSize = null;
 
     /// <summary>
     ///     Item's shape when activated
     /// </summary>
-    [ViewVariables(VVAccess.ReadWrite), DataField]
+    [DataField, AutoNetworkedField]
     public List<Box2i>? ActivatedShape = null;
 
     /// <summary>
     ///     Item's size when deactivated. If none is mentioned, it uses the item's default size instead.
     /// </summary>
-    [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+    [DataField, AutoNetworkedField]
     public ProtoId<ItemSizePrototype>? DeactivatedSize = null;
 
     /// <summary>
     ///     Item's shape when deactivated. If none is mentioned, it uses the item's default shape instead.
     /// </summary>
-    [ViewVariables(VVAccess.ReadWrite), DataField]
+    [DataField, AutoNetworkedField]
     public List<Box2i>? DeactivatedShape = null;
 }
index f6752a67f61b03ea294e65eccfd4e3b923c74d7f..819975ecda5e37a4c75ab856990e94b70a03b9eb 100644 (file)
@@ -76,6 +76,23 @@ public sealed class ItemToggleSystem : EntitySystem
 
         var user = args.User;
 
+        if (ent.Comp.Activated)
+        {
+            var ev = new ItemToggleActivateAttemptEvent(args.User);
+            RaiseLocalEvent(ent.Owner, ref ev);
+
+            if (ev.Cancelled)
+                return;
+        }
+        else
+        {
+            var ev = new ItemToggleDeactivateAttemptEvent(args.User);
+            RaiseLocalEvent(ent.Owner, ref ev);
+
+            if (ev.Cancelled)
+                return;
+        }
+
         args.Verbs.Add(new ActivationVerb()
         {
             Text = !ent.Comp.Activated ? Loc.GetString(ent.Comp.VerbToggleOn) : Loc.GetString(ent.Comp.VerbToggleOff),
@@ -133,15 +150,20 @@ public sealed class ItemToggleSystem : EntitySystem
         if (comp.Activated)
             return true;
 
-        if (!comp.Predictable && _netManager.IsClient)
-            return true;
-
         var attempt = new ItemToggleActivateAttemptEvent(user);
         RaiseLocalEvent(uid, ref attempt);
 
-        if (!comp.Predictable) predicted = false;
+        if (!comp.Predictable)
+            predicted = false;
+
+        if (!predicted && _netManager.IsClient)
+            return false;
+
         if (attempt.Cancelled)
         {
+            if (attempt.Silent)
+                return false;
+
             if (predicted)
                 _audio.PlayPredicted(comp.SoundFailToActivate, uid, user);
             else
@@ -159,7 +181,6 @@ public sealed class ItemToggleSystem : EntitySystem
         }
 
         Activate((uid, comp), predicted, user);
-
         return true;
     }
 
@@ -176,16 +197,31 @@ public sealed class ItemToggleSystem : EntitySystem
         if (!comp.Activated)
             return true;
 
-        if (!comp.Predictable && _netManager.IsClient)
-            return true;
+        if (!comp.Predictable)
+            predicted = false;
 
         var attempt = new ItemToggleDeactivateAttemptEvent(user);
         RaiseLocalEvent(uid, ref attempt);
 
+        if (!predicted && _netManager.IsClient)
+            return false;
+
         if (attempt.Cancelled)
+        {
+            if (attempt.Silent)
+                return false;
+
+            if (attempt.Popup != null && user != null)
+            {
+                if (predicted)
+                    _popup.PopupClient(attempt.Popup, uid, user.Value);
+                else
+                    _popup.PopupEntity(attempt.Popup, uid, user.Value);
+            }
+
             return false;
+        }
 
-        if (!comp.Predictable) predicted = false;
         Deactivate((uid, comp), predicted, user);
         return true;
     }
index 8ba26fd3495ebfd288b9d16682a1b7c455cc638a..18a98c7a0c9cbfb2cee9517f55dd2baf3708ee25 100644 (file)
@@ -39,20 +39,24 @@ public abstract class SharedItemSystem : EntitySystem
 
     public void SetSize(EntityUid uid, ProtoId<ItemSizePrototype> size, ItemComponent? component = null)
     {
-        if (!Resolve(uid, ref component, false))
+        if (!Resolve(uid, ref component, false) || component.Size == size)
             return;
 
         component.Size = size;
         Dirty(uid, component);
+        var ev = new ItemSizeChangedEvent(uid);
+        RaiseLocalEvent(uid, ref ev, broadcast: true);
     }
 
     public void SetShape(EntityUid uid, List<Box2i>? shape, ItemComponent? component = null)
     {
-        if (!Resolve(uid, ref component, false))
+        if (!Resolve(uid, ref component, false) || component.Shape == shape)
             return;
 
         component.Shape = shape;
         Dirty(uid, component);
+        var ev = new ItemSizeChangedEvent(uid);
+        RaiseLocalEvent(uid, ref ev, broadcast: true);
     }
 
     /// <summary>
@@ -236,6 +240,7 @@ public abstract class SharedItemSystem : EntitySystem
             {
                 // Set the deactivated shape to the default item's shape before it gets changed.
                 itemToggleSize.DeactivatedShape ??= new List<Box2i>(GetItemShape(item));
+                Dirty(uid, itemToggleSize);
                 SetShape(uid, itemToggleSize.ActivatedShape, item);
             }
 
@@ -243,6 +248,7 @@ public abstract class SharedItemSystem : EntitySystem
             {
                 // Set the deactivated size to the default item's size before it gets changed.
                 itemToggleSize.DeactivatedSize ??= item.Size;
+                Dirty(uid, itemToggleSize);
                 SetSize(uid, (ProtoId<ItemSizePrototype>) itemToggleSize.ActivatedSize, item);
             }
         }
@@ -258,7 +264,5 @@ public abstract class SharedItemSystem : EntitySystem
                 SetSize(uid, (ProtoId<ItemSizePrototype>) itemToggleSize.DeactivatedSize, item);
             }
         }
-
-        Dirty(uid, item);
     }
 }
index 3bf51f79579efc3f7bebacd1b6f615a9edfd17ae..e9ed89f5605d8590bada7a7dce359e1efef79a89 100644 (file)
@@ -16,6 +16,7 @@ using Content.Shared.Interaction;
 using Content.Shared.Interaction.Components;
 using Content.Shared.Inventory;
 using Content.Shared.Item;
+using Content.Shared.Item.ItemToggle.Components;
 using Content.Shared.Lock;
 using Content.Shared.Materials;
 using Content.Shared.Placeable;
@@ -146,13 +147,13 @@ public abstract class SharedStorageSystem : EntitySystem
         SubscribeLocalEvent<StorageComponent, BoundUserInterfaceMessageAttempt>(OnBoundUIAttempt);
         SubscribeLocalEvent<StorageComponent, BoundUIOpenedEvent>(OnBoundUIOpen);
         SubscribeLocalEvent<StorageComponent, LockToggledEvent>(OnLockToggled);
-        SubscribeLocalEvent<MetaDataComponent, StackCountChangedEvent>(OnStackCountChanged);
-
         SubscribeLocalEvent<StorageComponent, EntInsertedIntoContainerMessage>(OnEntInserted);
         SubscribeLocalEvent<StorageComponent, EntRemovedFromContainerMessage>(OnEntRemoved);
         SubscribeLocalEvent<StorageComponent, ContainerIsInsertingAttemptEvent>(OnInsertAttempt);
-
         SubscribeLocalEvent<StorageComponent, AreaPickupDoAfterEvent>(OnDoAfter);
+        SubscribeLocalEvent<StorageComponent, GotReclaimedEvent>(OnReclaimed);
+
+        SubscribeLocalEvent<MetaDataComponent, StackCountChangedEvent>(OnStackCountChanged);
 
         SubscribeAllEvent<OpenNestedStorageEvent>(OnStorageNested);
         SubscribeAllEvent<StorageTransferItemEvent>(OnStorageTransfer);
@@ -161,7 +162,7 @@ public abstract class SharedStorageSystem : EntitySystem
         SubscribeAllEvent<StorageInsertItemIntoLocationEvent>(OnInsertItemIntoLocation);
         SubscribeAllEvent<StorageSaveItemLocationEvent>(OnSaveItemLocation);
 
-        SubscribeLocalEvent<StorageComponent, GotReclaimedEvent>(OnReclaimed);
+        SubscribeLocalEvent<ItemSizeChangedEvent>(OnItemSizeChanged);
 
         CommandBinds.Builder
             .Bind(ContentKeyFunctions.OpenBackpack, InputCmdHandler.FromDelegate(HandleOpenBackpack, handle: false))
@@ -173,6 +174,21 @@ public abstract class SharedStorageSystem : EntitySystem
         UpdatePrototypeCache();
     }
 
+    private void OnItemSizeChanged(ref ItemSizeChangedEvent ev)
+    {
+        var itemEnt = new Entity<ItemComponent?>(ev.Entity, null);
+
+        if (!TryGetStorageLocation(itemEnt, out var container, out var storage, out var loc))
+        {
+            return;
+        }
+
+        if (!ItemFitsInGridLocation((itemEnt.Owner, itemEnt.Comp), (container.Owner, storage), loc))
+        {
+            ContainerSystem.Remove(itemEnt.Owner, container, force: true);
+        }
+    }
+
     private void OnNestedStorageCvar(bool obj)
     {
         NestedStorage = obj;
@@ -322,6 +338,25 @@ public abstract class SharedStorageSystem : EntitySystem
         args.Verbs.Add(verb);
     }
 
+    /// <summary>
+    /// Tries to get the storage location of an item.
+    /// </summary>
+    public bool TryGetStorageLocation(Entity<ItemComponent?> itemEnt, [NotNullWhen(true)] out BaseContainer? container, out StorageComponent? storage, out ItemStorageLocation loc)
+    {
+        loc = default;
+        storage = null;
+
+        if (!ContainerSystem.TryGetContainingContainer(itemEnt, out container) ||
+            !TryComp(container.Owner, out storage) ||
+            !_itemQuery.Resolve(itemEnt, ref itemEnt.Comp, false))
+        {
+            return false;
+        }
+
+        loc = storage.StoredItems[itemEnt];
+        return true;
+    }
+
     public void OpenStorageUI(EntityUid uid, EntityUid actor, StorageComponent? storageComp = null, bool silent = true)
     {
         // Handle recursively opening nested storages.
@@ -719,14 +754,23 @@ public abstract class SharedStorageSystem : EntitySystem
 
     private void OnStorageTransfer(StorageTransferItemEvent msg, EntitySessionEventArgs args)
     {
-        if (!TryGetEntity(msg.ItemEnt, out var itemEnt))
+        if (!TryGetEntity(msg.ItemEnt, out var itemUid) || !TryComp(itemUid, out ItemComponent? itemComp))
             return;
 
         var localPlayer = args.SenderSession.AttachedEntity;
+        var itemEnt = new Entity<ItemComponent?>(itemUid.Value, itemComp);
+
+        // Validate the source storage
+        if (!TryGetStorageLocation(itemEnt, out var container, out _, out _) ||
+            !ValidateInput(args, GetNetEntity(container.Owner), out _, out _))
+        {
+            return;
+        }
 
-        if (!TryComp(localPlayer, out HandsComponent? handsComp) || !_sharedHandsSystem.TryPickup(localPlayer.Value, itemEnt.Value, handsComp: handsComp, animate: false))
+        if (!TryComp(localPlayer, out HandsComponent? handsComp) || !_sharedHandsSystem.TryPickup(localPlayer.Value, itemEnt, handsComp: handsComp, animate: false))
             return;
 
+        // Validate the target storage
         if (!ValidateInput(args, msg.StorageEnt, msg.ItemEnt, out var player, out var storage, out var item, held: true))
             return;
 
@@ -1525,6 +1569,8 @@ public abstract class SharedStorageSystem : EntitySystem
         }
     }
 
+
+
     private void HandleOpenBackpack(ICommonSession? session)
     {
         HandleToggleSlotUI(session, "back");
index bcf5c161a6f37e6ee005db1fd8cbb76136a7b608..7f5dfea7c62936f81992c83e61c723aa3788cb1e 100644 (file)
@@ -1,2 +1,4 @@
 item-toggle-activate = Activate
 item-toggle-deactivate = Deactivate
+
+item-toggle-size-fail = Doesn't fit.