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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user