]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Virtual items cleanup (#23912)
authorAJCM-git <60196617+AJCM-git@users.noreply.github.com>
Sun, 14 Jan 2024 10:18:47 +0000 (06:18 -0400)
committerGitHub <noreply@github.com>
Sun, 14 Jan 2024 10:18:47 +0000 (21:18 +1100)
* Virtual items cleanup

* Detail

* Review

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
27 files changed:
Content.Client/Hands/Systems/HandVirtualItemSystem.cs [deleted file]
Content.Client/Hands/Systems/HandsSystem.cs
Content.Client/Inventory/StrippableBoundUserInterface.cs
Content.Client/Inventory/VirtualItemSystem.cs [new file with mode: 0644]
Content.Client/UserInterface/Systems/Hands/HandsUIController.cs
Content.Client/UserInterface/Systems/Inventory/Controls/ItemStatusPanel.xaml.cs
Content.Client/UserInterface/Systems/Inventory/InventoryUIController.cs
Content.IntegrationTests/Tests/Sprite/ItemSpriteTest.cs
Content.Server/Hands/Systems/HandVirtualItemSystem.cs [deleted file]
Content.Server/Hands/Systems/HandsSystem.cs
Content.Server/Inventory/VirtualItemSystem.cs [new file with mode: 0644]
Content.Server/Item/MultiHandedItemSystem.cs
Content.Server/Strip/StrippableSystem.cs
Content.Server/Verbs/VerbSystem.cs
Content.Shared/Cuffs/SharedCuffableSystem.cs
Content.Shared/Hands/Components/HandVirtualItemComponent.cs [deleted file]
Content.Shared/Hands/EntitySystems/SharedHandsSystem.Drop.cs
Content.Shared/Hands/EntitySystems/SharedHandsSystem.Interactions.cs
Content.Shared/Hands/EntitySystems/SharedHandsSystem.Virtual.cs [deleted file]
Content.Shared/Hands/EntitySystems/SharedHandsSystem.cs
Content.Shared/Hands/SharedHandVirtualItemSystem.cs [deleted file]
Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs [new file with mode: 0644]
Content.Shared/Inventory/VirtualItem/VirtualItemComponent.cs [new file with mode: 0644]
Content.Shared/Vehicle/SharedVehicleSystem.cs
Content.Shared/Verbs/SharedVerbSystem.cs
Content.Shared/Wieldable/WieldableSystem.cs
Resources/Prototypes/Entities/Virtual/virtual_item.yml

diff --git a/Content.Client/Hands/Systems/HandVirtualItemSystem.cs b/Content.Client/Hands/Systems/HandVirtualItemSystem.cs
deleted file mode 100644 (file)
index 496b8ce..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-using Content.Client.Hands.UI;
-using Content.Client.Items;
-using Content.Shared.Hands;
-using Content.Shared.Hands.Components;
-using JetBrains.Annotations;
-using Robust.Shared.GameObjects;
-
-namespace Content.Client.Hands.Systems
-{
-    [UsedImplicitly]
-    public sealed class HandVirtualItemSystem : SharedHandVirtualItemSystem
-    {
-        public override void Initialize()
-        {
-            base.Initialize();
-
-            Subs.ItemStatus<HandVirtualItemComponent>(_ => new HandVirtualItemStatus());
-        }
-    }
-}
index b403c66dd73350ede1b9d537579e0e9780615d1b..9ea094a73abc8239ede9212711630654298ff48d 100644 (file)
@@ -6,6 +6,7 @@ using Content.Client.Verbs.UI;
 using Content.Shared.Hands;
 using Content.Shared.Hands.Components;
 using Content.Shared.Hands.EntitySystems;
+using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Item;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
@@ -252,7 +253,7 @@ namespace Content.Client.Hands.Systems
 
             OnPlayerItemAdded?.Invoke(hand.Name, args.Entity);
 
-            if (HasComp<HandVirtualItemComponent>(args.Entity))
+            if (HasComp<VirtualItemComponent>(args.Entity))
                 OnPlayerHandBlocked?.Invoke(hand.Name);
         }
 
@@ -270,7 +271,7 @@ namespace Content.Client.Hands.Systems
 
             OnPlayerItemRemoved?.Invoke(hand.Name, args.Entity);
 
-            if (HasComp<HandVirtualItemComponent>(args.Entity))
+            if (HasComp<VirtualItemComponent>(args.Entity))
                 OnPlayerHandUnblocked?.Invoke(hand.Name);
         }
 
index 9fbb64309fbb098eebc278e2e6642ebd3125b0e2..028c035e8a78f4193503142fab9ee29cfeb2312a 100644 (file)
@@ -13,6 +13,7 @@ using Content.Shared.Hands.Components;
 using Content.Shared.IdentityManagement;
 using Content.Shared.Input;
 using Content.Shared.Inventory;
+using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Strip.Components;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
@@ -159,7 +160,7 @@ namespace Content.Client.Inventory
 
             button.Pressed += SlotPressed;
 
