2024-08-25 22:18:42 +10:00
using System.Diagnostics.CodeAnalysis ;
2023-01-20 11:05:54 -05:00
using Content.Server.Administration.Logs ;
2023-04-07 11:21:12 -07:00
using Content.Server.Administration.Managers ;
using Content.Server.Power.Components ;
using Content.Shared.Administration ;
using Content.Shared.Database ;
2022-04-08 17:17:25 -04:00
using Content.Shared.Examine ;
2023-04-07 11:21:12 -07:00
using Content.Shared.Hands.Components ;
2022-04-14 01:50:42 +12:00
using Content.Shared.Power ;
2024-05-29 23:46:22 -07:00
using Content.Shared.Power.Components ;
using Content.Shared.Power.EntitySystems ;
2023-01-20 11:05:54 -05:00
using Content.Shared.Verbs ;
2023-11-27 22:12:34 +11:00
using Robust.Server.Audio ;
2022-10-15 15:08:15 +11:00
using Robust.Server.GameObjects ;
2023-01-20 11:05:54 -05:00
using Robust.Shared.Audio ;
2024-05-29 23:46:22 -07:00
using Robust.Shared.GameStates ;
2023-02-26 18:48:57 +11:00
using Robust.Shared.Utility ;
2022-04-14 01:50:42 +12:00
2021-06-09 22:19:39 +02:00
namespace Content.Server.Power.EntitySystems
2021-05-13 02:05:46 +02:00
{
2024-05-29 23:46:22 -07:00
public sealed class PowerReceiverSystem : SharedPowerReceiverSystem
2021-05-13 02:05:46 +02:00
{
2023-01-20 11:05:54 -05:00
[Dependency] private readonly IAdminLogManager _adminLogger = default ! ;
2023-02-26 06:14:35 +13:00
[Dependency] private readonly IAdminManager _adminManager = default ! ;
2023-01-20 11:05:54 -05:00
[Dependency] private readonly AudioSystem _audio = default ! ;
2024-03-25 11:52:05 +11:00
private EntityQuery < ApcPowerReceiverComponent > _recQuery ;
private EntityQuery < ApcPowerProviderComponent > _provQuery ;
2023-02-26 06:14:35 +13:00
2021-05-13 02:05:46 +02:00
public override void Initialize ( )
{
base . Initialize ( ) ;
2022-04-08 17:17:25 -04:00
SubscribeLocalEvent < ApcPowerReceiverComponent , ExaminedEvent > ( OnExamined ) ;
2021-05-13 02:05:46 +02:00
2021-10-24 01:23:19 +02:00
SubscribeLocalEvent < ApcPowerReceiverComponent , ExtensionCableSystem . ProviderConnectedEvent > ( OnProviderConnected ) ;
SubscribeLocalEvent < ApcPowerReceiverComponent , ExtensionCableSystem . ProviderDisconnectedEvent > ( OnProviderDisconnected ) ;
2021-10-25 21:55:00 +02:00
SubscribeLocalEvent < ApcPowerProviderComponent , ComponentShutdown > ( OnProviderShutdown ) ;
2021-10-24 01:23:19 +02:00
SubscribeLocalEvent < ApcPowerProviderComponent , ExtensionCableSystem . ReceiverConnectedEvent > ( OnReceiverConnected ) ;
SubscribeLocalEvent < ApcPowerProviderComponent , ExtensionCableSystem . ReceiverDisconnectedEvent > ( OnReceiverDisconnected ) ;
2023-01-20 11:05:54 -05:00
2023-02-26 06:14:35 +13:00
SubscribeLocalEvent < ApcPowerReceiverComponent , GetVerbsEvent < Verb > > ( OnGetVerbs ) ;
2023-01-20 11:05:54 -05:00
SubscribeLocalEvent < PowerSwitchComponent , GetVerbsEvent < AlternativeVerb > > ( AddSwitchPowerVerb ) ;
2024-03-25 11:52:05 +11:00
2024-05-29 23:46:22 -07:00
SubscribeLocalEvent < ApcPowerReceiverComponent , ComponentGetState > ( OnGetState ) ;
2024-03-25 11:52:05 +11:00
_recQuery = GetEntityQuery < ApcPowerReceiverComponent > ( ) ;
_provQuery = GetEntityQuery < ApcPowerProviderComponent > ( ) ;
2021-10-24 01:23:19 +02:00
}
2024-07-29 00:28:17 -07:00
private void OnExamined ( Entity < ApcPowerReceiverComponent > ent , ref ExaminedEvent args )
{
args . PushMarkup ( GetExamineText ( ent . Comp . Powered ) ) ;
}
2023-02-26 06:14:35 +13:00
private void OnGetVerbs ( EntityUid uid , ApcPowerReceiverComponent component , GetVerbsEvent < Verb > args )
{
if ( ! _adminManager . HasAdminFlag ( args . User , AdminFlags . Admin ) )
return ;
// add debug verb to toggle power requirements
args . Verbs . Add ( new ( )
{
Text = Loc . GetString ( "verb-debug-toggle-need-power" ) ,
Category = VerbCategory . Debug ,
2023-04-20 20:16:01 +10:00
Icon = new SpriteSpecifier . Texture ( new ( "/Textures/Interface/VerbIcons/smite.svg.192dpi.png" ) ) , // "smite" is a lightning bolt
2023-02-26 06:14:35 +13:00
Act = ( ) = > component . NeedsPower = ! component . NeedsPower
} ) ;
}
2021-10-25 21:55:00 +02:00
private void OnProviderShutdown ( EntityUid uid , ApcPowerProviderComponent component , ComponentShutdown args )
{
foreach ( var receiver in component . LinkedReceivers )
{
receiver . NetworkLoad . LinkedNetwork = default ;
component . Net ? . QueueNetworkReconnect ( ) ;
}
component . LinkedReceivers . Clear ( ) ;
}
2023-10-19 12:34:31 -07:00
private void OnProviderConnected ( Entity < ApcPowerReceiverComponent > receiver , ref ExtensionCableSystem . ProviderConnectedEvent args )
2021-10-24 01:23:19 +02:00
{
2021-12-05 18:09:01 +01:00
var providerUid = args . Provider . Owner ;
2024-03-25 11:52:05 +11:00
if ( ! _provQuery . TryGetComponent ( providerUid , out var provider ) )
2021-10-25 21:55:00 +02:00
return ;
2023-10-19 12:34:31 -07:00
receiver . Comp . Provider = provider ;
2021-10-25 21:55:00 +02:00
2021-10-24 01:23:19 +02:00
ProviderChanged ( receiver ) ;
}
2023-10-19 12:34:31 -07:00
private void OnProviderDisconnected ( Entity < ApcPowerReceiverComponent > receiver , ref ExtensionCableSystem . ProviderDisconnectedEvent args )
2021-10-24 01:23:19 +02:00
{
2023-10-19 12:34:31 -07:00
receiver . Comp . Provider = null ;
2021-10-25 21:55:00 +02:00
2021-10-24 01:23:19 +02:00
ProviderChanged ( receiver ) ;
}
2023-10-19 12:34:31 -07:00
private void OnReceiverConnected ( Entity < ApcPowerProviderComponent > provider , ref ExtensionCableSystem . ReceiverConnectedEvent args )
2021-10-24 01:23:19 +02:00
{
2024-03-25 11:52:05 +11:00
if ( _recQuery . TryGetComponent ( args . Receiver , out var receiver ) )
2021-10-24 01:23:19 +02:00
{
2023-10-19 12:34:31 -07:00
provider . Comp . AddReceiver ( receiver ) ;
2021-10-24 01:23:19 +02:00
}
}
private void OnReceiverDisconnected ( EntityUid uid , ApcPowerProviderComponent provider , ExtensionCableSystem . ReceiverDisconnectedEvent args )
{
2024-03-25 11:52:05 +11:00
if ( _recQuery . TryGetComponent ( args . Receiver , out var receiver ) )
2021-10-24 01:23:19 +02:00
{
provider . RemoveReceiver ( receiver ) ;
}
2021-05-13 02:05:46 +02:00
}
2023-01-20 11:05:54 -05:00
private void AddSwitchPowerVerb ( EntityUid uid , PowerSwitchComponent component , GetVerbsEvent < AlternativeVerb > args )
{
if ( ! args . CanAccess | | ! args . CanInteract )
return ;
if ( ! HasComp < HandsComponent > ( args . User ) )
return ;
2024-03-25 11:52:05 +11:00
if ( ! _recQuery . TryGetComponent ( uid , out var receiver ) )
2023-01-20 11:05:54 -05:00
return ;
if ( ! receiver . NeedsPower )
return ;
AlternativeVerb verb = new ( )
{
Act = ( ) = >
{
TogglePower ( uid , user : args . User ) ;
} ,
2023-04-20 20:16:01 +10:00
Icon = new SpriteSpecifier . Texture ( new ( "/Textures/Interface/VerbIcons/Spare/poweronoff.svg.192dpi.png" ) ) ,
2023-01-20 11:05:54 -05:00
Text = Loc . GetString ( "power-switch-component-toggle-verb" ) ,
Priority = - 3
} ;
args . Verbs . Add ( verb ) ;
}
2024-05-29 23:46:22 -07:00
private void OnGetState ( EntityUid uid , ApcPowerReceiverComponent component , ref ComponentGetState args )
{
args . State = new ApcPowerReceiverComponentState
{
Powered = component . Powered
} ;
}
2023-10-19 12:34:31 -07:00
private void ProviderChanged ( Entity < ApcPowerReceiverComponent > receiver )
2021-05-13 02:05:46 +02:00
{
2023-10-19 12:34:31 -07:00
var comp = receiver . Comp ;
comp . NetworkLoad . LinkedNetwork = default ;
2021-05-13 02:05:46 +02:00
}
2022-08-04 00:05:17 -04:00
/// <summary>
/// If this takes power, it returns whether it has power.
/// Otherwise, it returns 'true' because if something doesn't take power
/// it's effectively always powered.
/// </summary>
2024-05-29 23:46:22 -07:00
/// <returns>True when entity has no ApcPowerReceiverComponent or is Powered. False when not.</returns>
2022-08-04 00:05:17 -04:00
public bool IsPowered ( EntityUid uid , ApcPowerReceiverComponent ? receiver = null )
{
2024-05-29 23:46:22 -07:00
return ! _recQuery . Resolve ( uid , ref receiver , false ) | | receiver . Powered ;
2022-08-04 00:05:17 -04:00
}
2023-01-20 11:05:54 -05:00
/// <summary>
/// Turn this machine on or off.
/// Returns true if we turned it on, false if we turned it off.
/// </summary>
public bool TogglePower ( EntityUid uid , bool playSwitchSound = true , ApcPowerReceiverComponent ? receiver = null , EntityUid ? user = null )
{
2024-03-25 11:52:05 +11:00
if ( ! _recQuery . Resolve ( uid , ref receiver , false ) )
2023-01-20 11:05:54 -05:00
return true ;
// it'll save a lot of confusion if 'always powered' means 'always powered'
if ( ! receiver . NeedsPower )
{
receiver . PowerDisabled = false ;
return true ;
}
receiver . PowerDisabled = ! receiver . PowerDisabled ;
if ( user ! = null )
_adminLogger . Add ( LogType . Action , LogImpact . Low , $"{ToPrettyString(user.Value):player} hit power button on {ToPrettyString(uid)}, it's now {(!receiver.PowerDisabled ? " on " : " off ")}" ) ;
if ( playSwitchSound )
{
_audio . PlayPvs ( new SoundPathSpecifier ( "/Audio/Machines/machine_switch.ogg" ) , uid ,
AudioParams . Default . WithVolume ( - 2f ) ) ;
}
return ! receiver . PowerDisabled ; // i.e. PowerEnabled
}
2024-05-29 23:46:22 -07:00
public void SetLoad ( ApcPowerReceiverComponent comp , float load )
{
comp . Load = load ;
}
2024-08-25 22:18:42 +10:00
public override bool ResolveApc ( EntityUid entity , [ NotNullWhen ( true ) ] ref SharedApcPowerReceiverComponent ? component )
{
if ( component ! = null )
return true ;
if ( ! TryComp ( entity , out ApcPowerReceiverComponent ? receiver ) )
return false ;
component = receiver ;
return true ;
}
2021-05-13 02:05:46 +02:00
}
}