1
0

SandboxSystem.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. using System.Linq;
  2. using Content.Server.GameTicking;
  3. using Content.Shared.Access;
  4. using Content.Shared.Access.Components;
  5. using Content.Shared.Access.Systems;
  6. using Content.Shared.Containers.ItemSlots;
  7. using Content.Shared.Hands.Components;
  8. using Content.Shared.Hands.EntitySystems;
  9. using Content.Shared.Inventory;
  10. using Content.Shared.PDA;
  11. using Content.Shared.Sandbox;
  12. using Robust.Server.Console;
  13. using Robust.Server.Placement;
  14. using Robust.Server.Player;
  15. using Robust.Shared.Enums;
  16. using Robust.Shared.Player;
  17. using Robust.Shared.Prototypes;
  18. namespace Content.Server.Sandbox
  19. {
  20. public sealed class SandboxSystem : SharedSandboxSystem
  21. {
  22. [Dependency] private readonly IPlayerManager _playerManager = default!;
  23. [Dependency] private readonly IPlacementManager _placementManager = default!;
  24. [Dependency] private readonly IConGroupController _conGroupController = default!;
  25. [Dependency] private readonly IServerConsoleHost _host = default!;
  26. [Dependency] private readonly SharedAccessSystem _access = default!;
  27. [Dependency] private readonly InventorySystem _inventory = default!;
  28. [Dependency] private readonly ItemSlotsSystem _slots = default!;
  29. [Dependency] private readonly GameTicker _ticker = default!;
  30. [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
  31. private bool _isSandboxEnabled;
  32. [ViewVariables(VVAccess.ReadWrite)]
  33. public bool IsSandboxEnabled
  34. {
  35. get => _isSandboxEnabled;
  36. set
  37. {
  38. _isSandboxEnabled = value;
  39. UpdateSandboxStatusForAll();
  40. }
  41. }
  42. public override void Initialize()
  43. {
  44. base.Initialize();
  45. SubscribeNetworkEvent<MsgSandboxRespawn>(SandboxRespawnReceived);
  46. SubscribeNetworkEvent<MsgSandboxGiveAccess>(SandboxGiveAccessReceived);
  47. SubscribeNetworkEvent<MsgSandboxGiveAghost>(SandboxGiveAghostReceived);
  48. SubscribeNetworkEvent<MsgSandboxSuicide>(SandboxSuicideReceived);
  49. SubscribeLocalEvent<GameRunLevelChangedEvent>(GameTickerOnOnRunLevelChanged);
  50. _playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
  51. _placementManager.AllowPlacementFunc = placement =>
  52. {
  53. if (IsSandboxEnabled)
  54. {
  55. return true;
  56. }
  57. var channel = placement.MsgChannel;
  58. var player = _playerManager.GetSessionByChannel(channel);
  59. if (_conGroupController.CanAdminPlace(player))
  60. {
  61. return true;
  62. }
  63. return false;
  64. };
  65. }
  66. public override void Shutdown()
  67. {
  68. base.Shutdown();
  69. _placementManager.AllowPlacementFunc = null;
  70. _playerManager.PlayerStatusChanged -= OnPlayerStatusChanged;
  71. }
  72. private void GameTickerOnOnRunLevelChanged(GameRunLevelChangedEvent obj)
  73. {
  74. // Automatically clear sandbox state when round resets.
  75. if (obj.New == GameRunLevel.PreRoundLobby)
  76. {
  77. IsSandboxEnabled = false;
  78. }
  79. }
  80. private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
  81. {
  82. if (e.NewStatus != SessionStatus.Connected || e.OldStatus != SessionStatus.Connecting)
  83. return;
  84. RaiseNetworkEvent(new MsgSandboxStatus { SandboxAllowed = IsSandboxEnabled }, e.Session.Channel);
  85. }
  86. private void SandboxRespawnReceived(MsgSandboxRespawn message, EntitySessionEventArgs args)
  87. {
  88. if (!IsSandboxEnabled)
  89. return;
  90. var player = _playerManager.GetSessionByChannel(args.SenderSession.Channel);
  91. if (player.AttachedEntity == null) return;
  92. _ticker.Respawn(player);
  93. }
  94. private void SandboxGiveAccessReceived(MsgSandboxGiveAccess message, EntitySessionEventArgs args)
  95. {
  96. if (!IsSandboxEnabled)
  97. return;
  98. var player = _playerManager.GetSessionByChannel(args.SenderSession.Channel);
  99. if (player.AttachedEntity is not { } attached)
  100. {
  101. return;
  102. }
  103. var allAccess = PrototypeManager
  104. .EnumeratePrototypes<AccessLevelPrototype>()
  105. .Select(p => new ProtoId<AccessLevelPrototype>(p.ID)).ToList();
  106. if (_inventory.TryGetSlotEntity(attached, "id", out var slotEntity))
  107. {
  108. if (HasComp<AccessComponent>(slotEntity))
  109. {
  110. UpgradeId(slotEntity.Value);
  111. }
  112. else if (TryComp<PdaComponent>(slotEntity, out var pda))
  113. {
  114. if (pda.ContainedId is null)
  115. {
  116. var newID = CreateFreshId();
  117. if (TryComp<ItemSlotsComponent>(slotEntity, out var itemSlots))
  118. {
  119. _slots.TryInsert(slotEntity.Value, pda.IdSlot, newID, null);
  120. }
  121. }
  122. else
  123. {
  124. UpgradeId(pda.ContainedId!.Value);
  125. }
  126. }
  127. }
  128. else if (TryComp<HandsComponent>(attached, out var hands))
  129. {
  130. var card = CreateFreshId();
  131. if (!_inventory.TryEquip(attached, card, "id", true, true))
  132. {
  133. _handsSystem.PickupOrDrop(attached, card, handsComp: hands);
  134. }
  135. }
  136. void UpgradeId(EntityUid id)
  137. {
  138. _access.TrySetTags(id, allAccess);
  139. }
  140. EntityUid CreateFreshId()
  141. {
  142. var card = Spawn("CaptainIDCard", Transform(attached).Coordinates);
  143. UpgradeId(card);
  144. Comp<IdCardComponent>(card).FullName = MetaData(attached).EntityName;
  145. return card;
  146. }
  147. }
  148. private void SandboxGiveAghostReceived(MsgSandboxGiveAghost message, EntitySessionEventArgs args)
  149. {
  150. if (!IsSandboxEnabled)
  151. return;
  152. var player = _playerManager.GetSessionByChannel(args.SenderSession.Channel);
  153. _host.ExecuteCommand(player, _conGroupController.CanCommand(player, "aghost") ? "aghost" : "ghost");
  154. }
  155. private void SandboxSuicideReceived(MsgSandboxSuicide message, EntitySessionEventArgs args)
  156. {
  157. if (!IsSandboxEnabled)
  158. return;
  159. var player = _playerManager.GetSessionByChannel(args.SenderSession.Channel);
  160. _host.ExecuteCommand(player, "suicide");
  161. }
  162. private void UpdateSandboxStatusForAll()
  163. {
  164. RaiseNetworkEvent(new MsgSandboxStatus { SandboxAllowed = IsSandboxEnabled });
  165. }
  166. }
  167. }