-            if (EntMan.TryGetComponent<HandVirtualItemComponent>(hand.HeldEntity, out var virt))
+            if (EntMan.TryGetComponent<VirtualItemComponent>(hand.HeldEntity, out var virt))
             {
                 button.Blocked = true;
                 if (EntMan.TryGetComponent<CuffableComponent>(Owner, out var cuff) && _cuffable.GetAllCuffs(cuff).Contains(virt.BlockingEntity))
@@ -224,7 +225,7 @@ namespace Content.Client.Inventory
             }
 
             EntityUid? viewEnt;
-            if (EntMan.TryGetComponent<HandVirtualItemComponent>(entity, out var virt))
+            if (EntMan.TryGetComponent<VirtualItemComponent>(entity, out var virt))
                 viewEnt = EntMan.HasComponent<SpriteComponent>(virt.BlockingEntity) ? virt.BlockingEntity : null;
             else if (EntMan.HasComponent<SpriteComponent>(entity))
                 viewEnt = entity;
diff --git a/Content.Client/Inventory/VirtualItemSystem.cs b/Content.Client/Inventory/VirtualItemSystem.cs
new file mode 100644 (file)
index 0000000..721aa11
--- /dev/null
@@ -0,0 +1,15 @@
+using Content.Client.Hands.UI;
+using Content.Client.Items;
+using Content.Shared.Inventory.VirtualItem;
+
+namespace Content.Client.Inventory;
+
+public sealed class VirtualItemSystem : SharedVirtualItemSystem
+{
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        Subs.ItemStatus<VirtualItemComponent>(_ => new HandVirtualItemStatus());
+    }
+}
index b82bcad470a7f1ba3286def1346e46c36d0eb892..1bcdd89af627f46f1d4742c52f36d30b32743ab3 100644 (file)
@@ -5,6 +5,7 @@ using Content.Client.UserInterface.Systems.Hands.Controls;
 using Content.Client.UserInterface.Systems.Hotbar.Widgets;
 using Content.Shared.Hands.Components;
 using Content.Shared.Input;
+using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Timing;
 using Robust.Client.Player;
 using Robust.Client.UserInterface;
