1
0

TabletopSystem.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. using Content.Server.Popups;
  2. using Content.Server.Tabletop.Components;
  3. using Content.Shared.CCVar;
  4. using Content.Shared.Hands.Components;
  5. using Content.Shared.Interaction;
  6. using Content.Shared.Item;
  7. using Content.Shared.Tabletop;
  8. using Content.Shared.Tabletop.Components;
  9. using Content.Shared.Tabletop.Events;
  10. using Content.Shared.Verbs;
  11. using JetBrains.Annotations;
  12. using Robust.Server.GameObjects;
  13. using Robust.Shared.Configuration;
  14. using Robust.Shared.Enums;
  15. using Robust.Shared.Map;
  16. using Robust.Shared.Player;
  17. using Robust.Shared.Utility;
  18. namespace Content.Server.Tabletop
  19. {
  20. [UsedImplicitly]
  21. public sealed partial class TabletopSystem : SharedTabletopSystem
  22. {
  23. [Dependency] private readonly IMapManager _mapManager = default!;
  24. [Dependency] private readonly EyeSystem _eye = default!;
  25. [Dependency] private readonly ViewSubscriberSystem _viewSubscriberSystem = default!;
  26. [Dependency] private readonly PopupSystem _popupSystem = default!;
  27. [Dependency] private readonly IConfigurationManager _cfg = default!;
  28. public override void Initialize()
  29. {
  30. base.Initialize();
  31. SubscribeNetworkEvent<TabletopStopPlayingEvent>(OnStopPlaying);
  32. SubscribeLocalEvent<TabletopGameComponent, ActivateInWorldEvent>(OnTabletopActivate);
  33. SubscribeLocalEvent<TabletopGameComponent, ComponentShutdown>(OnGameShutdown);
  34. SubscribeLocalEvent<TabletopGamerComponent, PlayerDetachedEvent>(OnPlayerDetached);
  35. SubscribeLocalEvent<TabletopGamerComponent, ComponentShutdown>(OnGamerShutdown);
  36. SubscribeLocalEvent<TabletopGameComponent, GetVerbsEvent<ActivationVerb>>(AddPlayGameVerb);
  37. SubscribeLocalEvent<TabletopGameComponent, InteractUsingEvent>(OnInteractUsing);
  38. SubscribeNetworkEvent<TabletopRequestTakeOut>(OnTabletopRequestTakeOut);
  39. InitializeMap();
  40. }
  41. private void OnTabletopRequestTakeOut(TabletopRequestTakeOut msg, EntitySessionEventArgs args)
  42. {
  43. if (args.SenderSession is not { } playerSession)
  44. return;
  45. var table = GetEntity(msg.TableUid);
  46. if (!TryComp(table, out TabletopGameComponent? tabletop) || tabletop.Session is not { } session)
  47. return;
  48. if (!msg.Entity.IsValid())
  49. return;
  50. var entity = GetEntity(msg.Entity);
  51. if (!TryComp(entity, out TabletopHologramComponent? hologram))
  52. {
  53. _popupSystem.PopupEntity(Loc.GetString("tabletop-error-remove-non-hologram"), table, args.SenderSession);
  54. return;
  55. }
  56. // Check if player is actually playing at this table
  57. if (!session.Players.ContainsKey(playerSession))
  58. return;
  59. // Find the entity, remove it from the session and set it's position to the tabletop
  60. session.Entities.TryGetValue(entity, out var result);
  61. session.Entities.Remove(result);
  62. QueueDel(result);
  63. }
  64. private void OnInteractUsing(EntityUid uid, TabletopGameComponent component, InteractUsingEvent args)
  65. {
  66. if (!_cfg.GetCVar(CCVars.GameTabletopPlace))
  67. return;
  68. if (!EntityManager.TryGetComponent(args.User, out HandsComponent? hands))
  69. return;
  70. if (component.Session is not { } session)
  71. return;
  72. if (hands.ActiveHand == null)
  73. return;
  74. if (hands.ActiveHand.HeldEntity == null)
  75. return;
  76. var handEnt = hands.ActiveHand.HeldEntity.Value;
  77. if (!TryComp<ItemComponent>(handEnt, out var item))
  78. return;
  79. var meta = MetaData(handEnt);
  80. var protoId = meta.EntityPrototype?.ID;
  81. var hologram = Spawn(protoId, session.Position.Offset(-1, 0));
  82. // Make sure the entity can be dragged and can be removed, move it into the board game world and add it to the Entities hashmap
  83. EnsureComp<TabletopDraggableComponent>(hologram);
  84. EnsureComp<TabletopHologramComponent>(hologram);
  85. session.Entities.Add(hologram);
  86. _popupSystem.PopupEntity(Loc.GetString("tabletop-added-piece"), uid, args.User);
  87. }
  88. protected override void OnTabletopMove(TabletopMoveEvent msg, EntitySessionEventArgs args)
  89. {
  90. if (args.SenderSession is not { } playerSession)
  91. return;
  92. if (!TryComp(GetEntity(msg.TableUid), out TabletopGameComponent? tabletop) || tabletop.Session is not { } session)
  93. return;
  94. // Check if player is actually playing at this table
  95. if (!session.Players.ContainsKey(playerSession))
  96. return;
  97. base.OnTabletopMove(msg, args);
  98. }
  99. /// <summary>
  100. /// Add a verb that allows the player to start playing a tabletop game.
  101. /// </summary>
  102. private void AddPlayGameVerb(EntityUid uid, TabletopGameComponent component, GetVerbsEvent<ActivationVerb> args)
  103. {
  104. if (!args.CanAccess || !args.CanInteract)
  105. return;
  106. if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
  107. return;
  108. var playVerb = new ActivationVerb()
  109. {
  110. Text = Loc.GetString("tabletop-verb-play-game"),
  111. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/die.svg.192dpi.png")),
  112. Act = () => OpenSessionFor(actor.PlayerSession, uid)
  113. };
  114. args.Verbs.Add(playVerb);
  115. }
  116. private void OnTabletopActivate(EntityUid uid, TabletopGameComponent component, ActivateInWorldEvent args)
  117. {
  118. if (args.Handled || !args.Complex)
  119. return;
  120. // Check that a player is attached to the entity.
  121. if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
  122. return;
  123. OpenSessionFor(actor.PlayerSession, uid);
  124. }
  125. private void OnGameShutdown(EntityUid uid, TabletopGameComponent component, ComponentShutdown args)
  126. {
  127. CleanupSession(uid);
  128. }
  129. private void OnStopPlaying(TabletopStopPlayingEvent msg, EntitySessionEventArgs args)
  130. {
  131. CloseSessionFor(args.SenderSession, GetEntity(msg.TableUid));
  132. }
  133. private void OnPlayerDetached(EntityUid uid, TabletopGamerComponent component, PlayerDetachedEvent args)
  134. {
  135. if(component.Tabletop.IsValid())
  136. CloseSessionFor(args.Player, component.Tabletop);
  137. }
  138. private void OnGamerShutdown(EntityUid uid, TabletopGamerComponent component, ComponentShutdown args)
  139. {
  140. if (!EntityManager.TryGetComponent(uid, out ActorComponent? actor))
  141. return;
  142. if(component.Tabletop.IsValid())
  143. CloseSessionFor(actor.PlayerSession, component.Tabletop);
  144. }
  145. public override void Update(float frameTime)
  146. {
  147. base.Update(frameTime);
  148. var query = EntityQueryEnumerator<TabletopGamerComponent>();
  149. while (query.MoveNext(out var uid, out var gamer))
  150. {
  151. if (!Exists(gamer.Tabletop))
  152. continue;
  153. if (!TryComp(uid, out ActorComponent? actor))
  154. {
  155. EntityManager.RemoveComponent<TabletopGamerComponent>(uid);
  156. return;
  157. }
  158. if (actor.PlayerSession.Status != SessionStatus.InGame || !CanSeeTable(uid, gamer.Tabletop))
  159. CloseSessionFor(actor.PlayerSession, gamer.Tabletop);
  160. }
  161. }
  162. }
  163. }