Power System (Complete) (#25)
* Power Commit 1 * Commit 2 * Powernet Part2, All components essentially complete * Commit 4 * Commit 5 * Commit 6 Creates prototypes * Finishes powernet code alpha Adds prototypes and logic for powernet updating and regeneration * Adds onremove functionality to all components Without these bits of logic nothing makes any sense! * And this * Fixes a lot of bugs * Fix powernet thinking devices are duplicates * Fix bug and add comments * woop woop thats the sound of the police
This commit is contained in:
294
Content.Server/GameObjects/Components/Power/PowerDevice.cs
Normal file
294
Content.Server/GameObjects/Components/Power/PowerDevice.cs
Normal file
@@ -0,0 +1,294 @@
|
||||
using SS14.Server.GameObjects;
|
||||
using SS14.Shared.GameObjects;
|
||||
using SS14.Shared.Interfaces.GameObjects;
|
||||
using SS14.Shared.IoC;
|
||||
using SS14.Shared.Utility;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Power
|
||||
{
|
||||
/// <summary>
|
||||
/// Component that requires power to function
|
||||
/// </summary>
|
||||
public class PowerDeviceComponent : Component
|
||||
{
|
||||
public override string Name => "PowerDevice";
|
||||
|
||||
/// <summary>
|
||||
/// The method of draw we will try to use to place our load set via component parameter, defaults to using power providers
|
||||
/// </summary>
|
||||
public virtual DrawTypes Drawtype { get; protected set; } = DrawTypes.Provider;
|
||||
|
||||
/// <summary>
|
||||
/// The power draw method we are currently connected to and using
|
||||
/// </summary>
|
||||
public DrawTypes Connected { get; protected set; } = DrawTypes.None;
|
||||
|
||||
public bool _powered = false;
|
||||
/// <summary>
|
||||
/// Status indicator variable for powered
|
||||
/// </summary>
|
||||
public virtual bool Powered
|
||||
{
|
||||
get => _powered;
|
||||
set => SetPowered(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Priority for powernet draw, lower will draw first, defined in powernet.cs
|
||||
/// </summary>
|
||||
public virtual Powernet.Priority Priority { get; protected set; } = Powernet.Priority.Medium;
|
||||
|
||||
|
||||
private float _load = 100; //arbitrary magic number to start
|
||||
/// <summary>
|
||||
/// Power load from this entity
|
||||
/// </summary>
|
||||
public float Load
|
||||
{
|
||||
get => _load;
|
||||
set { UpdateLoad(value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All the power providers that we are within range of
|
||||
/// </summary>
|
||||
public List<PowerProviderComponent> AvailableProviders = new List<PowerProviderComponent>();
|
||||
|
||||
|
||||
private PowerProviderComponent _provider;
|
||||
/// <summary>
|
||||
/// A power provider that will handle our load, if we are linked to any
|
||||
/// </summary>
|
||||
public PowerProviderComponent Provider
|
||||
{
|
||||
get => _provider;
|
||||
set {
|
||||
Connected = DrawTypes.Provider;
|
||||
if (_provider != null)
|
||||
{
|
||||
_provider.RemoveDevice(this);
|
||||
}
|
||||
|
||||
if(value != null)
|
||||
{
|
||||
_provider = value;
|
||||
_provider.AddDevice(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Connected = DrawTypes.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnAdd(IEntity owner)
|
||||
{
|
||||
base.OnAdd(owner);
|
||||
|
||||
if (Drawtype == DrawTypes.Both || Drawtype == DrawTypes.Node)
|
||||
{
|
||||
if (!owner.TryGetComponent(out PowerNodeComponent node))
|
||||
{
|
||||
var factory = IoCManager.Resolve<IComponentFactory>();
|
||||
node = factory.GetComponent<PowerNodeComponent>();
|
||||
owner.AddComponent(node);
|
||||
}
|
||||
node.OnPowernetConnect += PowernetConnect;
|
||||
node.OnPowernetDisconnect += PowernetDisconnect;
|
||||
node.OnPowernetRegenerate += PowernetRegenerate;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
if (Owner.TryGetComponent(out PowerNodeComponent node))
|
||||
{
|
||||
if(node.Parent != null)
|
||||
{
|
||||
node.Parent.RemoveDevice(this);
|
||||
}
|
||||
|
||||
node.OnPowernetConnect -= PowernetConnect;
|
||||
node.OnPowernetDisconnect -= PowernetDisconnect;
|
||||
node.OnPowernetRegenerate -= PowernetRegenerate;
|
||||
}
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
public override void LoadParameters(YamlMappingNode mapping)
|
||||
{
|
||||
if (mapping.TryGetNode("Drawtype", out YamlNode node))
|
||||
{
|
||||
Drawtype = node.AsEnum<DrawTypes>();
|
||||
}
|
||||
if (mapping.TryGetNode("Load", out node))
|
||||
{
|
||||
Load = node.AsFloat();
|
||||
}
|
||||
if (mapping.TryGetNode("Priority", out node))
|
||||
{
|
||||
Priority = node.AsEnum<Powernet.Priority>();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLoad(float value)
|
||||
{
|
||||
var oldLoad = _load;
|
||||
_load = value;
|
||||
if(Connected == DrawTypes.Node)
|
||||
{
|
||||
var node = Owner.GetComponent<PowerNodeComponent>();
|
||||
node.Parent.UpdateDevice(this, oldLoad);
|
||||
}
|
||||
else if(Connected == DrawTypes.Provider)
|
||||
{
|
||||
Provider.UpdateDevice(this, oldLoad);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes behavior when receiving a command to become powered or depowered
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public virtual void SetPowered(bool value)
|
||||
{
|
||||
//Let them set us to true
|
||||
if (value == true)
|
||||
{
|
||||
_powered = true;
|
||||
return;
|
||||
}
|
||||
|
||||
//A powernet has decided we will not be powered this tick, lets try to power ourselves
|
||||
if (value == false && Owner.TryGetComponent(out PowerStorageComponent storage))
|
||||
{
|
||||
if (storage.CanDeductCharge(Load))
|
||||
{
|
||||
storage.DeductCharge(Load);
|
||||
_powered = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//For some reason above we could not power ourselves, we depower
|
||||
_powered = false;
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a new power provider as a possible connection to this device
|
||||
/// </summary>
|
||||
/// <param name="provider"></param>
|
||||
public void AddProvider(PowerProviderComponent provider)
|
||||
{
|
||||
AvailableProviders.Add(provider);
|
||||
|
||||
if(Connected != DrawTypes.Node)
|
||||
{
|
||||
ConnectToBestProvider();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the nearest registered power provider and connect to it
|
||||
/// </summary>
|
||||
private void ConnectToBestProvider()
|
||||
{
|
||||
//Any values we can connect to or are we already connected to a node, cancel!
|
||||
if (!AvailableProviders.Any() || Connected == DrawTypes.Node)
|
||||
return;
|
||||
|
||||
//Get the starting value for our loop
|
||||
var position = Owner.GetComponent<TransformComponent>().WorldPosition;
|
||||
var bestprovider = AvailableProviders[0];
|
||||
|
||||
//If we are already connected to a power provider we need to do a loop to find the nearest one, otherwise skip it and use first entry
|
||||
if (Connected == DrawTypes.Provider)
|
||||
{
|
||||
var bestdistance = (bestprovider.Owner.GetComponent<TransformComponent>().WorldPosition - position).LengthSquared;
|
||||
|
||||
foreach (var availprovider in AvailableProviders)
|
||||
{
|
||||
//Find distance to new provider
|
||||
var distance = (availprovider.Owner.GetComponent<TransformComponent>().WorldPosition - position).LengthSquared;
|
||||
|
||||
//If new provider distance is shorter it becomes new best possible provider
|
||||
if (distance < bestdistance)
|
||||
{
|
||||
bestdistance = distance;
|
||||
bestprovider = availprovider;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(Provider != bestprovider)
|
||||
Provider = bestprovider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a power provider from being a possible connection to this device
|
||||
/// </summary>
|
||||
/// <param name="provider"></param>
|
||||
public void RemoveProvider(PowerProviderComponent provider)
|
||||
{
|
||||
if (!AvailableProviders.Contains(provider))
|
||||
return;
|
||||
|
||||
AvailableProviders.Remove(provider);
|
||||
|
||||
if (Connected != DrawTypes.Node)
|
||||
{
|
||||
ConnectToBestProvider();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Node has become anchored to a powernet
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="eventarg"></param>
|
||||
private void PowernetConnect(object sender, PowernetEventArgs eventarg)
|
||||
{
|
||||
//This sets connected = none so it must be first
|
||||
Provider = null;
|
||||
|
||||
eventarg.Powernet.AddDevice(this);
|
||||
Connected = DrawTypes.Node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Powernet wire was remove so we need to regenerate the powernet
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="eventarg"></param>
|
||||
private void PowernetRegenerate(object sender, PowernetEventArgs eventarg)
|
||||
{
|
||||
eventarg.Powernet.AddDevice(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Node has become unanchored from a powernet
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="eventarg"></param>
|
||||
private void PowernetDisconnect(object sender, PowernetEventArgs eventarg)
|
||||
{
|
||||
eventarg.Powernet.RemoveDevice(this);
|
||||
Connected = DrawTypes.None;
|
||||
|
||||
ConnectToBestProvider();
|
||||
}
|
||||
}
|
||||
|
||||
public enum DrawTypes
|
||||
{
|
||||
None = 0,
|
||||
Node = 1,
|
||||
Provider = 2,
|
||||
Both = 3
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
using SS14.Shared.GameObjects;
|
||||
using SS14.Shared.Interfaces.GameObjects;
|
||||
using SS14.Shared.IoC;
|
||||
using SS14.Shared.Log;
|
||||
using SS14.Shared.Utility;
|
||||
using System;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Power
|
||||
{
|
||||
/// <summary>
|
||||
/// Component that creates power and supplies it to the powernet
|
||||
/// </summary>
|
||||
public class PowerGeneratorComponent : Component
|
||||
{
|
||||
public override string Name => "PowerGenerator";
|
||||
|
||||
/// <summary>
|
||||
/// Power supply from this entity
|
||||
/// </summary>
|
||||
private float _supply = 1000; //arbitrary initial magic number to start
|
||||
public float Supply
|
||||
{
|
||||
get => _supply;
|
||||
set { UpdateSupply(value); }
|
||||
}
|
||||
|
||||
public override void LoadParameters(YamlMappingNode mapping)
|
||||
{
|
||||
if (mapping.TryGetNode("Supply", out YamlNode node))
|
||||
{
|
||||
Supply = node.AsFloat();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnAdd(IEntity owner)
|
||||
{
|
||||
base.OnAdd(owner);
|
||||
|
||||
if (!owner.TryGetComponent(out PowerNodeComponent node))
|
||||
{
|
||||
var factory = IoCManager.Resolve<IComponentFactory>();
|
||||
node = factory.GetComponent<PowerNodeComponent>();
|
||||
owner.AddComponent(node);
|
||||
}
|
||||
node.OnPowernetConnect += PowernetConnect;
|
||||
node.OnPowernetDisconnect += PowernetDisconnect;
|
||||
node.OnPowernetRegenerate += PowernetRegenerate;
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
if (Owner.TryGetComponent(out PowerNodeComponent node))
|
||||
{
|
||||
if (node.Parent != null)
|
||||
{
|
||||
node.Parent.RemoveGenerator(this);
|
||||
}
|
||||
|
||||
node.OnPowernetConnect -= PowernetConnect;
|
||||
node.OnPowernetDisconnect -= PowernetDisconnect;
|
||||
node.OnPowernetRegenerate -= PowernetRegenerate;
|
||||
}
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
private void UpdateSupply(float value)
|
||||
{
|
||||
_supply = value;
|
||||
var node = Owner.GetComponent<PowerNodeComponent>();
|
||||
node.Parent.UpdateGenerator(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Node has become anchored to a powernet
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="eventarg"></param>
|
||||
private void PowernetConnect(object sender, PowernetEventArgs eventarg)
|
||||
{
|
||||
eventarg.Powernet.AddGenerator(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Node has had its powernet regenerated
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="eventarg"></param>
|
||||
private void PowernetRegenerate(object sender, PowernetEventArgs eventarg)
|
||||
{
|
||||
eventarg.Powernet.AddGenerator(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Node has become unanchored from a powernet
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="eventarg"></param>
|
||||
private void PowernetDisconnect(object sender, PowernetEventArgs eventarg)
|
||||
{
|
||||
eventarg.Powernet.RemoveGenerator(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
using SS14.Server.GameObjects;
|
||||
using SS14.Server.Interfaces.GameObjects;
|
||||
using SS14.Shared.GameObjects;
|
||||
using SS14.Shared.IoC;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Power
|
||||
{
|
||||
/// <summary>
|
||||
/// Component that connects to the powernet
|
||||
/// </summary>
|
||||
public class PowerNodeComponent : Component
|
||||
{
|
||||
public override string Name => "PowerNode";
|
||||
|
||||
/// <summary>
|
||||
/// The powernet this node is connected to
|
||||
/// </summary>
|
||||
public Powernet Parent;
|
||||
|
||||
/// <summary>
|
||||
/// An event handling when this node connects to a powernet
|
||||
/// </summary>
|
||||
public event EventHandler<PowernetEventArgs> OnPowernetConnect;
|
||||
|
||||
/// <summary>
|
||||
/// An event handling when this node disconnects from a powernet
|
||||
/// </summary>
|
||||
public event EventHandler<PowernetEventArgs> OnPowernetDisconnect;
|
||||
|
||||
/// <summary>
|
||||
/// An event that registers us to a regenerating powernet
|
||||
/// </summary>
|
||||
public event EventHandler<PowernetEventArgs> OnPowernetRegenerate;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
TryCreatePowernetConnection();
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
DisconnectFromPowernet();
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find a nearby wire which will have a powernet and connect ourselves to its powernet
|
||||
/// </summary>
|
||||
public void TryCreatePowernetConnection()
|
||||
{
|
||||
var _emanager = IoCManager.Resolve<IServerEntityManager>();
|
||||
var position = Owner.GetComponent<TransformComponent>().WorldPosition;
|
||||
var wires = _emanager.GetEntitiesIntersecting(Owner)
|
||||
.Where(x => x.HasComponent<PowerTransferComponent>())
|
||||
.OrderByDescending(x => (x.GetComponent<TransformComponent>().WorldPosition - position).Length);
|
||||
var choose = wires.FirstOrDefault();
|
||||
if(choose != null)
|
||||
ConnectToPowernet(choose.GetComponent<PowerTransferComponent>().Parent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers event telling power components that we connected to a powernet
|
||||
/// </summary>
|
||||
/// <param name="toconnect"></param>
|
||||
public void ConnectToPowernet(Powernet toconnect)
|
||||
{
|
||||
Parent = toconnect;
|
||||
Parent.Nodelist.Add(this);
|
||||
OnPowernetConnect?.Invoke(this, new PowernetEventArgs(Parent));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers event telling power components that we haven't disconnected but have readded ourselves to a regenerated powernet
|
||||
/// </summary>
|
||||
/// <param name="toconnect"></param>
|
||||
public void RegeneratePowernet(Powernet toconnect)
|
||||
{
|
||||
//This removes the device from things that will be powernet disconnected when dirty powernet is killed
|
||||
Parent.Nodelist.Remove(this);
|
||||
|
||||
Parent = toconnect;
|
||||
Parent.Nodelist.Add(this);
|
||||
OnPowernetRegenerate?.Invoke(this, new PowernetEventArgs(Parent));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers event telling power components we have exited any powernets
|
||||
/// </summary>
|
||||
public void DisconnectFromPowernet()
|
||||
{
|
||||
Parent.Nodelist.Remove(this);
|
||||
OnPowernetDisconnect?.Invoke(this, new PowernetEventArgs(Parent));
|
||||
Parent = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class PowernetEventArgs : EventArgs
|
||||
{
|
||||
public PowernetEventArgs(Powernet powernet)
|
||||
{
|
||||
Powernet = powernet;
|
||||
}
|
||||
|
||||
public Powernet Powernet { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
using SS14.Server.GameObjects;
|
||||
using SS14.Server.Interfaces.GameObjects;
|
||||
using SS14.Shared.Interfaces.GameObjects;
|
||||
using SS14.Shared.IoC;
|
||||
using SS14.Shared.Log;
|
||||
using SS14.Shared.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Power
|
||||
{
|
||||
/// <summary>
|
||||
/// Component that wirelessly connects and powers devices, connects to powernet via node and can be combined with internal storage component
|
||||
/// </summary>
|
||||
public class PowerProviderComponent : PowerDeviceComponent
|
||||
{
|
||||
public override string Name => "PowerProvider";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DrawTypes Drawtype { get; protected set; } = DrawTypes.Node;
|
||||
|
||||
/// <summary>
|
||||
/// Variable that determines the range that the power provider will try to supply power to
|
||||
/// </summary>
|
||||
public int PowerRange { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// List storing all the power devices that we are currently providing power to
|
||||
/// </summary>
|
||||
public SortedSet<PowerDeviceComponent> Deviceloadlist = new SortedSet<PowerDeviceComponent>(new Powernet.DevicePriorityCompare());
|
||||
|
||||
public List<PowerDeviceComponent> DepoweredDevices = new List<PowerDeviceComponent>();
|
||||
|
||||
public override Powernet.Priority Priority { get; protected set; } = Powernet.Priority.Provider;
|
||||
|
||||
public override void LoadParameters(YamlMappingNode mapping)
|
||||
{
|
||||
if (mapping.TryGetNode("Range", out YamlNode node))
|
||||
{
|
||||
PowerRange = node.AsInt();
|
||||
}
|
||||
if (mapping.TryGetNode("Priority", out node))
|
||||
{
|
||||
Priority = node.AsEnum<Powernet.Priority>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void SetPowered(bool value)
|
||||
{
|
||||
//Let them set us true, we must now power all the devices that rely on us for energy
|
||||
if (value == true)
|
||||
{
|
||||
PowerAllDevices();
|
||||
return;
|
||||
}
|
||||
|
||||
//A powernet has decided we will not be powered this tick, lets try to power ourselves
|
||||
if (value == false && Owner.TryGetComponent(out PowerStorageComponent storage))
|
||||
{
|
||||
//Can the storage cover powering all our devices and us? If so power all
|
||||
if (storage.CanDeductCharge(Load))
|
||||
{
|
||||
storage.DeductCharge(Load);
|
||||
_powered = true;
|
||||
return;
|
||||
}
|
||||
//Does the storage even have any power to give us? If so power as much as we can
|
||||
else if (storage.RequestAllCharge() != 0)
|
||||
{
|
||||
var depowervalue = storage.RequestAllCharge() - Load;
|
||||
_powered = true;
|
||||
//See code in powernet for same functionality
|
||||
foreach (var device in Deviceloadlist)
|
||||
{
|
||||
device.Powered = false;
|
||||
DepoweredDevices.Add(device);
|
||||
depowervalue -= device.Load;
|
||||
if (depowervalue < 0)
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
//Storage doesn't have anything, depower everything
|
||||
else if(storage.RequestAllCharge() == 0)
|
||||
{
|
||||
DepowerAllDevices();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//For some reason above we could not power ourselves, we depower ourselves and all devices
|
||||
DepowerAllDevices();
|
||||
return;
|
||||
}
|
||||
|
||||
private void PowerAllDevices()
|
||||
{
|
||||
_powered = true;
|
||||
foreach (var device in DepoweredDevices)
|
||||
{
|
||||
device.Powered = true;
|
||||
}
|
||||
DepoweredDevices.Clear();
|
||||
}
|
||||
|
||||
private void DepowerAllDevices()
|
||||
{
|
||||
_powered = false;
|
||||
foreach (var device in DepoweredDevices)
|
||||
{
|
||||
device.Powered = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void PowernetConnect(object sender, PowernetEventArgs eventarg)
|
||||
{
|
||||
eventarg.Powernet.AddDevice(this);
|
||||
Connected = DrawTypes.Node;
|
||||
|
||||
//Find devices within range to take under our control
|
||||
var _emanager = IoCManager.Resolve<IServerEntityManager>();
|
||||
var position = Owner.GetComponent<TransformComponent>().WorldPosition;
|
||||
var entities = _emanager.GetEntitiesInRange(Owner, PowerRange)
|
||||
.Where(x => x.HasComponent<PowerDeviceComponent>());
|
||||
|
||||
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
var device = entity.GetComponent<PowerDeviceComponent>();
|
||||
|
||||
//Make sure the device can accept power providers to give it power
|
||||
if (device.Drawtype == DrawTypes.Provider || device.Drawtype == DrawTypes.Both)
|
||||
{
|
||||
device.AddProvider(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void PowernetRegenerate(object sender, PowernetEventArgs eventarg)
|
||||
{
|
||||
eventarg.Powernet.AddDevice(this);
|
||||
}
|
||||
|
||||
private void PowernetDisconnect(object sender, PowernetEventArgs eventarg)
|
||||
{
|
||||
eventarg.Powernet.RemoveDevice(this);
|
||||
Connected = DrawTypes.None;
|
||||
|
||||
//We don't want to make the devices under us think we're still a valid provider if we have no powernet to connect to
|
||||
foreach (var device in Deviceloadlist)
|
||||
{
|
||||
device.RemoveProvider(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a continuous load from a device connected to the powernet
|
||||
/// </summary>
|
||||
public void AddDevice(PowerDeviceComponent device)
|
||||
{
|
||||
Deviceloadlist.Add(device);
|
||||
Load += device.Load;
|
||||
if (!device.Powered)
|
||||
DepoweredDevices.Add(device);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update one of the loads from a deviceconnected to the powernet
|
||||
/// </summary>
|
||||
public void UpdateDevice(PowerDeviceComponent device, float oldLoad)
|
||||
{
|
||||
if (Deviceloadlist.Contains(device))
|
||||
{
|
||||
Load -= oldLoad;
|
||||
Load += device.Load;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a continuous load from a device connected to the powernet
|
||||
/// </summary>
|
||||
public void RemoveDevice(PowerDeviceComponent device)
|
||||
{
|
||||
if (Deviceloadlist.Contains(device))
|
||||
{
|
||||
Load -= device.Load;
|
||||
Deviceloadlist.Remove(device);
|
||||
if (DepoweredDevices.Contains(device))
|
||||
DepoweredDevices.Remove(device);
|
||||
}
|
||||
else
|
||||
{
|
||||
var name = device.Owner.Prototype.Name;
|
||||
Logger.Log(String.Format("We tried to remove a device twice from the same {0} somehow, prototype {1}", Name, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
using SS14.Shared.GameObjects;
|
||||
using SS14.Shared.Interfaces.GameObjects;
|
||||
using SS14.Shared.IoC;
|
||||
using SS14.Shared.Utility;
|
||||
using System;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Power
|
||||
{
|
||||
/// <summary>
|
||||
/// Feeds energy from the powernet and may have the ability to supply back into it
|
||||
/// </summary>
|
||||
public class PowerStorageComponent : Component
|
||||
{
|
||||
public override string Name => "PowerStorage";
|
||||
|
||||
/// <summary>
|
||||
/// Maximum amount of energy the internal battery can store
|
||||
/// </summary>
|
||||
public float Capacity { get; private set; } = 10000; //arbitrary value replace
|
||||
|
||||
/// <summary>
|
||||
/// Energy the battery is currently storing
|
||||
/// </summary>
|
||||
public float Charge { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Rate at which energy will be taken to charge internal battery
|
||||
/// </summary>
|
||||
public float ChargeRate { get; private set; } = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Rate at which energy will be distributed to the powernet if needed
|
||||
/// </summary>
|
||||
public float DistributionRate { get; private set; } = 1000;
|
||||
|
||||
private bool _chargepowernet = false;
|
||||
|
||||
/// <summary>
|
||||
/// Do we distribute power into the powernet from our stores if the powernet requires it?
|
||||
/// </summary>
|
||||
public bool ChargePowernet
|
||||
{
|
||||
get => _chargepowernet;
|
||||
set
|
||||
{
|
||||
_chargepowernet = value;
|
||||
if (Owner.TryGetComponent(out PowerNodeComponent node))
|
||||
{
|
||||
if (node.Parent != null)
|
||||
node.Parent.UpdateStorageType(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void LoadParameters(YamlMappingNode mapping)
|
||||
{
|
||||
if (mapping.TryGetNode("Capacity", out YamlNode node))
|
||||
{
|
||||
Capacity = node.AsFloat();
|
||||
}
|
||||
if (mapping.TryGetNode("Charge", out node))
|
||||
{
|
||||
Charge = node.AsFloat();
|
||||
}
|
||||
if (mapping.TryGetNode("ChargeRate", out node))
|
||||
{
|
||||
ChargeRate = node.AsFloat();
|
||||
}
|
||||
if (mapping.TryGetNode("DistributionRate", out node))
|
||||
{
|
||||
DistributionRate = node.AsFloat();
|
||||
}
|
||||
if (mapping.TryGetNode("ChargePowernet", out node))
|
||||
{
|
||||
_chargepowernet = node.AsBool();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnAdd(IEntity owner)
|
||||
{
|
||||
base.OnAdd(owner);
|
||||
|
||||
if (!owner.TryGetComponent(out PowerNodeComponent node))
|
||||
{
|
||||
var factory = IoCManager.Resolve<IComponentFactory>();
|
||||
node = factory.GetComponent<PowerNodeComponent>();
|
||||
owner.AddComponent(node);
|
||||
}
|
||||
node.OnPowernetConnect += PowernetConnect;
|
||||
node.OnPowernetDisconnect += PowernetDisconnect;
|
||||
node.OnPowernetRegenerate += PowernetRegenerate;
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
if (Owner.TryGetComponent(out PowerNodeComponent node))
|
||||
{
|
||||
if (node.Parent != null)
|
||||
{
|
||||
node.Parent.RemovePowerStorage(this);
|
||||
}
|
||||
|
||||
node.OnPowernetConnect -= PowernetConnect;
|
||||
node.OnPowernetDisconnect -= PowernetDisconnect;
|
||||
node.OnPowernetRegenerate -= PowernetRegenerate;
|
||||
}
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the storage can supply the amount of charge directly requested
|
||||
/// </summary>
|
||||
public bool CanDeductCharge(float todeduct)
|
||||
{
|
||||
if (Charge > todeduct)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deducts the requested charge from the energy storage
|
||||
/// </summary>
|
||||
public void DeductCharge(float todeduct)
|
||||
{
|
||||
Charge = Math.Min(0, Charge - todeduct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all possible charge available from the energy storage
|
||||
/// </summary>
|
||||
public float RequestAllCharge()
|
||||
{
|
||||
return Math.Min(ChargeRate, Capacity - Charge);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the charge available from the energy storage
|
||||
/// </summary>
|
||||
public float RequestCharge()
|
||||
{
|
||||
return Math.Min(ChargeRate, Capacity - Charge);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the charge available from the energy storage
|
||||
/// </summary>
|
||||
public float AvailableCharge()
|
||||
{
|
||||
return Math.Min(DistributionRate, Charge);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gives the storage one full tick of charging its energy storage
|
||||
/// </summary>
|
||||
public void ChargePowerTick()
|
||||
{
|
||||
Charge = Math.Max(Charge + ChargeRate, Capacity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes from the storage one full tick of energy
|
||||
/// </summary>
|
||||
public void RetrievePassiveStorage()
|
||||
{
|
||||
Charge = Math.Min(Charge - DistributionRate, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Node has become anchored to a powernet
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="eventarg"></param>
|
||||
private void PowernetConnect(object sender, PowernetEventArgs eventarg)
|
||||
{
|
||||
eventarg.Powernet.AddPowerStorage(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Node has had its powernet regenerated
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="eventarg"></param>
|
||||
private void PowernetRegenerate(object sender, PowernetEventArgs eventarg)
|
||||
{
|
||||
eventarg.Powernet.AddPowerStorage(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Node has become unanchored from a powernet
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="eventarg"></param>
|
||||
private void PowernetDisconnect(object sender, PowernetEventArgs eventarg)
|
||||
{
|
||||
eventarg.Powernet.RemovePowerStorage(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
using SS14.Server.GameObjects;
|
||||
using SS14.Server.Interfaces.GameObjects;
|
||||
using SS14.Shared.GameObjects;
|
||||
using SS14.Shared.IoC;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Power
|
||||
{
|
||||
/// <summary>
|
||||
/// Component to transfer power to nearby components, can create powernets and connect to nodes
|
||||
/// </summary>
|
||||
public class PowerTransferComponent : Component
|
||||
{
|
||||
public override string Name => "PowerTransfer";
|
||||
|
||||
/// <summary>
|
||||
/// The powernet this component is connected to
|
||||
/// </summary>
|
||||
public Powernet Parent;
|
||||
|
||||
public bool Regenerating { get; set; } = false;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
if(Parent == null)
|
||||
{
|
||||
SpreadPowernet();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
DisconnectFromPowernet();
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for local powernets to connect to, otherwise creates its own, and spreads powernet to nearby entities
|
||||
/// </summary>
|
||||
public void SpreadPowernet()
|
||||
{
|
||||
var _emanager = IoCManager.Resolve<IServerEntityManager>();
|
||||
var position = Owner.GetComponent<TransformComponent>().WorldPosition;
|
||||
var wires = _emanager.GetEntitiesInRange(Owner, 0.1f) //arbitrarily low, just scrape things //wip
|
||||
.Where(x => x.HasComponent<PowerTransferComponent>());
|
||||
|
||||
//we have no parent so lets find a partner we can join his powernet
|
||||
if(Parent == null || Regenerating)
|
||||
{
|
||||
foreach (var wire in wires)
|
||||
{
|
||||
var ptc = wire.GetComponent<PowerTransferComponent>();
|
||||
if (ptc.CanConnectTo())
|
||||
{
|
||||
ConnectToPowernet(ptc.Parent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//we couldn't find a partner so none must have spread yet, lets make our own powernet to spread
|
||||
if (Parent == null || Regenerating)
|
||||
{
|
||||
var powernew = new Powernet();
|
||||
ConnectToPowernet(powernew);
|
||||
}
|
||||
}
|
||||
|
||||
//Find nodes intersecting us and if not already assigned to a powernet assign them to us
|
||||
var nodes = _emanager.GetEntitiesIntersecting(Owner)
|
||||
.Where(x => x.HasComponent<PowerNodeComponent>())
|
||||
.Select(x => x.GetComponent<PowerNodeComponent>());
|
||||
|
||||
foreach(var node in nodes)
|
||||
{
|
||||
if(node.Parent == null)
|
||||
{
|
||||
node.ConnectToPowernet(Parent);
|
||||
}
|
||||
else if(node.Parent.Dirty)
|
||||
{
|
||||
node.RegeneratePowernet(Parent);
|
||||
}
|
||||
}
|
||||
|
||||
//spread powernet to nearby wires which haven't got one yet, and tell them to spread as well
|
||||
foreach (var wire in wires)
|
||||
{
|
||||
var ptc = wire.GetComponent<PowerTransferComponent>();
|
||||
if (ptc.Parent == null || Regenerating)
|
||||
{
|
||||
ptc.ConnectToPowernet(Parent);
|
||||
SpreadPowernet();
|
||||
}
|
||||
else if(ptc.Parent != Parent && !ptc.Parent.Dirty)
|
||||
{
|
||||
Parent.MergePowernets(ptc.Parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when connecting to a new powernet, either on creation or on regeneration
|
||||
/// </summary>
|
||||
/// <param name="toconnect"></param>
|
||||
public void ConnectToPowernet(Powernet toconnect)
|
||||
{
|
||||
Parent = toconnect;
|
||||
Parent.Wirelist.Add(this);
|
||||
Regenerating = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when we are removed and telling the powernet that it is now dirty and must regenerate
|
||||
/// </summary>
|
||||
public void DisconnectFromPowernet()
|
||||
{
|
||||
Parent.Wirelist.Remove(this);
|
||||
Parent.Dirty = true;
|
||||
Parent = null;
|
||||
}
|
||||
|
||||
|
||||
public bool CanConnectTo()
|
||||
{
|
||||
return Parent != null && Parent.Dirty == false && !Regenerating;
|
||||
}
|
||||
}
|
||||
}
|
||||
402
Content.Server/GameObjects/Components/Power/Powernet.cs
Normal file
402
Content.Server/GameObjects/Components/Power/Powernet.cs
Normal file
@@ -0,0 +1,402 @@
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using SS14.Shared.Interfaces.GameObjects;
|
||||
using SS14.Shared.IoC;
|
||||
using SS14.Shared.Log;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Power
|
||||
{
|
||||
/// <summary>
|
||||
/// Master class for group of powertransfercomponents, takes in and distributes power via nodes
|
||||
/// </summary>
|
||||
public class Powernet
|
||||
{
|
||||
public Powernet()
|
||||
{
|
||||
var EntitySystemManager = IoCManager.Resolve<IEntitySystemManager>();
|
||||
EntitySystemManager.GetEntitySystem<PowerSystem>().Powernets.Add(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The entities that make up the powernet's physical location and allow powernet connection
|
||||
/// </summary>
|
||||
public List<PowerTransferComponent> Wirelist { get; set; } = new List<PowerTransferComponent>();
|
||||
|
||||
/// <summary>
|
||||
/// Entities that connect directly to the powernet through PTC above to add power or add power load
|
||||
/// </summary>
|
||||
public List<PowerNodeComponent> Nodelist { get; set; } = new List<PowerNodeComponent>();
|
||||
|
||||
/// <summary>
|
||||
/// Subset of nodelist that adds a continuous power supply to the network
|
||||
/// </summary>
|
||||
public Dictionary<PowerGeneratorComponent, float> Generatorlist { get; set; } = new Dictionary<PowerGeneratorComponent, float>();
|
||||
|
||||
/// <summary>
|
||||
/// Subset of nodelist that draw power, stores information on current continuous powernet load
|
||||
/// </summary>
|
||||
public SortedSet<PowerDeviceComponent> Deviceloadlist { get; set; } = new SortedSet<PowerDeviceComponent>(new DevicePriorityCompare());
|
||||
|
||||
/// <summary>
|
||||
/// Comparer that keeps the device dictionary sorted by powernet priority
|
||||
/// </summary>
|
||||
public class DevicePriorityCompare : IComparer<PowerDeviceComponent>
|
||||
{
|
||||
public int Compare(PowerDeviceComponent x, PowerDeviceComponent y)
|
||||
{
|
||||
int compare = y.Priority.CompareTo(x.Priority);
|
||||
|
||||
//If the comparer returns 0 sortedset will believe it is a duplicate and return 0, so return 1 instead
|
||||
if (compare == 0 && !x.Equals(y))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return compare;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Priority that a device will receive power if powernet cannot supply every device
|
||||
/// </summary>
|
||||
public enum Priority
|
||||
{
|
||||
Necessary,
|
||||
High,
|
||||
Medium,
|
||||
Low,
|
||||
Provider,
|
||||
Unnecessary
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All the devices that have been depowered by this powernet or depowered prior to being absorted into this powernet
|
||||
/// </summary>
|
||||
public List<PowerDeviceComponent> DepoweredDevices { get; set; } = new List<PowerDeviceComponent>();
|
||||
|
||||
/// <summary>
|
||||
/// A list of the energy storage components that will feed the powernet if necessary, and if there is enough power feed itself
|
||||
/// </summary>
|
||||
public List<PowerStorageComponent> PowerStorageSupplierlist { get; set; } = new List<PowerStorageComponent>();
|
||||
|
||||
/// <summary>
|
||||
/// A list of energy storage components that will never feed the powernet, will try to draw energy to feed themselves if possible
|
||||
/// </summary>
|
||||
public List<PowerStorageComponent> PowerStorageConsumerlist { get; set; } = new List<PowerStorageComponent>();
|
||||
|
||||
/// <summary>
|
||||
/// Static counter of all continuous load placed from devices on this power network
|
||||
/// </summary>
|
||||
public float Load { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Static counter of all continiuous supply from generators on this power network
|
||||
/// </summary>
|
||||
public float Supply { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Variable that causes powernet to be regenerated from its wires during the next update cycle
|
||||
/// </summary>
|
||||
public bool Dirty { get; set; } = false;
|
||||
|
||||
public void Update(float frametime)
|
||||
{
|
||||
float activesupply = Supply;
|
||||
float activeload = Load;
|
||||
|
||||
float storagedemand = 0;
|
||||
|
||||
foreach (var supply in PowerStorageConsumerlist)
|
||||
{
|
||||
storagedemand += supply.RequestCharge();
|
||||
}
|
||||
|
||||
float passivesupply = 0;
|
||||
float passivedemand = 0;
|
||||
|
||||
foreach (var supply in PowerStorageSupplierlist)
|
||||
{
|
||||
passivesupply += supply.AvailableCharge();
|
||||
passivedemand += supply.RequestCharge();
|
||||
}
|
||||
|
||||
|
||||
//If we have enough power to feed all load and storage demand, then feed everything
|
||||
if (activesupply > activeload + storagedemand + passivedemand)
|
||||
{
|
||||
PowerAllDevices();
|
||||
ChargeActiveStorage();
|
||||
ChargePassiveStorage();
|
||||
}
|
||||
//We don't have enough power for the storage powernet suppliers, ignore powering them
|
||||
else if (activesupply > activeload + storagedemand)
|
||||
{
|
||||
PowerAllDevices();
|
||||
ChargeActiveStorage();
|
||||
}
|
||||
//We require the storage powernet suppliers to power the remaining storage components and device load
|
||||
else if (activesupply + passivesupply > activeload + storagedemand)
|
||||
{
|
||||
PowerAllDevices();
|
||||
ChargeActiveStorage();
|
||||
RetrievePassiveStorage();
|
||||
}
|
||||
//We cant afford to fund the storage components, so lets try to power the basic load using our supply and storage supply
|
||||
else if (activesupply + passivesupply > activeload)
|
||||
{
|
||||
PowerAllDevices();
|
||||
RetrievePassiveStorage();
|
||||
}
|
||||
//We cant even cover the basic device load, start disabling devices in order of priority until the remaining load is lowered enough to be met
|
||||
else if (activesupply + passivesupply < activeload)
|
||||
{
|
||||
PowerAllDevices(); //This merely makes our inevitable betrayal all the sweeter
|
||||
RetrievePassiveStorage();
|
||||
|
||||
var depowervalue = activeload - (activesupply + passivesupply);
|
||||
|
||||
//Providers use same method to recreate functionality
|
||||
foreach(var device in Deviceloadlist)
|
||||
{
|
||||
device.Powered = false;
|
||||
DepoweredDevices.Add(device);
|
||||
depowervalue -= device.Load;
|
||||
if (depowervalue < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void PowerAllDevices()
|
||||
{
|
||||
foreach(var device in DepoweredDevices)
|
||||
{
|
||||
device.Powered = true;
|
||||
}
|
||||
DepoweredDevices.Clear();
|
||||
}
|
||||
|
||||
private void ChargeActiveStorage()
|
||||
{
|
||||
foreach (var storage in PowerStorageConsumerlist)
|
||||
{
|
||||
storage.ChargePowerTick();
|
||||
}
|
||||
}
|
||||
|
||||
private void ChargePassiveStorage()
|
||||
{
|
||||
foreach (var storage in PowerStorageSupplierlist)
|
||||
{
|
||||
storage.ChargePowerTick();
|
||||
}
|
||||
}
|
||||
|
||||
private void RetrievePassiveStorage()
|
||||
{
|
||||
foreach (var storage in PowerStorageSupplierlist)
|
||||
{
|
||||
storage.ChargePowerTick();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Kills a powernet after it is marked dirty and its component have already been regenerated by the powernet system
|
||||
/// </summary>
|
||||
public void DirtyKill()
|
||||
{
|
||||
Wirelist.Clear();
|
||||
while(Nodelist.Count != 0)
|
||||
{
|
||||
Nodelist[0].DisconnectFromPowernet();
|
||||
}
|
||||
Generatorlist.Clear();
|
||||
Deviceloadlist.Clear();
|
||||
DepoweredDevices.Clear();
|
||||
PowerStorageSupplierlist.Clear();
|
||||
PowerStorageConsumerlist.Clear();
|
||||
|
||||
RemoveFromSystem();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Combines two powernets when they connect via powertransfer components
|
||||
/// </summary>
|
||||
public void MergePowernets(Powernet toMerge)
|
||||
{
|
||||
//TODO: load balance reconciliation between powernets on merge tick here
|
||||
|
||||
foreach (var wire in toMerge.Wirelist)
|
||||
{
|
||||
wire.Parent = this;
|
||||
}
|
||||
Wirelist.AddRange(toMerge.Wirelist);
|
||||
toMerge.Wirelist.Clear();
|
||||
|
||||
foreach (var node in toMerge.Nodelist)
|
||||
{
|
||||
node.Parent = this;
|
||||
}
|
||||
Nodelist.AddRange(toMerge.Nodelist);
|
||||
toMerge.Nodelist.Clear();
|
||||
|
||||
foreach (var generator in toMerge.Generatorlist)
|
||||
{
|
||||
Generatorlist.Add(generator.Key, generator.Value);
|
||||
}
|
||||
toMerge.Generatorlist.Clear();
|
||||
|
||||
foreach (var device in toMerge.Deviceloadlist)
|
||||
{
|
||||
Deviceloadlist.Add(device);
|
||||
}
|
||||
toMerge.Deviceloadlist.Clear();
|
||||
|
||||
DepoweredDevices.AddRange(toMerge.DepoweredDevices);
|
||||
toMerge.DepoweredDevices.Clear();
|
||||
|
||||
PowerStorageSupplierlist.AddRange(toMerge.PowerStorageSupplierlist);
|
||||
toMerge.PowerStorageSupplierlist.Clear();
|
||||
|
||||
PowerStorageConsumerlist.AddRange(toMerge.PowerStorageConsumerlist);
|
||||
toMerge.PowerStorageConsumerlist.Clear();
|
||||
|
||||
toMerge.RemoveFromSystem();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes reference from the powernets list on the powernet system
|
||||
/// </summary>
|
||||
private void RemoveFromSystem()
|
||||
{
|
||||
var EntitySystemManager = IoCManager.Resolve<IEntitySystemManager>();
|
||||
EntitySystemManager.GetEntitySystem<PowerSystem>().Powernets.Remove(this);
|
||||
}
|
||||
|
||||
#region Registration
|
||||
|
||||
/// <summary>
|
||||
/// Register a continuous load from a device connected to the powernet
|
||||
/// </summary>
|
||||
public void AddDevice(PowerDeviceComponent device)
|
||||
{
|
||||
Deviceloadlist.Add(device);
|
||||
Load += device.Load;
|
||||
if (!device.Powered)
|
||||
DepoweredDevices.Add(device);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update one of the loads from a deviceconnected to the powernet
|
||||
/// </summary>
|
||||
public void UpdateDevice(PowerDeviceComponent device, float oldLoad)
|
||||
{
|
||||
if(Deviceloadlist.Contains(device))
|
||||
{
|
||||
Load -= oldLoad;
|
||||
Load += device.Load;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a continuous load from a device connected to the powernet
|
||||
/// </summary>
|
||||
public void RemoveDevice(PowerDeviceComponent device)
|
||||
{
|
||||
if(Deviceloadlist.Contains(device))
|
||||
{
|
||||
Load -= device.Load;
|
||||
Deviceloadlist.Remove(device);
|
||||
if (DepoweredDevices.Contains(device))
|
||||
DepoweredDevices.Remove(device);
|
||||
}
|
||||
else
|
||||
{
|
||||
var name = device.Owner.Prototype.Name;
|
||||
Logger.Log(String.Format("We tried to remove a device twice from the same powernet somehow, prototype {0}", name));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a power supply from a generator connected to the powernet
|
||||
/// </summary>
|
||||
public void AddGenerator(PowerGeneratorComponent generator)
|
||||
{
|
||||
Generatorlist.Add(generator, generator.Supply);
|
||||
Supply += generator.Supply;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the value supplied from a generator connected to the powernet
|
||||
/// </summary>
|
||||
public void UpdateGenerator(PowerGeneratorComponent generator)
|
||||
{
|
||||
if (Generatorlist.ContainsKey(generator))
|
||||
{
|
||||
Supply -= Generatorlist[generator];
|
||||
Generatorlist[generator] = generator.Supply;
|
||||
Supply += generator.Supply;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a power supply from a generator connected to the powernet
|
||||
/// </summary>
|
||||
public void RemoveGenerator(PowerGeneratorComponent generator)
|
||||
{
|
||||
if (Generatorlist.ContainsKey(generator))
|
||||
{
|
||||
Supply -= Generatorlist[generator];
|
||||
Generatorlist.Remove(generator);
|
||||
}
|
||||
else
|
||||
{
|
||||
var name = generator.Owner.Prototype.Name;
|
||||
Logger.Log(String.Format("We tried to remove a device twice from the same power somehow, prototype {1}", name));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a power supply from a generator connected to the powernet
|
||||
/// </summary>
|
||||
public void AddPowerStorage(PowerStorageComponent storage)
|
||||
{
|
||||
if(storage.ChargePowernet)
|
||||
PowerStorageSupplierlist.Add(storage);
|
||||
else
|
||||
PowerStorageConsumerlist.Add(storage);
|
||||
}
|
||||
|
||||
//How do I even call this? TODO: fix
|
||||
public void UpdateStorageType(PowerStorageComponent storage)
|
||||
{
|
||||
//If our chargepowernet settings change we need to tell the powernet of this new setting and remove traces of our old setting
|
||||
if (PowerStorageSupplierlist.Contains(storage))
|
||||
PowerStorageSupplierlist.Remove(storage);
|
||||
if (PowerStorageConsumerlist.Contains(storage))
|
||||
PowerStorageConsumerlist.Remove(storage);
|
||||
|
||||
//Apply new setting
|
||||
if (storage.ChargePowernet)
|
||||
PowerStorageSupplierlist.Add(storage);
|
||||
else
|
||||
PowerStorageConsumerlist.Add(storage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a power supply from a generator connected to the powernet
|
||||
/// </summary>
|
||||
public void RemovePowerStorage(PowerStorageComponent storage)
|
||||
{
|
||||
if (PowerStorageSupplierlist.Contains(storage))
|
||||
{
|
||||
PowerStorageSupplierlist.Remove(storage);
|
||||
}
|
||||
if (PowerStorageConsumerlist.Contains(storage))
|
||||
{
|
||||
PowerStorageSupplierlist.Remove(storage);
|
||||
}
|
||||
}
|
||||
#endregion Registration
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user