@@ -117,7 +118,7 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
         {
             var handButton = AddHand(name, hand.Location);
 
-            if (_entities.TryGetComponent(hand.HeldEntity, out HandVirtualItemComponent? virt))
+            if (_entities.TryGetComponent(hand.HeldEntity, out VirtualItemComponent? virt))
             {
                 handButton.SpriteView.SetEntity(virt.BlockingEntity);
                 handButton.Blocked = true;
@@ -168,7 +169,7 @@ public sealed class HandsUIController : UIController, IOnStateEntered<GameplaySt
         if (hand == null)
             return;
 
-        if (_entities.TryGetComponent(entity, out HandVirtualItemComponent? virt))
+        if (_entities.TryGetComponent(entity, out VirtualItemComponent? virt))
         {
             hand.SpriteView.SetEntity(virt.BlockingEntity);
             hand.Blocked = true;
index 60582df0cfc1547e0e75af5cda58a51413498b93..90ae571711d91af2eea8b996c71eb740d61884fb 100644 (file)
@@ -2,6 +2,7 @@ using Content.Client.Items;
 using Content.Client.Resources;
 using Content.Shared.Hands.Components;
 using Content.Shared.IdentityManagement;
+using Content.Shared.Inventory.VirtualItem;
 using Robust.Client.AutoGenerated;
 using Robust.Client.Graphics;
 using Robust.Client.UserInterface.Controls;
@@ -104,7 +105,7 @@ public sealed partial class ItemStatusPanel : BoxContainer
             return;
         }
 
-        if (_entityManager.TryGetComponent(_entity, out HandVirtualItemComponent? virtualItem)
+        if (_entityManager.TryGetComponent(_entity, out VirtualItemComponent? virtualItem)
             && _entityManager.EntityExists(virtualItem.BlockingEntity))
         {
             // Uses identity because we can be blocked by pulling someone
index 5b461c76887c39b53aa6c3efcf704133c04f888e..ad007be5fb056e830c7140f46b7b21caf91f6901 100644 (file)
@@ -12,6 +12,7 @@ using Content.Client.UserInterface.Systems.Inventory.Windows;
 using Content.Shared.Containers.ItemSlots;
 using Content.Shared.Hands.Components;
 using Content.Shared.Input;
+using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Storage;
 using Robust.Client.GameObjects;
 using Robust.Client.UserInterface;
@@ -423,8 +424,17 @@ public sealed class InventoryUIController : UIController, IOnStateEntered<Gamepl
         if (_slotGroups.GetValueOrDefault(group)?.GetButton(name) is not { } button)
             return;
 
-        button.SpriteView.SetEntity(entity);
-        button.StorageButton.Visible = showStorage;
+        if (_entities.TryGetComponent(entity, out VirtualItemComponent? virtb))
+        {
+            button.SpriteView.SetEntity(virtb.BlockingEntity);
+            button.Blocked = true;
+        }
+        else
+        {
+            button.SpriteView.SetEntity(entity);
+            button.Blocked = false;
+            button.StorageButton.Visible = showStorage;
+        }
     }
 
     public bool RegisterSlotGroupContainer(ItemSlotButtonContainer slotContainer)
index 96f710d4681881e558a58aa95a1d56abba7ebb89..1762c4213c415960b47d1d95af25dec460d8ceb7 100644 (file)
@@ -28,7 +28,7 @@ public sealed class PrototypeSaveTest
     {
         // The only prototypes that should get ignored are those that REQUIRE setup to get a sprite. At that point it is
         // the responsibility of the spawner to ensure that a valid sprite is set.
-        "HandVirtualItem"
+        "VirtualItem"
     };
 
     [Test]
diff --git a/Content.Server/Hands/Systems/HandVirtualItemSystem.cs b/Content.Server/Hands/Systems/HandVirtualItemSystem.cs
deleted file mode 100644 (file)
index 6d20420..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-using Content.Shared.Hands;
-using Content.Shared.Hands.Components;
-using Content.Shared.Hands.EntitySystems;
-using JetBrains.Annotations;
-using System.Diagnostics.CodeAnalysis;
-
-namespace Content.Server.Hands.Systems
-{
-    [UsedImplicitly]
-    public sealed class HandVirtualItemSystem : SharedHandVirtualItemSystem
-    {
-
-    }
-}
index 0b2180065321d0caa256a100be5c9c34fe315d03..9d664d0f9a02909eabfefe19c35f26511a3e5c4a 100644 (file)
@@ -1,4 +1,5 @@
 using System.Numerics;
+using Content.Server.Inventory;
 using Content.Server.Pulling;
 using Content.Server.Stack;
 using Content.Server.Stunnable;
@@ -9,6 +10,7 @@ using Content.Shared.Explosion;
 using Content.Shared.Hands.Components;
 using Content.Shared.Hands.EntitySystems;
 using Content.Shared.Input;
+using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Physics.Pull;
 using Content.Shared.Pulling.Components;
 using Content.Shared.Stacks;
@@ -26,7 +28,7 @@ namespace Content.Server.Hands.Systems
     {
         [Dependency] private readonly IGameTiming _timing = default!;
         [Dependency] private readonly StackSystem _stackSystem = default!;
-        [Dependency] private readonly HandVirtualItemSystem _virtualItemSystem = default!;
+        [Dependency] private readonly VirtualItemSystem _virtualItemSystem = default!;
         [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
         [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
         [Dependency] private readonly PullingSystem _pullingSystem = default!;
@@ -148,7 +150,7 @@ namespace Content.Server.Hands.Systems
             foreach (var hand in component.Hands.Values)
             {
                 if (hand.HeldEntity == null
-                    || !TryComp(hand.HeldEntity, out HandVirtualItemComponent? virtualItem)
+                    || !TryComp(hand.HeldEntity, out VirtualItemComponent? virtualItem)
                     || virtualItem.BlockingEntity != args.Pulled.Owner)
                     continue;
 
diff --git a/Content.Server/Inventory/VirtualItemSystem.cs b/Content.Server/Inventory/VirtualItemSystem.cs
new file mode 100644 (file)
index 0000000..922c456
--- /dev/null
@@ -0,0 +1,9 @@
+using Content.Shared.Hands;
+using Content.Shared.Inventory.VirtualItem;
+
+namespace Content.Server.Inventory;
+
+public sealed class VirtualItemSystem : SharedVirtualItemSystem
+{
+
+}
index 3dc213e1fca22ec4c952c0dea7951047ba394ee3..9146c7c98241e2e53f6202c1c7d14592a263de82 100644 (file)
@@ -1,4 +1,5 @@
 using Content.Server.Hands.Systems;
+using Content.Server.Inventory;
 using Content.Shared.Hands;
 using Content.Shared.Item;
 
@@ -6,7 +7,7 @@ namespace Content.Server.Item;
 
 public sealed class MultiHandedItemSystem : SharedMultiHandedItemSystem
 {
-    [Dependency] private readonly HandVirtualItemSystem _virtualItem = default!;
+    [Dependency] private readonly VirtualItemSystem _virtualItem = default!;
 
     protected override void OnEquipped(EntityUid uid, MultiHandedItemComponent component, GotEquippedHandEvent args)
     {
index b354f9071adadc39a3b5aafe9665f3b532c01e50..89eb202b25e83e4bf746ec4b4896a6b4bcdd097c 100644 (file)
@@ -13,6 +13,7 @@ using Content.Shared.IdentityManagement;
 using Content.Shared.Interaction;
 using Content.Shared.Interaction.Events;
 using Content.Shared.Inventory;
+using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Popups;
 using Content.Shared.Strip;
 using Content.Shared.Strip.Components;
@@ -93,7 +94,7 @@ namespace Content.Server.Strip
                 return;
 
             // is the target a handcuff?
-            if (TryComp(hand.HeldEntity, out HandVirtualItemComponent? virt)
+            if (TryComp(hand.HeldEntity, out VirtualItemComponent? virt)
                 && TryComp(target, out CuffableComponent? cuff)
                 && _cuffable.GetAllCuffs(cuff).Contains(virt.BlockingEntity))
             {
@@ -413,7 +414,7 @@ namespace Content.Server.Strip
                     return false;
                 }
 
-                if (HasComp<HandVirtualItemComponent>(hand.HeldEntity))
+                if (HasComp<VirtualItemComponent>(hand.HeldEntity))
                     return false;
 
                 if (!_handsSystem.CanDropHeld(target, hand, false))
index e304c6b4af07393fbc5ab6069504a9647ce8378f..114c62a0ce2f607f8e037849951a02512418b7ad 100644 (file)
@@ -5,6 +5,7 @@ using Content.Shared.Administration;
 using Content.Shared.Administration.Logs;
 using Content.Shared.Database;
 using Content.Shared.Hands.Components;
+using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Verbs;
 
 namespace Content.Server.Verbs
@@ -96,7 +97,7 @@ namespace Content.Server.Verbs
             }
 
             // if this is a virtual pull, get the held entity
-            if (holding != null && TryComp(holding, out HandVirtualItemComponent? pull))
+            if (holding != null && TryComp(holding, out VirtualItemComponent? pull))
                 holding = pull.BlockingEntity;
 
             var verbText = $"{verb.Category?.Text} {verb.Text}".Trim();
index 088323fcc5263f29d53799d0deae4221b50ddcfb..99657c87aabe50a3e4c99801397def3536d38492 100644 (file)
@@ -18,6 +18,7 @@ using Content.Shared.Interaction;
 using Content.Shared.Interaction.Components;
 using Content.Shared.Interaction.Events;
 using Content.Shared.Inventory.Events;
+using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Item;
 using Content.Shared.Mobs.Systems;
 using Content.Shared.Movement.Events;
@@ -53,7 +54,7 @@ namespace Content.Shared.Cuffs
         [Dependency] private readonly SharedContainerSystem _container = default!;
         [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
         [Dependency] private readonly SharedHandsSystem _hands = default!;
-        [Dependency] private readonly SharedHandVirtualItemSystem _handVirtualItem = default!;
+        [Dependency] private readonly SharedVirtualItemSystem _virtualItem = default!;
         [Dependency] private readonly SharedInteractionSystem _interaction = default!;
         [Dependency] private readonly SharedPopupSystem _popup = default!;
         [Dependency] private readonly SharedTransformSystem _transform = default!;
@@ -149,7 +150,7 @@ namespace Content.Shared.Cuffs
             if (args.Container.ID != component.Container?.ID)
                 return;
 
-            _handVirtualItem.DeleteInHandsMatching(uid, args.Entity);
+            _virtualItem.DeleteInHandsMatching(uid, args.Entity);
             UpdateCuffState(uid, component);
         }
 
@@ -427,10 +428,10 @@ namespace Content.Shared.Cuffs
                     break;
             }
 
-            if (_handVirtualItem.TrySpawnVirtualItemInHand(handcuff, uid, out var virtItem1))
+            if (_virtualItem.TrySpawnVirtualItemInHand(handcuff, uid, out var virtItem1))
                 EnsureComp<UnremoveableComponent>(virtItem1.Value);
 
-            if (_handVirtualItem.TrySpawnVirtualItemInHand(handcuff, uid, out var virtItem2))
+            if (_virtualItem.TrySpawnVirtualItemInHand(handcuff, uid, out var virtItem2))
                 EnsureComp<UnremoveableComponent>(virtItem2.Value);
         }
 
diff --git a/Content.Shared/Hands/Components/HandVirtualItemComponent.cs b/Content.Shared/Hands/Components/HandVirtualItemComponent.cs
deleted file mode 100644 (file)
index e456013..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-using Robust.Shared.GameStates;
-
-namespace Content.Shared.Hands.Components;
-
-[RegisterComponent]
-[NetworkedComponent]
-[AutoGenerateComponentState(true)]
-public sealed partial class HandVirtualItemComponent : Component
-{
-    /// <summary>
-    ///     The entity blocking this hand.
-    /// </summary>
-    [DataField("blockingEntity"), AutoNetworkedField]
-    public EntityUid BlockingEntity;
-}
index 42201ab6af9328bdb2479469e998168466d0a5ea..e071cdc69380c4f58e589a79ab4f2c5b827d3016 100644 (file)
@@ -1,6 +1,7 @@
 using System.Numerics;
 using Content.Shared.Hands.Components;
 using Content.Shared.Interaction;
+using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Tag;
 using Robust.Shared.Containers;
 using Robust.Shared.Map;
@@ -28,8 +29,8 @@ public abstract partial class SharedHandsSystem
         var didUnequip = new DidUnequipHandEvent(uid, args.Entity, hand);
         RaiseLocalEvent(uid, didUnequip);
 
-        if (TryComp(args.Entity, out HandVirtualItemComponent? @virtual))
-            _virtualSystem.Delete((args.Entity, @virtual), uid);
+        if (TryComp(args.Entity, out VirtualItemComponent? @virtual))
+            _virtualSystem.DeleteVirtualItem((args.Entity, @virtual), uid);
     }
 
     private bool ShouldIgnoreRestrictions(EntityUid user)
index c5dd7c6e35981c49b89b04adbbf16ab8fe8e3985..32339eb03ac5bf42ae9f1c3537000d13c3746964 100644 (file)
@@ -3,6 +3,7 @@ using Content.Shared.Examine;
 using Content.Shared.Hands.Components;
 using Content.Shared.IdentityManagement;
 using Content.Shared.Input;
+using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Localizations;
 using Robust.Shared.Input.Binding;
 using Robust.Shared.Map;
@@ -183,7 +184,7 @@ public abstract partial class SharedHandsSystem : EntitySystem
     private void HandleExamined(EntityUid uid, HandsComponent handsComp, ExaminedEvent args)
     {
         var held = EnumerateHeld(uid, handsComp)
-            .Where(x => !HasComp<HandVirtualItemComponent>(x)).ToList();
+            .Where(x => !HasComp<VirtualItemComponent>(x)).ToList();
 
         using (args.PushGroup(nameof(HandsComponent)))
         {
diff --git a/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Virtual.cs b/Content.Shared/Hands/EntitySystems/SharedHandsSystem.Virtual.cs
deleted file mode 100644 (file)
index b83ec8c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-using Content.Shared.Hands.Components;
-
-namespace Content.Shared.Hands.EntitySystems;
-
-public abstract partial class SharedHandsSystem
-{
-    private void InitializeVirtual()
-    {
-        SubscribeLocalEvent<HandVirtualItemComponent, AfterAutoHandleStateEvent>(OnVirtualAfter);
-    }
-
-    private void OnVirtualAfter(EntityUid uid, HandVirtualItemComponent component, ref AfterAutoHandleStateEvent args)
-    {
-        // update hands GUI with new entity.
-        if (ContainerSystem.IsEntityInContainer(uid))
-            _items.VisualsChanged(uid);
-    }
-}
index f0a1bcb29ccb6562cdbf4b1ecc5c7383416948b2..699fb64ee8dee8279abc7d984a22d330e5f1d48e 100644 (file)
@@ -4,6 +4,7 @@ using Content.Shared.ActionBlocker;
 using Content.Shared.Administration.Logs;
 using Content.Shared.Hands.Components;
 using Content.Shared.Interaction;
+using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Item;
 using Content.Shared.Storage.EntitySystems;
 using Robust.Shared.Containers;
@@ -20,7 +21,7 @@ public abstract partial class SharedHandsSystem
     [Dependency] private readonly SharedItemSystem _items = default!;
     [Dependency] private readonly SharedStorageSystem _storage = default!;
     [Dependency] protected readonly SharedTransformSystem TransformSystem = default!;
-    [Dependency] private readonly SharedHandVirtualItemSystem _virtualSystem = default!;
+    [Dependency] private readonly SharedVirtualItemSystem _virtualSystem = default!;
 
     protected event Action<Entity<HandsComponent>?>? OnHandSetActive;
 
@@ -31,7 +32,6 @@ public abstract partial class SharedHandsSystem
         InitializeInteractions();
         InitializeDrop();
         InitializePickup();
-        InitializeVirtual();
         InitializeRelay();
     }
 
diff --git a/Content.Shared/Hands/SharedHandVirtualItemSystem.cs b/Content.Shared/Hands/SharedHandVirtualItemSystem.cs
deleted file mode 100644 (file)
index d2fb86f..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using Content.Shared.Hands.Components;
-using Content.Shared.Hands.EntitySystems;
-using Content.Shared.Interaction;
-using Content.Shared.Inventory.Events;
-using Robust.Shared.Network;
-
-namespace Content.Shared.Hands;
-
-public abstract class SharedHandVirtualItemSystem : EntitySystem
-{
-    [Dependency] private readonly INetManager _net = default!;
-    [Dependency] private readonly SharedHandsSystem _hands = default!;
-    [Dependency] private readonly SharedTransformSystem _transform = default!;
-
-    public override void Initialize()
-    {
-        base.Initialize();
-
-        SubscribeLocalEvent<HandVirtualItemComponent, BeingEquippedAttemptEvent>(OnBeingEquippedAttempt);
-        SubscribeLocalEvent<HandVirtualItemComponent, BeforeRangedInteractEvent>(HandleBeforeInteract);
-    }
-
-    public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user)
-    {
-        return TrySpawnVirtualItemInHand(blockingEnt, user, out _);
-    }
-
-    public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user, [NotNullWhen(true)] out EntityUid? virtualItem)
-    {
-        if (_net.IsClient || !_hands.TryGetEmptyHand(user, out var hand))
-        {
-            virtualItem = null;
-            return false;
-        }
-
-        var pos = Transform(user).Coordinates;
-        virtualItem = Spawn("HandVirtualItem", pos);
-        var virtualItemComp = EntityManager.GetComponent<HandVirtualItemComponent>(virtualItem.Value);
-        virtualItemComp.BlockingEntity = blockingEnt;
-        Dirty(virtualItemComp);
-        _hands.DoPickup(user, hand, virtualItem.Value);
-        return true;
-    }
-
-
-    /// <summary>
-    ///     Deletes all virtual items in a user's hands with
-    ///     the specified blocked entity.
-    /// </summary>
-    public void DeleteInHandsMatching(EntityUid user, EntityUid matching)
-    {
-        // Client can't currently predict deleting network entities atm and this might happen due to the
-        // hands leaving PVS for example, in which case we wish to ignore it.
-        if (_net.IsClient)
-            return;
-
-        foreach (var hand in _hands.EnumerateHands(user))
-        {
-            if (TryComp(hand.HeldEntity, out HandVirtualItemComponent? virt) && virt.BlockingEntity == matching)
-            {
-                Delete((hand.HeldEntity.Value, virt), user);
-            }
-        }
-    }
-
-    private void OnBeingEquippedAttempt(EntityUid uid, HandVirtualItemComponent component, BeingEquippedAttemptEvent args)
-    {
-        args.Cancel();
-    }
-
-    private static void HandleBeforeInteract(
-        EntityUid uid,
-        HandVirtualItemComponent component,
-        BeforeRangedInteractEvent args)
-    {
-        // No interactions with a virtual item, please.
-        args.Handled = true;
-    }
-
-    /// <summary>
-    ///     Queues a deletion for a virtual item and notifies the blocking entity and user.
-    /// </summary>
-    public void Delete(Entity<HandVirtualItemComponent> item, EntityUid user)
-    {
-        var userEv = new VirtualItemDeletedEvent(item.Comp.BlockingEntity, user);
-        RaiseLocalEvent(user, userEv);
-        var targEv = new VirtualItemDeletedEvent(item.Comp.BlockingEntity, user);
-        RaiseLocalEvent(item.Comp.BlockingEntity, targEv);
-
-        if (TerminatingOrDeleted(item))
-            return;
-
-        _transform.DetachParentToNull(item, Transform(item));
-        if (_net.IsServer)
-            QueueDel(item);
-    }
-}
diff --git a/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs b/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs
new file mode 100644 (file)
index 0000000..e45530e
--- /dev/null
@@ -0,0 +1,215 @@
+using System.Diagnostics.CodeAnalysis;
+using Content.Shared.Hands;
+using Content.Shared.Hands.EntitySystems;
+using Content.Shared.Interaction;
+using Content.Shared.Inventory.Events;
+using Content.Shared.Item;
+using Robust.Shared.Containers;
+using Robust.Shared.Network;
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Inventory.VirtualItem;
+
+/// <summary>
+/// In charge of managing virtual items.
+/// Virtual items are used to block a <see cref="SlotButton"/>
+/// or a <see cref="HandButton"/> with a non-existent item that
+/// is a visual copy of another for whatever use
+/// </summary>
+/// <remarks>
+/// The slot visuals are managed by <see cref="HandsUiController"/>
+/// and <see cref="InventoryUiController"/>, see the <see cref="VirtualItemComponent"/>
+/// references there for more information
+/// </remarks>
+public abstract class SharedVirtualItemSystem : EntitySystem
+{
+    [Dependency] private readonly INetManager _netManager = default!;
+    [Dependency] private readonly SharedTransformSystem _transformSystem = default!;
+    [Dependency] private readonly SharedContainerSystem _containerSystem = default!;
+    [Dependency] private readonly SharedItemSystem _itemSystem = default!;
+    [Dependency] private readonly InventorySystem _inventorySystem = default!;
+    [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
+
+    [ValidatePrototypeId<EntityPrototype>]
+    private const string VirtualItem = "VirtualItem";
+
+    public override void Initialize()
+    {
+        SubscribeLocalEvent<VirtualItemComponent, AfterAutoHandleStateEvent>(OnAfterAutoHandleState);
+
+        SubscribeLocalEvent<VirtualItemComponent, BeingEquippedAttemptEvent>(OnBeingEquippedAttempt);
+        SubscribeLocalEvent<VirtualItemComponent, BeingUnequippedAttemptEvent>(OnBeingUnequippedAttempt);
+
+        SubscribeLocalEvent<VirtualItemComponent, BeforeRangedInteractEvent>(OnBeforeRangedInteract);
+    }
+
+    /// <summary>
+    /// Updates the GUI buttons with the new entity.
+    /// </summary>
+    private void OnAfterAutoHandleState(Entity<VirtualItemComponent> ent, ref AfterAutoHandleStateEvent args)
+    {
+        if (_containerSystem.IsEntityInContainer(ent))
+            _itemSystem.VisualsChanged(ent);
+    }
+
+    private void OnBeingEquippedAttempt(Entity<VirtualItemComponent> ent, ref BeingEquippedAttemptEvent args)
+    {
+        // No interactions with a virtual item, please.
+        args.Cancel();
+    }
+
+    private void OnBeingUnequippedAttempt(Entity<VirtualItemComponent> ent, ref BeingUnequippedAttemptEvent args)
+    {
+        // No interactions with a virtual item, please.
+        args.Cancel();
+    }
+
+    private void OnBeforeRangedInteract(Entity<VirtualItemComponent> ent, ref BeforeRangedInteractEvent args)
+    {
+        // No interactions with a virtual item, please.
+        args.Handled = true;
+    }
+
+    #region Hands
+    /// <summary>
+    /// Spawns a virtual item in a empty hand
+    /// </summary>
+    /// <param name="blockingEnt">The entity we will make a virtual entity copy of</param>
+    /// <param name="user">The entity that we want to insert the virtual entity</param>
+    public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user)
+    {
+        return TrySpawnVirtualItemInHand(blockingEnt, user, out _);
+    }
+
+    /// <inheritdoc cref="TrySpawnVirtualItemInHand(Robust.Shared.GameObjects.EntityUid,Robust.Shared.GameObjects.EntityUid)"/>
+    public bool TrySpawnVirtualItemInHand(EntityUid blockingEnt, EntityUid user, [NotNullWhen(true)] out EntityUid? virtualItem)
+    {
+        if (!TrySpawnVirtualItem(blockingEnt, user, out virtualItem) || !_handsSystem.TryGetEmptyHand(user, out var hand))
+            return false;
+
+        _handsSystem.DoPickup(user, hand, virtualItem.Value);
+        return true;
+    }
+
+    /// <summary>
+    /// Scan the user's hands until we find the virtual entity, if the
+    /// virtual entity is a copy of the matching entity, delete it
+    /// </summary>
+    public void DeleteInHandsMatching(EntityUid user, EntityUid matching)
+    {
+        // Client can't currently predict deleting networked entities so we use this workaround, another
+        // problem can popup when the hands leave PVS for example and this avoids that too
+        if (_netManager.IsClient)
+            return;
+
+        foreach (var hand in _handsSystem.EnumerateHands(user))
+        {
+            if (TryComp(hand.HeldEntity, out VirtualItemComponent? virt) && virt.BlockingEntity == matching)
+            {
+                DeleteVirtualItem((hand.HeldEntity.Value, virt), user);
+            }
+        }
+    }
+    #endregion
+
+    #region Inventory
+
+    /// <summary>
+    /// Spawns a virtual item inside a inventory slot
+    /// </summary>
+    /// <param name="blockingEnt">The entity we will make a virtual entity copy of</param>
+    /// <param name="user">The entity that we want to insert the virtual entity</param>
+    /// <param name="slot">The slot to which we will insert the virtual entity (could be the "shoes" slot, for example)</param>
+    public bool TrySpawnVirtualItemInInventory(EntityUid blockingEnt, EntityUid user, string slot, bool force = false)
+    {
+        return TrySpawnVirtualItemInInventory(blockingEnt, user, slot, force, out _);
+    }
+
+    /// <inheritdoc cref="TrySpawnVirtualItemInInventory(Robust.Shared.GameObjects.EntityUid,Robust.Shared.GameObjects.EntityUid,string,bool)"/>
+    public bool TrySpawnVirtualItemInInventory(EntityUid blockingEnt, EntityUid user, string slot, bool force, [NotNullWhen(true)] out EntityUid? virtualItem)
+    {
+        if (!TrySpawnVirtualItem(blockingEnt, user, out virtualItem))
+            return false;
+
+        _inventorySystem.TryEquip(user, virtualItem.Value, slot, force: force);
+        return true;
+    }
+
+    /// <summary>
+    /// Scan the user's inventory slots until we find a virtual entity, when
+    /// that's done check if the found virtual entity is a copy of our matching entity,
+    /// if it is, delete it
+    /// </summary>
+    /// <param name="slotName">Set this param if you have the name of the slot, it avoids unnecessary queries</param>
+    public void DeleteInSlotMatching(EntityUid user, EntityUid matching, string? slotName = null)
+    {
+        // Client can't currently predict deleting networked entities so we use this workaround, another
+        // problem can popup when the hands leave PVS for example and this avoids that too
+        if (_netManager.IsClient)
+            return;
+
+        if (slotName != null)
+        {
+            if (!_inventorySystem.TryGetSlotEntity(user, slotName, out var slotEnt))
+                return;
+
+            if (TryComp(slotEnt, out VirtualItemComponent? virt) && virt.BlockingEntity == matching)
+                DeleteVirtualItem((slotEnt.Value, virt), user);
+
+            return;
+        }
+
+        if (!_inventorySystem.TryGetSlots(user, out var slotDefinitions))
+            return;
+
+        foreach (var slot in slotDefinitions)
+        {
+            if (!_inventorySystem.TryGetSlotEntity(user, slot.Name, out var slotEnt))
+                continue;
+
+            if (TryComp(slotEnt, out VirtualItemComponent? virt) && virt.BlockingEntity == matching)
+                DeleteVirtualItem((slotEnt.Value, virt), user);
+        }
+    }
+    #endregion
+
+    /// <summary>
+    /// Spawns a virtual item and setups the component without any special handling
+    /// </summary>
+    /// <param name="blockingEnt">The entity we will make a virtual entity copy of</param>
+    /// <param name="user">The entity that we want to insert the virtual entity</param>
+    public bool TrySpawnVirtualItem(EntityUid blockingEnt, EntityUid user, [NotNullWhen(true)] out EntityUid? virtualItem)
+    {
+        if (_netManager.IsClient)
+        {
+            virtualItem = null;
+            return false;
+        }
+
+        var pos = Transform(user).Coordinates;
+        virtualItem = Spawn(VirtualItem, pos);
+        var virtualItemComp = Comp<VirtualItemComponent>(virtualItem.Value);
+        virtualItemComp.BlockingEntity = blockingEnt;
+        Dirty(virtualItem.Value, virtualItemComp);
+        return true;
+    }
+
+    /// <summary>
+    /// Queues a deletion for a virtual item and notifies the blocking entity and user.
+    /// </summary>
+    public void DeleteVirtualItem(Entity<VirtualItemComponent> item, EntityUid user)
+    {
+        var userEv = new VirtualItemDeletedEvent(item.Comp.BlockingEntity, user);
+        RaiseLocalEvent(user, userEv);
+
+        var targEv = new VirtualItemDeletedEvent(item.Comp.BlockingEntity, user);
+        RaiseLocalEvent(item.Comp.BlockingEntity, targEv);
+
+        if (TerminatingOrDeleted(item))
+            return;
+
+        _transformSystem.DetachParentToNull(item, Transform(item));
+        if (_netManager.IsServer)
+            QueueDel(item);
+    }
+}
diff --git a/Content.Shared/Inventory/VirtualItem/VirtualItemComponent.cs b/Content.Shared/Inventory/VirtualItem/VirtualItemComponent.cs
new file mode 100644 (file)
index 0000000..cda1be5
--- /dev/null
@@ -0,0 +1,16 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Inventory.VirtualItem;
+
+/// <inheritdoc cref="SharedVirtualItemSystem"/>
+[RegisterComponent]
+[NetworkedComponent]
+[AutoGenerateComponentState(true)]
+public sealed partial class VirtualItemComponent : Component
+{
+    /// <summary>
+    /// The entity blocking this slot.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public EntityUid BlockingEntity;
+}
index 3775ab1ec140b640e0a7e19ba1bb40f3c67da04a..50143ae551c7871bc0e05ad7b3f7536e4740937f 100644 (file)
@@ -5,6 +5,7 @@ using Content.Shared.Audio;
 using Content.Shared.Buckle;
 using Content.Shared.Buckle.Components;
 using Content.Shared.Hands;
+using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Item;
 using Content.Shared.Light.Components;
 using Content.Shared.Movement.Components;
@@ -37,7 +38,7 @@ public abstract partial class SharedVehicleSystem : EntitySystem
     [Dependency] private readonly SharedTransformSystem _transform = default!;
     [Dependency] private readonly TagSystem _tagSystem = default!;
     [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
-    [Dependency] private readonly SharedHandVirtualItemSystem _virtualItemSystem = default!;
+    [Dependency] private readonly SharedVirtualItemSystem _virtualItemSystem = default!;
     [Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
     [Dependency] private readonly SharedJointSystem _joints = default!;
     [Dependency] private readonly SharedBuckleSystem _buckle = default!;
index e6286c47cc399667db5a9c9b0db5a410345b3149..9dda910f3ffc15ac386158fc03b80a55df102582 100644 (file)
@@ -1,6 +1,7 @@
 using Content.Shared.ActionBlocker;
 using Content.Shared.Hands.Components;
 using Content.Shared.Interaction;
+using Content.Shared.Inventory.VirtualItem;
 using Robust.Shared.Containers;
 
 namespace Content.Shared.Verbs
@@ -97,7 +98,7 @@ namespace Content.Shared.Verbs
                     // This allows you to do things like buckle a dragged person onto a surgery table, without click-dragging
                     // their sprite.
 
-                    if (TryComp(@using, out HandVirtualItemComponent? pull))
+                    if (TryComp(@using, out VirtualItemComponent? pull))
                     {
                         @using = pull.BlockingEntity;
                     }
index 0f6422241cf96dfbd42b5fdcc687dcad8f4a18f9..54b030b9eb21df5bb6fd85e182b92071af82053e 100644 (file)
@@ -2,6 +2,7 @@ using Content.Shared.Hands;
 using Content.Shared.Hands.Components;
 using Content.Shared.Hands.EntitySystems;
 using Content.Shared.Interaction.Events;
+using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Item;
 using Content.Shared.Popups;
 using Content.Shared.Timing;
@@ -19,7 +20,7 @@ namespace Content.Shared.Wieldable;
 
 public sealed class WieldableSystem : EntitySystem
 {
-    [Dependency] private readonly SharedHandVirtualItemSystem _virtualItemSystem = default!;
+    [Dependency] private readonly SharedVirtualItemSystem _virtualItemSystem = default!;
     [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
     [Dependency] private readonly SharedItemSystem _itemSystem = default!;
     [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
index f397f9a61af6f8eeaab272e591ce90cc2acb3699..ed7424355018067af090ac608daa64f1f4b66ffb 100644 (file)
@@ -1,8 +1,8 @@
 # This item is stored in the hand slot while it is blocked, to represent what is blocking that hand.
 - type: entity
-  id: HandVirtualItem
+  id: VirtualItem
   name: VIRTUAL ITEM YOU SHOULD NOT SEE THIS
   noSpawn: true
   components:
   - type: Item
-  - type: HandVirtualItem
+  - type: VirtualItem