DragInsertContainerSystem.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. using Content.Shared.ActionBlocker;
  2. using Content.Shared.Administration.Logs;
  3. using Content.Shared.Climbing.Systems;
  4. using Content.Shared.Database;
  5. using Content.Shared.DoAfter;
  6. using Content.Shared.DragDrop;
  7. using Content.Shared.Verbs;
  8. using Robust.Shared.Containers;
  9. using Robust.Shared.Serialization;
  10. namespace Content.Shared.Containers;
  11. public sealed partial class DragInsertContainerSystem : EntitySystem
  12. {
  13. [Dependency] private readonly ISharedAdminLogManager _adminLog = default!;
  14. [Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
  15. [Dependency] private readonly ClimbSystem _climb = default!;
  16. [Dependency] private readonly SharedContainerSystem _container = default!;
  17. [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
  18. public override void Initialize()
  19. {
  20. base.Initialize();
  21. SubscribeLocalEvent<DragInsertContainerComponent, DragDropTargetEvent>(OnDragDropOn, before: new []{ typeof(ClimbSystem)});
  22. SubscribeLocalEvent<DragInsertContainerComponent, DragInsertContainerDoAfterEvent>(OnDragFinished);
  23. SubscribeLocalEvent<DragInsertContainerComponent, CanDropTargetEvent>(OnCanDragDropOn);
  24. SubscribeLocalEvent<DragInsertContainerComponent, GetVerbsEvent<AlternativeVerb>>(OnGetAlternativeVerb);
  25. }
  26. private void OnDragDropOn(Entity<DragInsertContainerComponent> ent, ref DragDropTargetEvent args)
  27. {
  28. if (args.Handled)
  29. return;
  30. var (_, comp) = ent;
  31. if (!_container.TryGetContainer(ent, comp.ContainerId, out var container))
  32. return;
  33. if (comp.EntryDelay <= TimeSpan.Zero ||
  34. !comp.DelaySelfEntry && args.User == args.Dragged)
  35. {
  36. //instant insertion
  37. args.Handled = Insert(args.Dragged, args.User, ent, container);
  38. return;
  39. }
  40. //delayed insertion
  41. var doAfterArgs = new DoAfterArgs(EntityManager, args.User, comp.EntryDelay, new DragInsertContainerDoAfterEvent(), ent, args.Dragged, ent)
  42. {
  43. BreakOnDamage = true,
  44. BreakOnMove = true,
  45. NeedHand = false,
  46. };
  47. _doAfter.TryStartDoAfter(doAfterArgs);
  48. args.Handled = true;
  49. }
  50. private void OnDragFinished(Entity<DragInsertContainerComponent> ent, ref DragInsertContainerDoAfterEvent args)
  51. {
  52. if (args.Handled || args.Cancelled || args.Args.Target == null)
  53. return;
  54. if (!_container.TryGetContainer(ent, ent.Comp.ContainerId, out var container))
  55. return;
  56. Insert(args.Args.Target.Value, args.User, ent, container);
  57. }
  58. private void OnCanDragDropOn(Entity<DragInsertContainerComponent> ent, ref CanDropTargetEvent args)
  59. {
  60. var (_, comp) = ent;
  61. if (!_container.TryGetContainer(ent, comp.ContainerId, out var container))
  62. return;
  63. args.Handled = true;
  64. args.CanDrop |= _container.CanInsert(args.Dragged, container);
  65. }
  66. private void OnGetAlternativeVerb(Entity<DragInsertContainerComponent> ent, ref GetVerbsEvent<AlternativeVerb> args)
  67. {
  68. var (uid, comp) = ent;
  69. if (!comp.UseVerbs)
  70. return;
  71. if (!args.CanInteract || !args.CanAccess || args.Hands == null)
  72. return;
  73. if (!_container.TryGetContainer(uid, comp.ContainerId, out var container))
  74. return;
  75. var user = args.User;
  76. if (!_actionBlocker.CanInteract(user, ent))
  77. return;
  78. // Eject verb
  79. if (container.ContainedEntities.Count > 0)
  80. {
  81. // make sure that we can actually take stuff out of the container
  82. var emptyableCount = 0;
  83. foreach (var contained in container.ContainedEntities)
  84. {
  85. if (!_container.CanRemove(contained, container))
  86. continue;
  87. emptyableCount++;
  88. }
  89. if (emptyableCount > 0)
  90. {
  91. AlternativeVerb verb = new()
  92. {
  93. Act = () =>
  94. {
  95. _adminLog.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user):player} emptied container {ToPrettyString(ent)}");
  96. var ents = _container.EmptyContainer(container);
  97. foreach (var contained in ents)
  98. {
  99. _climb.ForciblySetClimbing(contained, ent);
  100. }
  101. },
  102. Category = VerbCategory.Eject,
  103. Text = Loc.GetString("container-verb-text-empty"),
  104. Priority = 1 // Promote to top to make ejecting the ALT-click action
  105. };
  106. args.Verbs.Add(verb);
  107. }
  108. }
  109. // Self-insert verb
  110. if (_container.CanInsert(user, container) &&
  111. _actionBlocker.CanMove(user))
  112. {
  113. AlternativeVerb verb = new()
  114. {
  115. Act = () => Insert(user, user, ent, container),
  116. Text = Loc.GetString("container-verb-text-enter"),
  117. Priority = 2
  118. };
  119. args.Verbs.Add(verb);
  120. }
  121. }
  122. public bool Insert(EntityUid target, EntityUid user, EntityUid containerEntity, BaseContainer container)
  123. {
  124. if (!_container.Insert(target, container))
  125. return false;
  126. _adminLog.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(user):player} inserted {ToPrettyString(target):player} into container {ToPrettyString(containerEntity)}");
  127. return true;
  128. }
  129. [Serializable, NetSerializable]
  130. public sealed partial class DragInsertContainerDoAfterEvent : SimpleDoAfterEvent
  131. {
  132. }
  133. }