1
0

LogProbeCartridgeSystem.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. using Content.Shared.Access.Components;
  2. using Content.Shared.Administration.Logs;
  3. using Content.Shared.Audio;
  4. using Content.Shared.CartridgeLoader;
  5. using Content.Shared.CartridgeLoader.Cartridges;
  6. using Content.Shared.Database;
  7. using Content.Shared.Hands.EntitySystems;
  8. using Content.Shared.Labels.EntitySystems;
  9. using Content.Shared.Paper;
  10. using Content.Shared.Popups;
  11. using Robust.Shared.Audio.Systems;
  12. using Robust.Shared.Random;
  13. using Robust.Shared.Timing;
  14. using System.Text;
  15. namespace Content.Server.CartridgeLoader.Cartridges;
  16. public sealed class LogProbeCartridgeSystem : EntitySystem
  17. {
  18. [Dependency] private readonly CartridgeLoaderSystem _cartridge = default!;
  19. [Dependency] private readonly IGameTiming _timing = default!;
  20. [Dependency] private readonly IRobustRandom _random = default!;
  21. [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
  22. [Dependency] private readonly SharedAudioSystem _audio = default!;
  23. [Dependency] private readonly SharedHandsSystem _hands = default!;
  24. [Dependency] private readonly SharedLabelSystem _label = default!;
  25. [Dependency] private readonly SharedPopupSystem _popup = default!;
  26. [Dependency] private readonly SharedTransformSystem _transform = default!;
  27. [Dependency] private readonly PaperSystem _paper = default!;
  28. public override void Initialize()
  29. {
  30. base.Initialize();
  31. SubscribeLocalEvent<LogProbeCartridgeComponent, CartridgeUiReadyEvent>(OnUiReady);
  32. SubscribeLocalEvent<LogProbeCartridgeComponent, CartridgeAfterInteractEvent>(AfterInteract);
  33. SubscribeLocalEvent<LogProbeCartridgeComponent, CartridgeMessageEvent>(OnMessage);
  34. }
  35. /// <summary>
  36. /// The <see cref="CartridgeAfterInteractEvent" /> gets relayed to this system if the cartridge loader is running
  37. /// the LogProbe program and someone clicks on something with it. <br/>
  38. /// <br/>
  39. /// Updates the program's list of logs with those from the device.
  40. /// </summary>
  41. private void AfterInteract(Entity<LogProbeCartridgeComponent> ent, ref CartridgeAfterInteractEvent args)
  42. {
  43. if (args.InteractEvent.Handled || !args.InteractEvent.CanReach || args.InteractEvent.Target is not { } target)
  44. return;
  45. if (!TryComp(target, out AccessReaderComponent? accessReaderComponent))
  46. return;
  47. //Play scanning sound with slightly randomized pitch
  48. _audio.PlayEntity(ent.Comp.SoundScan, args.InteractEvent.User, target, AudioHelpers.WithVariation(0.25f, _random));
  49. _popup.PopupCursor(Loc.GetString("log-probe-scan", ("device", target)), args.InteractEvent.User);
  50. ent.Comp.EntityName = Name(target);
  51. ent.Comp.PulledAccessLogs.Clear();
  52. foreach (var accessRecord in accessReaderComponent.AccessLog)
  53. {
  54. var log = new PulledAccessLog(
  55. accessRecord.AccessTime,
  56. accessRecord.Accessor
  57. );
  58. ent.Comp.PulledAccessLogs.Add(log);
  59. }
  60. // Reverse the list so the oldest is at the bottom
  61. ent.Comp.PulledAccessLogs.Reverse();
  62. UpdateUiState(ent, args.Loader);
  63. }
  64. /// <summary>
  65. /// This gets called when the ui fragment needs to be updated for the first time after activating
  66. /// </summary>
  67. private void OnUiReady(Entity<LogProbeCartridgeComponent> ent, ref CartridgeUiReadyEvent args)
  68. {
  69. UpdateUiState(ent, args.Loader);
  70. }
  71. private void OnMessage(Entity<LogProbeCartridgeComponent> ent, ref CartridgeMessageEvent args)
  72. {
  73. if (args is LogProbePrintMessage cast)
  74. PrintLogs(ent, cast.User);
  75. }
  76. private void PrintLogs(Entity<LogProbeCartridgeComponent> ent, EntityUid user)
  77. {
  78. if (string.IsNullOrEmpty(ent.Comp.EntityName))
  79. return;
  80. if (_timing.CurTime < ent.Comp.NextPrintAllowed)
  81. return;
  82. ent.Comp.NextPrintAllowed = _timing.CurTime + ent.Comp.PrintCooldown;
  83. var paper = Spawn(ent.Comp.PaperPrototype, _transform.GetMapCoordinates(user));
  84. _label.Label(paper, ent.Comp.EntityName); // label it for easy identification
  85. _audio.PlayEntity(ent.Comp.PrintSound, user, paper);
  86. _hands.PickupOrDrop(user, paper, checkActionBlocker: false);
  87. // generate the actual printout text
  88. var builder = new StringBuilder();
  89. builder.AppendLine(Loc.GetString("log-probe-printout-device", ("name", ent.Comp.EntityName)));
  90. builder.AppendLine(Loc.GetString("log-probe-printout-header"));
  91. var number = 1;
  92. foreach (var log in ent.Comp.PulledAccessLogs)
  93. {
  94. var time = TimeSpan.FromSeconds(Math.Truncate(log.Time.TotalSeconds)).ToString();
  95. builder.AppendLine(Loc.GetString("log-probe-printout-entry", ("number", number), ("time", time), ("accessor", log.Accessor)));
  96. number++;
  97. }
  98. var paperComp = Comp<PaperComponent>(paper);
  99. _paper.SetContent((paper, paperComp), builder.ToString());
  100. _adminLogger.Add(LogType.EntitySpawn, LogImpact.Low, $"{ToPrettyString(user):user} printed out LogProbe logs ({paper}) of {ent.Comp.EntityName}");
  101. }
  102. private void UpdateUiState(Entity<LogProbeCartridgeComponent> ent, EntityUid loaderUid)
  103. {
  104. var state = new LogProbeUiState(ent.Comp.EntityName, ent.Comp.PulledAccessLogs);
  105. _cartridge.UpdateCartridgeUiState(loaderUid, state);
  106. }
  107. }