SharedContentEyeSystem.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. using System.Numerics;
  2. using Content.Shared.Administration;
  3. using Content.Shared.Administration.Managers;
  4. using Content.Shared.Camera;
  5. using Content.Shared.Ghost;
  6. using Content.Shared.Input;
  7. using Content.Shared.Movement.Components;
  8. using Robust.Shared.Input.Binding;
  9. using Robust.Shared.Player;
  10. using Robust.Shared.Serialization;
  11. namespace Content.Shared.Movement.Systems;
  12. /// <summary>
  13. /// Lets specific sessions scroll and set their zoom directly.
  14. /// </summary>
  15. public abstract class SharedContentEyeSystem : EntitySystem
  16. {
  17. [Dependency] private readonly ISharedAdminManager _admin = default!;
  18. // Admin flags required to ignore normal eye restrictions.
  19. public const AdminFlags EyeFlag = AdminFlags.Debug;
  20. public const float ZoomMod = 1.5f;
  21. public static readonly Vector2 DefaultZoom = Vector2.One;
  22. public static readonly Vector2 MinZoom = DefaultZoom * (float)Math.Pow(ZoomMod, -3);
  23. [Dependency] private readonly SharedEyeSystem _eye = default!;
  24. public override void Initialize()
  25. {
  26. base.Initialize();
  27. SubscribeLocalEvent<ContentEyeComponent, ComponentStartup>(OnContentEyeStartup);
  28. SubscribeAllEvent<RequestTargetZoomEvent>(OnContentZoomRequest);
  29. SubscribeAllEvent<RequestPvsScaleEvent>(OnPvsScale);
  30. SubscribeAllEvent<RequestEyeEvent>(OnRequestEye);
  31. CommandBinds.Builder
  32. .Bind(ContentKeyFunctions.ZoomIn, InputCmdHandler.FromDelegate(ZoomIn, handle:false))
  33. .Bind(ContentKeyFunctions.ZoomOut, InputCmdHandler.FromDelegate(ZoomOut, handle:false))
  34. .Bind(ContentKeyFunctions.ResetZoom, InputCmdHandler.FromDelegate(ResetZoom, handle:false))
  35. .Register<SharedContentEyeSystem>();
  36. Log.Level = LogLevel.Info;
  37. UpdatesOutsidePrediction = true;
  38. }
  39. public override void Shutdown()
  40. {
  41. base.Shutdown();
  42. CommandBinds.Unregister<SharedContentEyeSystem>();
  43. }
  44. private void ResetZoom(ICommonSession? session)
  45. {
  46. if (TryComp(session?.AttachedEntity, out ContentEyeComponent? eye))
  47. ResetZoom(session.AttachedEntity.Value, eye);
  48. }
  49. private void ZoomOut(ICommonSession? session)
  50. {
  51. if (TryComp(session?.AttachedEntity, out ContentEyeComponent? eye))
  52. SetZoom(session.AttachedEntity.Value, eye.TargetZoom * ZoomMod, eye: eye);
  53. }
  54. private void ZoomIn(ICommonSession? session)
  55. {
  56. if (TryComp(session?.AttachedEntity, out ContentEyeComponent? eye))
  57. SetZoom(session.AttachedEntity.Value, eye.TargetZoom / ZoomMod, eye: eye);
  58. }
  59. private Vector2 Clamp(Vector2 zoom, ContentEyeComponent component)
  60. {
  61. return Vector2.Clamp(zoom, MinZoom, component.MaxZoom);
  62. }
  63. /// <summary>
  64. /// Sets the target zoom, optionally ignoring normal zoom limits.
  65. /// </summary>
  66. public void SetZoom(EntityUid uid, Vector2 zoom, bool ignoreLimits = false, ContentEyeComponent? eye = null)
  67. {
  68. if (!Resolve(uid, ref eye, false))
  69. return;
  70. eye.TargetZoom = ignoreLimits ? zoom : Clamp(zoom, eye);
  71. Dirty(uid, eye);
  72. }
  73. private void OnContentZoomRequest(RequestTargetZoomEvent msg, EntitySessionEventArgs args)
  74. {
  75. var ignoreLimit = msg.IgnoreLimit && _admin.HasAdminFlag(args.SenderSession, EyeFlag);
  76. if (TryComp<ContentEyeComponent>(args.SenderSession.AttachedEntity, out var content))
  77. SetZoom(args.SenderSession.AttachedEntity.Value, msg.TargetZoom, ignoreLimit, eye: content);
  78. }
  79. private void OnPvsScale(RequestPvsScaleEvent ev, EntitySessionEventArgs args)
  80. {
  81. if (args.SenderSession.AttachedEntity is {} uid && _admin.HasAdminFlag(args.SenderSession, EyeFlag))
  82. _eye.SetPvsScale(uid, ev.Scale);
  83. }
  84. private void OnRequestEye(RequestEyeEvent msg, EntitySessionEventArgs args)
  85. {
  86. if (args.SenderSession.AttachedEntity is not { } player)
  87. return;
  88. if (!HasComp<GhostComponent>(player) && !_admin.IsAdmin(player))
  89. return;
  90. if (TryComp<EyeComponent>(player, out var eyeComp))
  91. {
  92. _eye.SetDrawFov(player, msg.DrawFov, eyeComp);
  93. _eye.SetDrawLight((player, eyeComp), msg.DrawLight);
  94. }
  95. }
  96. private void OnContentEyeStartup(EntityUid uid, ContentEyeComponent component, ComponentStartup args)
  97. {
  98. if (!TryComp<EyeComponent>(uid, out var eyeComp))
  99. return;
  100. _eye.SetZoom(uid, component.TargetZoom, eyeComp);
  101. Dirty(uid, component);
  102. }
  103. public void ResetZoom(EntityUid uid, ContentEyeComponent? component = null)
  104. {
  105. _eye.SetPvsScale(uid, 1);
  106. SetZoom(uid, DefaultZoom, eye: component);
  107. }
  108. public void SetMaxZoom(EntityUid uid, Vector2 value, ContentEyeComponent? component = null)
  109. {
  110. if (!Resolve(uid, ref component))
  111. return;
  112. component.MaxZoom = value;
  113. component.TargetZoom = Clamp(component.TargetZoom, component);
  114. Dirty(uid, component);
  115. }
  116. public void UpdateEyeOffset(Entity<EyeComponent> eye)
  117. {
  118. var ev = new GetEyeOffsetEvent();
  119. //RaiseLocalEvent(eye, ref ev);
  120. var evRelayed = new GetEyeOffsetRelayedEvent();
  121. RaiseLocalEvent(eye, ref evRelayed);
  122. _eye.SetOffset(eye, ev.Offset + evRelayed.Offset, eye);
  123. }
  124. public void UpdatePvsScale(EntityUid uid, ContentEyeComponent? contentEye = null, EyeComponent? eye = null)
  125. {
  126. if (!Resolve(uid, ref contentEye) || !Resolve(uid, ref eye))
  127. return;
  128. var ev = new GetEyePvsScaleEvent();
  129. RaiseLocalEvent(uid, ref ev);
  130. var evRelayed = new GetEyePvsScaleRelayedEvent();
  131. RaiseLocalEvent(uid, ref evRelayed);
  132. _eye.SetPvsScale((uid, eye), 1 + ev.Scale + evRelayed.Scale);
  133. }
  134. /// <summary>
  135. /// Sendable from client to server to request a target zoom.
  136. /// </summary>
  137. [Serializable, NetSerializable]
  138. public sealed class RequestTargetZoomEvent : EntityEventArgs
  139. {
  140. public Vector2 TargetZoom;
  141. public bool IgnoreLimit;
  142. }
  143. /// <summary>
  144. /// Client->Server request for new PVS scale.
  145. /// </summary>
  146. [Serializable, NetSerializable]
  147. public sealed class RequestPvsScaleEvent(float scale) : EntityEventArgs
  148. {
  149. public float Scale = scale;
  150. }
  151. /// <summary>
  152. /// Sendable from client to server to request changing fov.
  153. /// </summary>
  154. [Serializable, NetSerializable]
  155. public sealed class RequestEyeEvent : EntityEventArgs
  156. {
  157. public readonly bool DrawFov;
  158. public readonly bool DrawLight;
  159. public RequestEyeEvent(bool drawFov, bool drawLight)
  160. {
  161. DrawFov = drawFov;
  162. DrawLight = drawLight;
  163. }
  164. }
  165. }