PowerSwitchableSystem.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. using Content.Server.NodeContainer;
  2. using Content.Server.NodeContainer.EntitySystems;
  3. using Content.Server.Popups;
  4. using Content.Server.Power.Components;
  5. using Content.Server.Power.Nodes;
  6. using Content.Shared.Power.Generator;
  7. using Content.Shared.Timing;
  8. using Content.Shared.Verbs;
  9. using Robust.Shared.Audio.Systems;
  10. using Robust.Shared.Utility;
  11. namespace Content.Server.Power.Generator;
  12. /// <summary>
  13. /// Implements server logic for power-switchable devices.
  14. /// </summary>
  15. /// <seealso cref="PowerSwitchableComponent"/>
  16. /// <seealso cref="PortableGeneratorSystem"/>
  17. /// <seealso cref="GeneratorSystem"/>
  18. public sealed class PowerSwitchableSystem : SharedPowerSwitchableSystem
  19. {
  20. [Dependency] private readonly NodeGroupSystem _nodeGroup = default!;
  21. [Dependency] private readonly PopupSystem _popup = default!;
  22. [Dependency] private readonly SharedAudioSystem _audio = default!;
  23. [Dependency] private readonly UseDelaySystem _useDelay = default!;
  24. public override void Initialize()
  25. {
  26. base.Initialize();
  27. SubscribeLocalEvent<PowerSwitchableComponent, GetVerbsEvent<InteractionVerb>>(GetVerbs);
  28. }
  29. private void GetVerbs(EntityUid uid, PowerSwitchableComponent comp, GetVerbsEvent<InteractionVerb> args)
  30. {
  31. if (!args.CanAccess || !args.CanInteract)
  32. return;
  33. var voltage = VoltageColor(GetNextVoltage(uid, comp));
  34. var msg = Loc.GetString("power-switchable-switch-voltage", ("voltage", voltage));
  35. InteractionVerb verb = new()
  36. {
  37. Act = () =>
  38. {
  39. // don't need to check it again since if its disabled server wont let the verb act
  40. Cycle(uid, args.User, comp);
  41. },
  42. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/zap.svg.192dpi.png")),
  43. Text = msg
  44. };
  45. var ev = new SwitchPowerCheckEvent();
  46. RaiseLocalEvent(uid, ref ev);
  47. if (ev.DisableMessage != null)
  48. {
  49. verb.Message = ev.DisableMessage;
  50. verb.Disabled = true;
  51. }
  52. args.Verbs.Add(verb);
  53. }
  54. /// <summary>
  55. /// Cycles voltage then updates nodes and optionally power supplier to match it.
  56. /// </summary>
  57. public void Cycle(EntityUid uid, EntityUid user, PowerSwitchableComponent? comp = null)
  58. {
  59. if (!Resolve(uid, ref comp))
  60. return;
  61. // no sound spamming
  62. if (!TryComp(uid, out UseDelayComponent? useDelay) || _useDelay.IsDelayed((uid, useDelay)))
  63. return;
  64. comp.ActiveIndex = NextIndex(uid, comp);
  65. Dirty(uid, comp);
  66. var voltage = GetVoltage(uid, comp);
  67. if (TryComp<PowerSupplierComponent>(uid, out var supplier))
  68. {
  69. // convert to nodegroupid (goofy server Voltage enum is just alias for it)
  70. switch (voltage)
  71. {
  72. case SwitchableVoltage.HV:
  73. supplier.Voltage = Voltage.High;
  74. break;
  75. case SwitchableVoltage.MV:
  76. supplier.Voltage = Voltage.Medium;
  77. break;
  78. case SwitchableVoltage.LV:
  79. supplier.Voltage = Voltage.Apc;
  80. break;
  81. }
  82. }
  83. // Switching around the voltage on the power supplier is "enough",
  84. // but we also want to disconnect the cable nodes so it doesn't show up in power monitors etc.
  85. var nodeContainer = Comp<NodeContainerComponent>(uid);
  86. foreach (var cable in comp.Cables)
  87. {
  88. var node = (CableDeviceNode) nodeContainer.Nodes[cable.Node];
  89. node.Enabled = cable.Voltage == voltage;
  90. _nodeGroup.QueueReflood(node);
  91. }
  92. var popup = Loc.GetString(comp.SwitchText, ("voltage", VoltageString(voltage)));
  93. _popup.PopupEntity(popup, uid, user);
  94. _audio.PlayPvs(comp.SwitchSound, uid);
  95. _useDelay.TryResetDelay((uid, useDelay));
  96. }
  97. }
  98. /// <summary>
  99. /// Raised on a <see cref="PowerSwitchableComponent"/> to see if its verb should work.
  100. /// If <see cref="DisableMessage"/> is non-null, the verb is disabled with that as the message.
  101. /// </summary>
  102. [ByRefEvent]
  103. public record struct SwitchPowerCheckEvent(string? DisableMessage = null);