MoverController.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. using Content.Shared.Alert;
  2. using Content.Shared.CCVar;
  3. using Content.Shared.Movement.Components;
  4. using Content.Shared.Movement.Pulling.Components;
  5. using Content.Shared.Movement.Systems;
  6. using Robust.Client.GameObjects;
  7. using Robust.Client.Physics;
  8. using Robust.Client.Player;
  9. using Robust.Shared.Configuration;
  10. using Robust.Shared.Physics.Components;
  11. using Robust.Shared.Player;
  12. using Robust.Shared.Timing;
  13. namespace Content.Client.Physics.Controllers;
  14. public sealed class MoverController : SharedMoverController
  15. {
  16. [Dependency] private readonly IGameTiming _timing = default!;
  17. [Dependency] private readonly IPlayerManager _playerManager = default!;
  18. [Dependency] private readonly AlertsSystem _alerts = default!;
  19. [Dependency] private readonly IConfigurationManager _cfg = default!;
  20. public override void Initialize()
  21. {
  22. base.Initialize();
  23. SubscribeLocalEvent<RelayInputMoverComponent, LocalPlayerAttachedEvent>(OnRelayPlayerAttached);
  24. SubscribeLocalEvent<RelayInputMoverComponent, LocalPlayerDetachedEvent>(OnRelayPlayerDetached);
  25. SubscribeLocalEvent<InputMoverComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
  26. SubscribeLocalEvent<InputMoverComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
  27. SubscribeLocalEvent<InputMoverComponent, UpdateIsPredictedEvent>(OnUpdatePredicted);
  28. SubscribeLocalEvent<MovementRelayTargetComponent, UpdateIsPredictedEvent>(OnUpdateRelayTargetPredicted);
  29. SubscribeLocalEvent<PullableComponent, UpdateIsPredictedEvent>(OnUpdatePullablePredicted);
  30. }
  31. private void OnUpdatePredicted(Entity<InputMoverComponent> entity, ref UpdateIsPredictedEvent args)
  32. {
  33. // Enable prediction if an entity is controlled by the player
  34. if (entity.Owner == _playerManager.LocalEntity)
  35. args.IsPredicted = true;
  36. }
  37. private void OnUpdateRelayTargetPredicted(Entity<MovementRelayTargetComponent> entity, ref UpdateIsPredictedEvent args)
  38. {
  39. if (entity.Comp.Source == _playerManager.LocalEntity)
  40. args.IsPredicted = true;
  41. }
  42. private void OnUpdatePullablePredicted(Entity<PullableComponent> entity, ref UpdateIsPredictedEvent args)
  43. {
  44. // Enable prediction if an entity is being pulled by the player.
  45. // Disable prediction if an entity is being pulled by some non-player entity.
  46. if (entity.Comp.Puller == _playerManager.LocalEntity)
  47. args.IsPredicted = true;
  48. else if (entity.Comp.Puller != null)
  49. args.BlockPrediction = true;
  50. // TODO recursive pulling checks?
  51. // What if the entity is being pulled by a vehicle controlled by the player?
  52. }
  53. private void OnRelayPlayerAttached(Entity<RelayInputMoverComponent> entity, ref LocalPlayerAttachedEvent args)
  54. {
  55. Physics.UpdateIsPredicted(entity.Owner);
  56. Physics.UpdateIsPredicted(entity.Comp.RelayEntity);
  57. if (MoverQuery.TryGetComponent(entity.Comp.RelayEntity, out var inputMover))
  58. SetMoveInput((entity.Comp.RelayEntity, inputMover), MoveButtons.None);
  59. }
  60. private void OnRelayPlayerDetached(Entity<RelayInputMoverComponent> entity, ref LocalPlayerDetachedEvent args)
  61. {
  62. Physics.UpdateIsPredicted(entity.Owner);
  63. Physics.UpdateIsPredicted(entity.Comp.RelayEntity);
  64. if (MoverQuery.TryGetComponent(entity.Comp.RelayEntity, out var inputMover))
  65. SetMoveInput((entity.Comp.RelayEntity, inputMover), MoveButtons.None);
  66. }
  67. private void OnPlayerAttached(Entity<InputMoverComponent> entity, ref LocalPlayerAttachedEvent args)
  68. {
  69. SetMoveInput(entity, MoveButtons.None);
  70. }
  71. private void OnPlayerDetached(Entity<InputMoverComponent> entity, ref LocalPlayerDetachedEvent args)
  72. {
  73. SetMoveInput(entity, MoveButtons.None);
  74. }
  75. public override void UpdateBeforeSolve(bool prediction, float frameTime)
  76. {
  77. base.UpdateBeforeSolve(prediction, frameTime);
  78. if (_playerManager.LocalEntity is not {Valid: true} player)
  79. return;
  80. if (RelayQuery.TryGetComponent(player, out var relayMover))
  81. HandleClientsideMovement(relayMover.RelayEntity, frameTime);
  82. HandleClientsideMovement(player, frameTime);
  83. }
  84. private void HandleClientsideMovement(EntityUid player, float frameTime)
  85. {
  86. if (!MoverQuery.TryGetComponent(player, out var mover) ||
  87. !XformQuery.TryGetComponent(player, out var xform))
  88. {
  89. return;
  90. }
  91. var physicsUid = player;
  92. PhysicsComponent? body;
  93. var xformMover = xform;
  94. if (mover.ToParent && RelayQuery.HasComponent(xform.ParentUid))
  95. {
  96. if (!PhysicsQuery.TryGetComponent(xform.ParentUid, out body) ||
  97. !XformQuery.TryGetComponent(xform.ParentUid, out xformMover))
  98. {
  99. return;
  100. }
  101. physicsUid = xform.ParentUid;
  102. }
  103. else if (!PhysicsQuery.TryGetComponent(player, out body))
  104. {
  105. return;
  106. }
  107. // Server-side should just be handled on its own so we'll just do this shizznit
  108. HandleMobMovement(
  109. player,
  110. mover,
  111. physicsUid,
  112. body,
  113. xformMover,
  114. frameTime);
  115. }
  116. protected override bool CanSound()
  117. {
  118. return _timing is { IsFirstTimePredicted: true, InSimulation: true };
  119. }
  120. public override void SetSprinting(Entity<InputMoverComponent> entity, ushort subTick, bool walking)
  121. {
  122. // Logger.Info($"[{_gameTiming.CurTick}/{subTick}] Sprint: {enabled}");
  123. base.SetSprinting(entity, subTick, walking);
  124. if (walking && _cfg.GetCVar(CCVars.ToggleWalk))
  125. _alerts.ShowAlert(entity, WalkingAlert, showCooldown: false, autoRemove: false);
  126. else
  127. _alerts.ClearAlert(entity, WalkingAlert);
  128. }
  129. }