ReplaySpectatorSystem.cs 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. using Content.Shared.Movement.Systems;
  2. using Content.Shared.Verbs;
  3. using Robust.Client.GameObjects;
  4. using Robust.Client.Player;
  5. using Robust.Client.Replays.Playback;
  6. using Robust.Client.State;
  7. using Robust.Shared.Console;
  8. using Robust.Shared.Network;
  9. using Robust.Shared.Player;
  10. using Robust.Shared.Serialization.Markdown.Mapping;
  11. namespace Content.Client.Replay.Spectator;
  12. /// <summary>
  13. /// This system handles spawning replay observer ghosts and maintaining their positions when traveling through time.
  14. /// It also blocks most normal interactions, just in case.
  15. /// </summary>
  16. /// <remarks>
  17. /// E.g., if an observer is on a grid, and then jumps forward or backward in time to a point where the grid does not
  18. /// exist, where should the observer go? This attempts to maintain their position and eye rotation or just re-spawns
  19. /// them as needed.
  20. /// </remarks>
  21. public sealed partial class ReplaySpectatorSystem : EntitySystem
  22. {
  23. [Dependency] private readonly IPlayerManager _player = default!;
  24. [Dependency] private readonly IConsoleHost _conHost = default!;
  25. [Dependency] private readonly IStateManager _stateMan = default!;
  26. [Dependency] private readonly TransformSystem _transform = default!;
  27. [Dependency] private readonly SharedMoverController _mover = default!;
  28. [Dependency] private readonly SharedContentEyeSystem _eye = default!;
  29. [Dependency] private readonly IReplayPlaybackManager _replayPlayback = default!;
  30. private SpectatorData? _spectatorData;
  31. public const string SpectateCmd = "replay_spectate";
  32. /// <summary>
  33. /// User Id that corresponds to the local user in a single-player game.
  34. /// </summary>
  35. public static readonly NetUserId DefaultUser = default;
  36. public override void Initialize()
  37. {
  38. base.Initialize();
  39. SubscribeLocalEvent<GetVerbsEvent<AlternativeVerb>>(OnGetAlternativeVerbs);
  40. SubscribeLocalEvent<ReplaySpectatorComponent, EntityTerminatingEvent>(OnTerminating);
  41. SubscribeLocalEvent<ReplaySpectatorComponent, LocalPlayerDetachedEvent>(OnDetached);
  42. SubscribeLocalEvent<ReplaySpectatorComponent, EntParentChangedMessage>(OnParentChanged);
  43. InitializeBlockers();
  44. _replayPlayback.BeforeSetTick += OnBeforeSetTick;
  45. _replayPlayback.AfterSetTick += OnAfterSetTick;
  46. _replayPlayback.ReplayPlaybackStarted += OnPlaybackStarted;
  47. _replayPlayback.ReplayPlaybackStopped += OnPlaybackStopped;
  48. _replayPlayback.BeforeApplyState += OnBeforeApplyState;
  49. }
  50. public override void Shutdown()
  51. {
  52. base.Shutdown();
  53. _replayPlayback.BeforeSetTick -= OnBeforeSetTick;
  54. _replayPlayback.AfterSetTick -= OnAfterSetTick;
  55. _replayPlayback.ReplayPlaybackStarted -= OnPlaybackStarted;
  56. _replayPlayback.ReplayPlaybackStopped -= OnPlaybackStopped;
  57. _replayPlayback.BeforeApplyState -= OnBeforeApplyState;
  58. }
  59. private void OnPlaybackStarted(MappingDataNode yamlMappingNode, List<object> objects)
  60. {
  61. InitializeMovement();
  62. _conHost.RegisterCommand(SpectateCmd,
  63. Loc.GetString("cmd-replay-spectate-desc"),
  64. Loc.GetString("cmd-replay-spectate-help"),
  65. SpectateCommand,
  66. SpectateCompletions);
  67. if (_replayPlayback.TryGetRecorderEntity(out var recorder))
  68. SpectateEntity(recorder.Value);
  69. else
  70. SetSpectatorPosition(default);
  71. }
  72. private void OnPlaybackStopped()
  73. {
  74. ShutdownMovement();
  75. _conHost.UnregisterCommand(SpectateCmd);
  76. }
  77. }