diff --git a/Content.Client/Storage/Systems/StorageSystem.cs b/Content.Client/Storage/Systems/StorageSystem.cs index ce0a6bf1ca..2728bfa9e8 100644 --- a/Content.Client/Storage/Systems/StorageSystem.cs +++ b/Content.Client/Storage/Systems/StorageSystem.cs @@ -26,7 +26,7 @@ public sealed class StorageSystem : SharedStorageSystem SubscribeLocalEvent(OnShutdown); SubscribeNetworkEvent(HandlePickupAnimation); - SubscribeNetworkEvent(HandleAnimatingInsertingEntities); + SubscribeAllEvent(HandleAnimatingInsertingEntities); } public override void UpdateUI(Entity entity) diff --git a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs index 194ea985fb..37d7a57a4a 100644 --- a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs @@ -61,6 +61,9 @@ public abstract class SharedStorageSystem : EntitySystem public bool CheckingCanInsert; + private List _entList = new(); + private HashSet _entSet = new(); + private readonly List _sortedSizes = new(); private FrozenDictionary _nextSmallest = FrozenDictionary.Empty; @@ -262,36 +265,40 @@ public abstract class SharedStorageSystem : EntitySystem /// private void AfterInteract(EntityUid uid, StorageComponent storageComp, AfterInteractEvent args) { - if (args.Handled || !args.CanReach) + if (args.Handled || !args.CanReach || !UseDelay.TryResetDelay(uid, checkDelayed: true)) return; // Pick up all entities in a radius around the clicked location. // The last half of the if is because carpets exist and this is terrible if (storageComp.AreaInsert && (args.Target == null || !HasComp(args.Target.Value))) { - var validStorables = new List(); + _entList.Clear(); + _entSet.Clear(); + _entityLookupSystem.GetEntitiesInRange(args.ClickLocation, storageComp.AreaInsertRadius, _entSet, LookupFlags.Dynamic | LookupFlags.Sundries); var delay = 0f; - foreach (var entity in _entityLookupSystem.GetEntitiesInRange(args.ClickLocation, storageComp.AreaInsertRadius, LookupFlags.Dynamic | LookupFlags.Sundries)) + foreach (var entity in _entSet) { if (entity == args.User - // || !_itemQuery.HasComponent(entity) - || !TryComp(entity, out var itemComp) // Need comp to get item size to get weight + || !_itemQuery.TryGetComponent(entity, out var itemComp) // Need comp to get item size to get weight || !_prototype.TryIndex(itemComp.Size, out var itemSize) - || !CanInsert(uid, entity, out _, storageComp) + || !CanInsert(uid, entity, out _, storageComp, item: itemComp) || !_interactionSystem.InRangeUnobstructed(args.User, entity)) { continue; } - validStorables.Add(entity); + _entList.Add(entity); delay += itemSize.Weight * AreaInsertDelayPerItem; + + if (_entList.Count >= StorageComponent.AreaPickupLimit) + break; } //If there's only one then let's be generous - if (validStorables.Count > 1) + if (_entList.Count > 1) { - var doAfterArgs = new DoAfterArgs(EntityManager, args.User, delay, new AreaPickupDoAfterEvent(GetNetEntityList(validStorables)), uid, target: uid) + var doAfterArgs = new DoAfterArgs(EntityManager, args.User, delay, new AreaPickupDoAfterEvent(GetNetEntityList(_entList)), uid, target: uid) { BreakOnDamage = true, BreakOnMove = true, @@ -313,7 +320,7 @@ public abstract class SharedStorageSystem : EntitySystem if (_containerSystem.IsEntityInContainer(target) || target == args.User - || !HasComp(target)) + || !_itemQuery.HasComponent(target)) { return; } @@ -331,10 +338,10 @@ public abstract class SharedStorageSystem : EntitySystem args.Handled = true; if (PlayerInsertEntityInWorld((uid, storageComp), args.User, target)) { - RaiseNetworkEvent(new AnimateInsertingEntitiesEvent(GetNetEntity(uid), + EntityManager.RaiseSharedEvent(new AnimateInsertingEntitiesEvent(GetNetEntity(uid), new List { GetNetEntity(target) }, new List { GetNetCoordinates(position) }, - new List { transformOwner.LocalRotation })); + new List { transformOwner.LocalRotation }), args.User); } } } @@ -349,20 +356,27 @@ public abstract class SharedStorageSystem : EntitySystem var successfullyInserted = new List(); var successfullyInsertedPositions = new List(); var successfullyInsertedAngles = new List(); - _xformQuery.TryGetComponent(uid, out var xform); - foreach (var netEntity in args.Entities) + if (!_xformQuery.TryGetComponent(uid, out var xform)) { - var entity = GetEntity(netEntity); + return; + } + + var entCount = Math.Min(StorageComponent.AreaPickupLimit, args.Entities.Count); + + for (var i = 0; i < entCount; i++) + { + 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) || entity == args.Args.User || !_itemQuery.HasComponent(entity)) + { continue; + } - if (xform == null || - !_xformQuery.TryGetComponent(entity, out var targetXform) || + if (!_xformQuery.TryGetComponent(entity, out var targetXform) || targetXform.MapID != xform.MapID) { continue; @@ -387,12 +401,12 @@ public abstract class SharedStorageSystem : EntitySystem // If we picked up at least one thing, play a sound and do a cool animation! if (successfullyInserted.Count > 0) { - Audio.PlayPvs(component.StorageInsertSound, uid); - RaiseNetworkEvent(new AnimateInsertingEntitiesEvent( + Audio.PlayPredicted(component.StorageInsertSound, uid, args.User); + EntityManager.RaiseSharedEvent(new AnimateInsertingEntitiesEvent( GetNetEntity(uid), GetNetEntityList(successfullyInserted), GetNetCoordinatesList(successfullyInsertedPositions), - successfullyInsertedAngles)); + successfullyInsertedAngles), args.User); } args.Handled = true; diff --git a/Content.Shared/Storage/StorageComponent.cs b/Content.Shared/Storage/StorageComponent.cs index 2cae12f07a..16987f1de0 100644 --- a/Content.Shared/Storage/StorageComponent.cs +++ b/Content.Shared/Storage/StorageComponent.cs @@ -60,6 +60,11 @@ namespace Content.Shared.Storage [DataField] public bool ClickInsert = true; // Can insert stuff by clicking the storage entity with it + /// + /// How many entities area pickup can pickup at once. + /// + public const int AreaPickupLimit = 10; + [DataField] public bool AreaInsert; // Clicking with the storage entity causes it to insert all nearby storables after a delay diff --git a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/trashbag.yml b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/trashbag.yml index f802ae1c5c..9927d836ba 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/trashbag.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/trashbag.yml @@ -22,6 +22,8 @@ tags: - Cartridge - Trash + - type: UseDelay + delay: 0.5 - type: Tag tags: - TrashBag