224 lines
6.6 KiB
C#
224 lines
6.6 KiB
C#
#nullable enable
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Content.Server.APC.Components;
|
|
using Content.Server.Battery.Components;
|
|
using Content.Server.NodeContainer.NodeGroups;
|
|
using Content.Server.NodeContainer.Nodes;
|
|
using Content.Server.Power.Components;
|
|
using Robust.Shared.GameObjects;
|
|
using Robust.Shared.Map;
|
|
using Robust.Shared.Utility;
|
|
using Robust.Shared.ViewVariables;
|
|
|
|
namespace Content.Server.APC
|
|
{
|
|
public interface IApcNet
|
|
{
|
|
bool Powered { get; }
|
|
|
|
void AddApc(ApcComponent apc);
|
|
|
|
void RemoveApc(ApcComponent apc);
|
|
|
|
void AddPowerProvider(PowerProviderComponent provider);
|
|
|
|
void RemovePowerProvider(PowerProviderComponent provider);
|
|
|
|
void UpdatePowerProviderReceivers(PowerProviderComponent provider, int oldLoad, int newLoad);
|
|
|
|
void Update(float frameTime);
|
|
|
|
GridId? GridId { get; }
|
|
}
|
|
|
|
[NodeGroup(NodeGroupID.Apc)]
|
|
public class ApcNetNodeGroup : BaseNetConnectorNodeGroup<BaseApcNetComponent, IApcNet>, IApcNet
|
|
{
|
|
[ViewVariables]
|
|
private readonly Dictionary<ApcComponent, BatteryComponent> _apcBatteries = new();
|
|
|
|
[ViewVariables]
|
|
private readonly List<PowerProviderComponent> _providers = new();
|
|
|
|
[ViewVariables]
|
|
public bool Powered { get => _powered; private set => SetPowered(value); }
|
|
private bool _powered = false;
|
|
|
|
//Debug property
|
|
[ViewVariables]
|
|
private int TotalReceivers => _providers.SelectMany(provider => provider.LinkedReceivers).Count();
|
|
|
|
[ViewVariables]
|
|
private int TotalPowerReceiverLoad { get => _totalPowerReceiverLoad; set => SetTotalPowerReceiverLoad(value); }
|
|
|
|
GridId? IApcNet.GridId => GridId;
|
|
|
|
private int _totalPowerReceiverLoad = 0;
|
|
|
|
public static readonly IApcNet NullNet = new NullApcNet();
|
|
|
|
public override void Initialize(Node sourceNode)
|
|
{
|
|
base.Initialize(sourceNode);
|
|
|
|
EntitySystem.Get<ApcNetSystem>().AddApcNet(this);
|
|
}
|
|
|
|
protected override void AfterRemake(IEnumerable<INodeGroup> newGroups)
|
|
{
|
|
base.AfterRemake(newGroups);
|
|
|
|
foreach (var group in newGroups)
|
|
{
|
|
if (group is not ApcNetNodeGroup apcNet)
|
|
continue;
|
|
|
|
apcNet.Powered = Powered;
|
|
}
|
|
|
|
StopUpdates();
|
|
}
|
|
|
|
protected override void OnGivingNodesForCombine(INodeGroup newGroup)
|
|
{
|
|
base.OnGivingNodesForCombine(newGroup);
|
|
|
|
if (newGroup is ApcNetNodeGroup apcNet)
|
|
{
|
|
apcNet.Powered = Powered;
|
|
}
|
|
|
|
StopUpdates();
|
|
}
|
|
|
|
private void StopUpdates()
|
|
{
|
|
EntitySystem.Get<ApcNetSystem>().RemoveApcNet(this);
|
|
}
|
|
|
|
#region IApcNet Methods
|
|
|
|
protected override void SetNetConnectorNet(BaseApcNetComponent netConnectorComponent)
|
|
{
|
|
netConnectorComponent.Net = this;
|
|
}
|
|
|
|
public void AddApc(ApcComponent apc)
|
|
{
|
|
if (!apc.Owner.TryGetComponent(out BatteryComponent? battery))
|
|
{
|
|
return;
|
|
}
|
|
|
|
_apcBatteries.Add(apc, battery);
|
|
}
|
|
|
|
public void RemoveApc(ApcComponent apc)
|
|
{
|
|
_apcBatteries.Remove(apc);
|
|
}
|
|
|
|
public void AddPowerProvider(PowerProviderComponent provider)
|
|
{
|
|
_providers.Add(provider);
|
|
|
|
foreach (var receiver in provider.LinkedReceivers)
|
|
{
|
|
TotalPowerReceiverLoad += receiver.Load;
|
|
}
|
|
}
|
|
|
|
public void RemovePowerProvider(PowerProviderComponent provider)
|
|
{
|
|
_providers.Remove(provider);
|
|
|
|
foreach (var receiver in provider.LinkedReceivers)
|
|
{
|
|
TotalPowerReceiverLoad -= receiver.Load;
|
|
}
|
|
}
|
|
|
|
public void UpdatePowerProviderReceivers(PowerProviderComponent provider, int oldLoad, int newLoad)
|
|
{
|
|
DebugTools.Assert(_providers.Contains(provider));
|
|
TotalPowerReceiverLoad -= oldLoad;
|
|
TotalPowerReceiverLoad += newLoad;
|
|
}
|
|
|
|
public void Update(float frameTime)
|
|
{
|
|
var remainingPowerNeeded = TotalPowerReceiverLoad * frameTime;
|
|
|
|
foreach (var apcBatteryPair in _apcBatteries)
|
|
{
|
|
var apc = apcBatteryPair.Key;
|
|
|
|
if (!apc.MainBreakerEnabled)
|
|
continue;
|
|
|
|
var battery = apcBatteryPair.Value;
|
|
|
|
if (battery.CurrentCharge < remainingPowerNeeded)
|
|
{
|
|
remainingPowerNeeded -= battery.CurrentCharge;
|
|
battery.CurrentCharge = 0;
|
|
}
|
|
else
|
|
{
|
|
battery.UseCharge(remainingPowerNeeded);
|
|
remainingPowerNeeded = 0;
|
|
}
|
|
|
|
if (remainingPowerNeeded == 0)
|
|
break;
|
|
}
|
|
|
|
Powered = remainingPowerNeeded == 0;
|
|
}
|
|
|
|
private void SetPowered(bool powered)
|
|
{
|
|
if (powered != Powered)
|
|
{
|
|
_powered = powered;
|
|
PoweredChanged();
|
|
}
|
|
}
|
|
|
|
private void PoweredChanged()
|
|
{
|
|
foreach (var provider in _providers)
|
|
{
|
|
foreach (var receiver in provider.LinkedReceivers)
|
|
{
|
|
receiver.ApcPowerChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SetTotalPowerReceiverLoad(int totalPowerReceiverLoad)
|
|
{
|
|
DebugTools.Assert(totalPowerReceiverLoad >= 0, $"Expected load equal to or greater than 0, was {totalPowerReceiverLoad}");
|
|
_totalPowerReceiverLoad = totalPowerReceiverLoad;
|
|
}
|
|
|
|
#endregion
|
|
|
|
private class NullApcNet : IApcNet
|
|
{
|
|
/// <summary>
|
|
/// It is important that this returns false, so <see cref="PowerProviderComponent"/>s with a <see cref="NullApcNet"/> have no power.
|
|
/// </summary>
|
|
public bool Powered => false;
|
|
public GridId? GridId => default;
|
|
public void AddApc(ApcComponent apc) { }
|
|
public void AddPowerProvider(PowerProviderComponent provider) { }
|
|
public void RemoveApc(ApcComponent apc) { }
|
|
public void RemovePowerProvider(PowerProviderComponent provider) { }
|
|
public void UpdatePowerProviderReceivers(PowerProviderComponent provider, int oldLoad, int newLoad) { }
|
|
public void Update(float frameTime) { }
|
|
}
|
|
}
|
|
}
|