CargoSystem.Telepad.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. using System.Linq;
  2. using Content.Server.Cargo.Components;
  3. using Content.Server.Power.Components;
  4. using Content.Server.Power.EntitySystems;
  5. using Content.Server.Station.Components;
  6. using Content.Shared.Cargo;
  7. using Content.Shared.Cargo.Components;
  8. using Content.Shared.DeviceLinking;
  9. using Content.Shared.Power;
  10. using Robust.Shared.Audio;
  11. using Robust.Shared.Random;
  12. using Robust.Shared.Utility;
  13. namespace Content.Server.Cargo.Systems;
  14. public sealed partial class CargoSystem
  15. {
  16. private void InitializeTelepad()
  17. {
  18. SubscribeLocalEvent<CargoTelepadComponent, ComponentInit>(OnInit);
  19. SubscribeLocalEvent<CargoTelepadComponent, ComponentShutdown>(OnShutdown);
  20. SubscribeLocalEvent<CargoTelepadComponent, PowerChangedEvent>(OnTelepadPowerChange);
  21. // Shouldn't need re-anchored event
  22. SubscribeLocalEvent<CargoTelepadComponent, AnchorStateChangedEvent>(OnTelepadAnchorChange);
  23. SubscribeLocalEvent<FulfillCargoOrderEvent>(OnTelepadFulfillCargoOrder);
  24. }
  25. private void OnTelepadFulfillCargoOrder(ref FulfillCargoOrderEvent args)
  26. {
  27. var query = EntityQueryEnumerator<CargoTelepadComponent, TransformComponent>();
  28. while (query.MoveNext(out var uid, out var tele, out var xform))
  29. {
  30. if (tele.CurrentState != CargoTelepadState.Idle)
  31. continue;
  32. if (!this.IsPowered(uid, EntityManager))
  33. continue;
  34. if (_station.GetOwningStation(uid, xform) != args.Station)
  35. continue;
  36. // todo cannot be fucking asked to figure out device linking rn but this shouldn't just default to the first port.
  37. if (!TryComp<DeviceLinkSinkComponent>(uid, out var sinkComponent) ||
  38. sinkComponent.LinkedSources.FirstOrNull() is not { } console ||
  39. console != args.OrderConsole.Owner)
  40. continue;
  41. for (var i = 0; i < args.Order.OrderQuantity; i++)
  42. {
  43. tele.CurrentOrders.Add(args.Order);
  44. }
  45. tele.Accumulator = tele.Delay;
  46. args.Handled = true;
  47. args.FulfillmentEntity = uid;
  48. return;
  49. }
  50. }
  51. private void UpdateTelepad(float frameTime)
  52. {
  53. var query = EntityQueryEnumerator<CargoTelepadComponent>();
  54. while (query.MoveNext(out var uid, out var comp))
  55. {
  56. // Don't EntityQuery for it as it's not required.
  57. TryComp<AppearanceComponent>(uid, out var appearance);
  58. if (comp.CurrentState == CargoTelepadState.Unpowered)
  59. {
  60. comp.CurrentState = CargoTelepadState.Idle;
  61. _appearance.SetData(uid, CargoTelepadVisuals.State, CargoTelepadState.Idle, appearance);
  62. comp.Accumulator = comp.Delay;
  63. continue;
  64. }
  65. comp.Accumulator -= frameTime;
  66. // Uhh listen teleporting takes time and I just want the 1 float.
  67. if (comp.Accumulator > 0f)
  68. {
  69. comp.CurrentState = CargoTelepadState.Idle;
  70. _appearance.SetData(uid, CargoTelepadVisuals.State, CargoTelepadState.Idle, appearance);
  71. continue;
  72. }
  73. if (comp.CurrentOrders.Count == 0)
  74. {
  75. comp.Accumulator += comp.Delay;
  76. continue;
  77. }
  78. var xform = Transform(uid);
  79. var currentOrder = comp.CurrentOrders.First();
  80. if (FulfillOrder(currentOrder, xform.Coordinates, comp.PrinterOutput))
  81. {
  82. _audio.PlayPvs(_audio.ResolveSound(comp.TeleportSound), uid, AudioParams.Default.WithVolume(-8f));
  83. if (_station.GetOwningStation(uid) is { } station)
  84. UpdateOrders(station);
  85. comp.CurrentOrders.Remove(currentOrder);
  86. comp.CurrentState = CargoTelepadState.Teleporting;
  87. _appearance.SetData(uid, CargoTelepadVisuals.State, CargoTelepadState.Teleporting, appearance);
  88. }
  89. comp.Accumulator += comp.Delay;
  90. }
  91. }
  92. private void OnInit(EntityUid uid, CargoTelepadComponent telepad, ComponentInit args)
  93. {
  94. _linker.EnsureSinkPorts(uid, telepad.ReceiverPort);
  95. }
  96. private void OnShutdown(Entity<CargoTelepadComponent> ent, ref ComponentShutdown args)
  97. {
  98. if (ent.Comp.CurrentOrders.Count == 0)
  99. return;
  100. if (_station.GetStations().Count == 0)
  101. return;
  102. if (_station.GetOwningStation(ent) is not { } station)
  103. {
  104. station = _random.Pick(_station.GetStations().Where(HasComp<StationCargoOrderDatabaseComponent>).ToList());
  105. }
  106. if (!TryComp<StationCargoOrderDatabaseComponent>(station, out var db) ||
  107. !TryComp<StationDataComponent>(station, out var data))
  108. return;
  109. foreach (var order in ent.Comp.CurrentOrders)
  110. {
  111. TryFulfillOrder((station, data), order, db);
  112. }
  113. }
  114. private void SetEnabled(EntityUid uid, CargoTelepadComponent component, ApcPowerReceiverComponent? receiver = null,
  115. TransformComponent? xform = null)
  116. {
  117. // False due to AllCompsOneEntity test where they may not have the powerreceiver.
  118. if (!Resolve(uid, ref receiver, ref xform, false))
  119. return;
  120. var disabled = !receiver.Powered || !xform.Anchored;
  121. // Setting idle state should be handled by Update();
  122. if (disabled)
  123. return;
  124. TryComp<AppearanceComponent>(uid, out var appearance);
  125. component.CurrentState = CargoTelepadState.Unpowered;
  126. _appearance.SetData(uid, CargoTelepadVisuals.State, CargoTelepadState.Unpowered, appearance);
  127. }
  128. private void OnTelepadPowerChange(EntityUid uid, CargoTelepadComponent component, ref PowerChangedEvent args)
  129. {
  130. SetEnabled(uid, component);
  131. }
  132. private void OnTelepadAnchorChange(EntityUid uid, CargoTelepadComponent component, ref AnchorStateChangedEvent args)
  133. {
  134. SetEnabled(uid, component);
  135. }
  136. }