1
0

MagnetPickupSystem.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. using Content.Server.Storage.Components;
  2. using Content.Shared.Inventory;
  3. using Content.Shared.Whitelist;
  4. using Robust.Shared.Map;
  5. using Robust.Shared.Physics.Components;
  6. using Robust.Shared.Timing;
  7. namespace Content.Shared.Storage.EntitySystems;
  8. /// <summary>
  9. /// <see cref="MagnetPickupComponent"/>
  10. /// </summary>
  11. public sealed class MagnetPickupSystem : EntitySystem
  12. {
  13. [Dependency] private readonly IGameTiming _timing = default!;
  14. [Dependency] private readonly EntityLookupSystem _lookup = default!;
  15. [Dependency] private readonly InventorySystem _inventory = default!;
  16. [Dependency] private readonly SharedTransformSystem _transform = default!;
  17. [Dependency] private readonly SharedStorageSystem _storage = default!;
  18. [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
  19. private static readonly TimeSpan ScanDelay = TimeSpan.FromSeconds(1);
  20. private EntityQuery<PhysicsComponent> _physicsQuery;
  21. public override void Initialize()
  22. {
  23. base.Initialize();
  24. _physicsQuery = GetEntityQuery<PhysicsComponent>();
  25. SubscribeLocalEvent<MagnetPickupComponent, MapInitEvent>(OnMagnetMapInit);
  26. }
  27. private void OnMagnetMapInit(EntityUid uid, MagnetPickupComponent component, MapInitEvent args)
  28. {
  29. component.NextScan = _timing.CurTime;
  30. }
  31. public override void Update(float frameTime)
  32. {
  33. base.Update(frameTime);
  34. var query = EntityQueryEnumerator<MagnetPickupComponent, StorageComponent, TransformComponent, MetaDataComponent>();
  35. var currentTime = _timing.CurTime;
  36. while (query.MoveNext(out var uid, out var comp, out var storage, out var xform, out var meta))
  37. {
  38. if (comp.NextScan > currentTime)
  39. continue;
  40. comp.NextScan += ScanDelay;
  41. if (!_inventory.TryGetContainingSlot((uid, xform, meta), out var slotDef))
  42. continue;
  43. if ((slotDef.SlotFlags & comp.SlotFlags) == 0x0)
  44. continue;
  45. // No space
  46. if (!_storage.HasSpace((uid, storage)))
  47. continue;
  48. var parentUid = xform.ParentUid;
  49. var playedSound = false;
  50. var finalCoords = xform.Coordinates;
  51. var moverCoords = _transform.GetMoverCoordinates(uid, xform);
  52. foreach (var near in _lookup.GetEntitiesInRange(uid, comp.Range, LookupFlags.Dynamic | LookupFlags.Sundries))
  53. {
  54. if (_whitelistSystem.IsWhitelistFail(storage.Whitelist, near))
  55. continue;
  56. if (!_physicsQuery.TryGetComponent(near, out var physics) || physics.BodyStatus != BodyStatus.OnGround)
  57. continue;
  58. if (near == parentUid)
  59. continue;
  60. // TODO: Probably move this to storage somewhere when it gets cleaned up
  61. // TODO: This sucks but you need to fix a lot of stuff to make it better
  62. // the problem is that stack pickups delete the original entity, which is fine, but due to
  63. // game state handling we can't show a lerp animation for it.
  64. var nearXform = Transform(near);
  65. var nearMap = _transform.GetMapCoordinates(near, xform: nearXform);
  66. var nearCoords = _transform.ToCoordinates(moverCoords.EntityId, nearMap);
  67. if (!_storage.Insert(uid, near, out var stacked, storageComp: storage, playSound: !playedSound))
  68. continue;
  69. // Play pickup animation for either the stack entity or the original entity.
  70. if (stacked != null)
  71. _storage.PlayPickupAnimation(stacked.Value, nearCoords, finalCoords, nearXform.LocalRotation);
  72. else
  73. _storage.PlayPickupAnimation(near, nearCoords, finalCoords, nearXform.LocalRotation);
  74. playedSound = true;
  75. }
  76. }
  77. }
  78. }