2023-09-10 07:20:27 +01:00
using Content.Shared.Ninja.Components ;
using Content.Shared.DoAfter ;
using Robust.Shared.Serialization ;
namespace Content.Shared.Ninja.Systems ;
/// <summary>
/// Basic draining prediction and API, all real logic is handled serverside.
/// </summary>
public abstract class SharedBatteryDrainerSystem : EntitySystem
{
public override void Initialize ( )
{
base . Initialize ( ) ;
SubscribeLocalEvent < BatteryDrainerComponent , DoAfterAttemptEvent < DrainDoAfterEvent > > ( OnDoAfterAttempt ) ;
SubscribeLocalEvent < BatteryDrainerComponent , DrainDoAfterEvent > ( OnDoAfter ) ;
}
/// <summary>
2024-07-11 05:55:56 +00:00
/// Cancel any drain doafters if the battery is removed or, on the server, gets filled.
2023-09-10 07:20:27 +01:00
/// </summary>
2024-07-11 05:55:56 +00:00
protected virtual void OnDoAfterAttempt ( Entity < BatteryDrainerComponent > ent , ref DoAfterAttemptEvent < DrainDoAfterEvent > args )
2023-09-10 07:20:27 +01:00
{
2024-07-11 05:55:56 +00:00
if ( ent . Comp . BatteryUid = = null )
2023-09-10 07:20:27 +01:00
args . Cancel ( ) ;
}
/// <summary>
/// Drain power from a power source (on server) and repeat if it succeeded.
/// Client will predict always succeeding since power is serverside.
/// </summary>
2024-07-11 05:55:56 +00:00
private void OnDoAfter ( Entity < BatteryDrainerComponent > ent , ref DrainDoAfterEvent args )
2023-09-10 07:20:27 +01:00
{
2024-07-11 05:55:56 +00:00
if ( args . Cancelled | | args . Handled | | args . Target is not { } target )
2023-09-10 07:20:27 +01:00
return ;
// repeat if there is still power to drain
2024-07-11 05:55:56 +00:00
args . Repeat = TryDrainPower ( ent , target ) ;
2023-09-10 07:20:27 +01:00
}
/// <summary>
/// Attempt to drain as much power as possible into the powercell.
/// Client always predicts this as succeeding since power is serverside and it can only fail once, when the powercell is filled or the target is emptied.
/// </summary>
2024-07-11 05:55:56 +00:00
protected virtual bool TryDrainPower ( Entity < BatteryDrainerComponent > ent , EntityUid target )
2023-09-10 07:20:27 +01:00
{
return true ;
}
/// <summary>
/// Sets the battery field on the drainer.
/// </summary>
2024-07-11 05:55:56 +00:00
public void SetBattery ( Entity < BatteryDrainerComponent ? > ent , EntityUid ? battery )
2023-09-10 07:20:27 +01:00
{
2024-07-11 05:55:56 +00:00
if ( ! Resolve ( ent , ref ent . Comp ) | | ent . Comp . BatteryUid = = battery )
2023-09-10 07:20:27 +01:00
return ;
2024-07-11 05:55:56 +00:00
ent . Comp . BatteryUid = battery ;
Dirty ( ent , ent . Comp ) ;
2023-09-10 07:20:27 +01:00
}
}
/// <summary>
/// DoAfter event for <see cref="BatteryDrainerComponent"/>.
/// </summary>
[Serializable, NetSerializable]
2024-07-11 05:55:56 +00:00
public sealed partial class DrainDoAfterEvent : SimpleDoAfterEvent ;