using Content.Server.Power.Components;
using Content.Shared.Cargo;
using Content.Shared.Examine;
using Content.Shared.Power;
using Content.Shared.Power.Components;
using Content.Shared.Power.EntitySystems;
using Content.Shared.Rejuvenate;
using JetBrains.Annotations;
using Robust.Shared.Utility;
using Robust.Shared.Timing;
namespace Content.Server.Power.EntitySystems;
///
/// Responsible for .
/// Unpredicted equivalent of .
/// If you make changes to this make sure to keep the two consistent.
///
[UsedImplicitly]
public sealed partial class BatterySystem : SharedBatterySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent(OnInit);
SubscribeLocalEvent(OnExamine);
SubscribeLocalEvent(OnBatteryRejuvenate);
SubscribeLocalEvent(OnNetBatteryRejuvenate);
SubscribeLocalEvent(CalculateBatteryPrice);
SubscribeLocalEvent(OnChangeCharge);
SubscribeLocalEvent(OnGetCharge);
SubscribeLocalEvent(PreSync);
SubscribeLocalEvent(PostSync);
}
private void OnInit(Entity ent, ref ComponentInit args)
{
DebugTools.Assert(!HasComp(ent), $"{ent} has both BatteryComponent and PredictedBatteryComponent");
}
private void OnNetBatteryRejuvenate(Entity ent, ref RejuvenateEvent args)
{
ent.Comp.NetworkBattery.CurrentStorage = ent.Comp.NetworkBattery.Capacity;
}
private void OnBatteryRejuvenate(Entity ent, ref RejuvenateEvent args)
{
SetCharge(ent.AsNullable(), ent.Comp.MaxCharge);
}
private void OnExamine(Entity ent, ref ExaminedEvent args)
{
if (!args.IsInDetailsRange)
return;
if (!HasComp(ent))
return;
var chargePercentRounded = 0;
if (ent.Comp.MaxCharge != 0)
chargePercentRounded = (int)(100 * ent.Comp.CurrentCharge / ent.Comp.MaxCharge);
args.PushMarkup(
Loc.GetString(
"examinable-battery-component-examine-detail",
("percent", chargePercentRounded),
("markupPercentColor", "green")
)
);
}
private void PreSync(NetworkBatteryPreSync ev)
{
// Ignoring entity pausing. If the entity was paused, neither component's data should have been changed.
var enumerator = AllEntityQuery();
while (enumerator.MoveNext(out var netBat, out var bat))
{
DebugTools.Assert(bat.CurrentCharge <= bat.MaxCharge && bat.CurrentCharge >= 0);
netBat.NetworkBattery.Capacity = bat.MaxCharge;
netBat.NetworkBattery.CurrentStorage = bat.CurrentCharge;
}
}
private void PostSync(NetworkBatteryPostSync ev)
{
// Ignoring entity pausing. If the entity was paused, neither component's data should have been changed.
var enumerator = AllEntityQuery();
while (enumerator.MoveNext(out var uid, out var netBat, out var bat))
{
SetCharge((uid, bat), netBat.NetworkBattery.CurrentStorage);
}
}
///
/// Gets the price for the power contained in an entity's battery.
///
private void CalculateBatteryPrice(Entity ent, ref PriceCalculationEvent args)
{
args.Price += ent.Comp.CurrentCharge * ent.Comp.PricePerJoule;
}
private void OnChangeCharge(Entity ent, ref ChangeChargeEvent args)
{
if (args.ResidualValue == 0)
return;
args.ResidualValue -= ChangeCharge(ent.AsNullable(), args.ResidualValue);
}
private void OnGetCharge(Entity entity, ref GetChargeEvent args)
{
args.CurrentCharge += entity.Comp.CurrentCharge;
args.MaxCharge += entity.Comp.MaxCharge;
}
public override void Update(float frameTime)
{
var query = EntityQueryEnumerator();
var curTime = _timing.CurTime;
while (query.MoveNext(out var uid, out var comp, out var bat))
{
if (!comp.AutoRecharge || IsFull((uid, bat)))
continue;
if (comp.NextAutoRecharge > curTime)
continue;
SetCharge((uid, bat), bat.CurrentCharge + comp.AutoRechargeRate * frameTime);
}
}
}