1
0

EntityStorageSystem.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. using System.Diagnostics.CodeAnalysis;
  2. using Content.Server.Atmos.EntitySystems;
  3. using Content.Server.Body.Systems;
  4. using Content.Server.Construction;
  5. using Content.Server.Construction.Components;
  6. using Content.Server.Storage.Components;
  7. using Content.Shared.Destructible;
  8. using Content.Shared.Explosion;
  9. using Content.Shared.Foldable;
  10. using Content.Shared.Interaction;
  11. using Content.Shared.Lock;
  12. using Content.Shared.Movement.Events;
  13. using Content.Shared.Storage.Components;
  14. using Content.Shared.Storage.EntitySystems;
  15. using Content.Shared.Tools.Systems;
  16. using Content.Shared.Verbs;
  17. using Robust.Server.GameObjects;
  18. using Robust.Shared.Containers;
  19. using Robust.Shared.GameStates;
  20. using Robust.Shared.Map;
  21. namespace Content.Server.Storage.EntitySystems;
  22. public sealed class EntityStorageSystem : SharedEntityStorageSystem
  23. {
  24. [Dependency] private readonly ConstructionSystem _construction = default!;
  25. [Dependency] private readonly AtmosphereSystem _atmos = default!;
  26. [Dependency] private readonly IMapManager _map = default!;
  27. [Dependency] private readonly MapSystem _mapSystem = default!;
  28. public override void Initialize()
  29. {
  30. base.Initialize();
  31. /* CompRef things */
  32. SubscribeLocalEvent<EntityStorageComponent, EntityUnpausedEvent>(OnEntityUnpausedEvent);
  33. SubscribeLocalEvent<EntityStorageComponent, ComponentInit>(OnComponentInit);
  34. SubscribeLocalEvent<EntityStorageComponent, ComponentStartup>(OnComponentStartup);
  35. SubscribeLocalEvent<EntityStorageComponent, ActivateInWorldEvent>(OnInteract, after: new[] { typeof(LockSystem) });
  36. SubscribeLocalEvent<EntityStorageComponent, LockToggleAttemptEvent>(OnLockToggleAttempt);
  37. SubscribeLocalEvent<EntityStorageComponent, DestructionEventArgs>(OnDestruction);
  38. SubscribeLocalEvent<EntityStorageComponent, GetVerbsEvent<InteractionVerb>>(AddToggleOpenVerb);
  39. SubscribeLocalEvent<EntityStorageComponent, ContainerRelayMovementEntityEvent>(OnRelayMovement);
  40. SubscribeLocalEvent<EntityStorageComponent, FoldAttemptEvent>(OnFoldAttempt);
  41. SubscribeLocalEvent<EntityStorageComponent, ComponentGetState>(OnGetState);
  42. SubscribeLocalEvent<EntityStorageComponent, ComponentHandleState>(OnHandleState);
  43. /* CompRef things */
  44. SubscribeLocalEvent<EntityStorageComponent, MapInitEvent>(OnMapInit);
  45. SubscribeLocalEvent<EntityStorageComponent, WeldableAttemptEvent>(OnWeldableAttempt);
  46. SubscribeLocalEvent<EntityStorageComponent, BeforeExplodeEvent>(OnExploded);
  47. SubscribeLocalEvent<InsideEntityStorageComponent, InhaleLocationEvent>(OnInsideInhale);
  48. SubscribeLocalEvent<InsideEntityStorageComponent, ExhaleLocationEvent>(OnInsideExhale);
  49. SubscribeLocalEvent<InsideEntityStorageComponent, AtmosExposedGetAirEvent>(OnInsideExposed);
  50. SubscribeLocalEvent<InsideEntityStorageComponent, EntGotRemovedFromContainerMessage>(OnRemoved);
  51. }
  52. private void OnMapInit(EntityUid uid, EntityStorageComponent component, MapInitEvent args)
  53. {
  54. if (!component.Open && component.Air.TotalMoles == 0)
  55. {
  56. // If we're closed on spawn and have no air already saved, we need to pull some air into our environment from where we spawned,
  57. // so that we have -something-. For example, if you bought an animal crate or something.
  58. TakeGas(uid, component);
  59. }
  60. }
  61. protected override void OnComponentInit(EntityUid uid, SharedEntityStorageComponent component, ComponentInit args)
  62. {
  63. base.OnComponentInit(uid, component, args);
  64. if (TryComp<ConstructionComponent>(uid, out var construction))
  65. _construction.AddContainer(uid, ContainerName, construction);
  66. }
  67. public override bool ResolveStorage(EntityUid uid, [NotNullWhen(true)] ref SharedEntityStorageComponent? component)
  68. {
  69. if (component != null)
  70. return true;
  71. TryComp<EntityStorageComponent>(uid, out var storage);
  72. component = storage;
  73. return component != null;
  74. }
  75. private void OnWeldableAttempt(EntityUid uid, EntityStorageComponent component, WeldableAttemptEvent args)
  76. {
  77. if (component.Open)
  78. {
  79. args.Cancel();
  80. return;
  81. }
  82. if (component.Contents.Contains(args.User))
  83. {
  84. var msg = Loc.GetString("entity-storage-component-already-contains-user-message");
  85. Popup.PopupEntity(msg, args.User, args.User);
  86. args.Cancel();
  87. }
  88. }
  89. private void OnExploded(Entity<EntityStorageComponent> ent, ref BeforeExplodeEvent args)
  90. {
  91. args.Contents.AddRange(ent.Comp.Contents.ContainedEntities);
  92. }
  93. protected override void TakeGas(EntityUid uid, SharedEntityStorageComponent component)
  94. {
  95. if (!component.Airtight)
  96. return;
  97. var serverComp = (EntityStorageComponent) component;
  98. var tile = GetOffsetTileRef(uid, serverComp);
  99. if (tile != null && _atmos.GetTileMixture(tile.Value.GridUid, null, tile.Value.GridIndices, true) is {} environment)
  100. {
  101. _atmos.Merge(serverComp.Air, environment.RemoveVolume(serverComp.Air.Volume));
  102. }
  103. }
  104. public override void ReleaseGas(EntityUid uid, SharedEntityStorageComponent component)
  105. {
  106. var serverComp = (EntityStorageComponent) component;
  107. if (!serverComp.Airtight)
  108. return;
  109. var tile = GetOffsetTileRef(uid, serverComp);
  110. if (tile != null && _atmos.GetTileMixture(tile.Value.GridUid, null, tile.Value.GridIndices, true) is {} environment)
  111. {
  112. _atmos.Merge(environment, serverComp.Air);
  113. serverComp.Air.Clear();
  114. }
  115. }
  116. private TileRef? GetOffsetTileRef(EntityUid uid, EntityStorageComponent component)
  117. {
  118. var targetCoordinates = new EntityCoordinates(uid, component.EnteringOffset).ToMap(EntityManager, TransformSystem);
  119. if (_map.TryFindGridAt(targetCoordinates, out var gridId, out var grid))
  120. {
  121. return _mapSystem.GetTileRef(gridId, grid, targetCoordinates);
  122. }
  123. return null;
  124. }
  125. private void OnRemoved(EntityUid uid, InsideEntityStorageComponent component, EntGotRemovedFromContainerMessage args)
  126. {
  127. if (args.Container.Owner != component.Storage)
  128. return;
  129. RemComp(uid, component);
  130. }
  131. #region Gas mix event handlers
  132. private void OnInsideInhale(EntityUid uid, InsideEntityStorageComponent component, InhaleLocationEvent args)
  133. {
  134. if (TryComp<EntityStorageComponent>(component.Storage, out var storage) && storage.Airtight)
  135. {
  136. args.Gas = storage.Air;
  137. }
  138. }
  139. private void OnInsideExhale(EntityUid uid, InsideEntityStorageComponent component, ExhaleLocationEvent args)
  140. {
  141. if (TryComp<EntityStorageComponent>(component.Storage, out var storage) && storage.Airtight)
  142. {
  143. args.Gas = storage.Air;
  144. }
  145. }
  146. private void OnInsideExposed(EntityUid uid, InsideEntityStorageComponent component, ref AtmosExposedGetAirEvent args)
  147. {
  148. if (args.Handled)
  149. return;
  150. if (TryComp<EntityStorageComponent>(component.Storage, out var storage))
  151. {
  152. if (!storage.Airtight)
  153. return;
  154. args.Gas = storage.Air;
  155. }
  156. args.Handled = true;
  157. }
  158. #endregion
  159. }