diff --git a/Content.Client/Content.Client.csproj b/Content.Client/Content.Client.csproj index 66e924d664..2a68133adb 100644 --- a/Content.Client/Content.Client.csproj +++ b/Content.Client/Content.Client.csproj @@ -75,6 +75,7 @@ + diff --git a/Content.Client/EntryPoint.cs b/Content.Client/EntryPoint.cs index 6b332a56ca..38542f363c 100644 --- a/Content.Client/EntryPoint.cs +++ b/Content.Client/EntryPoint.cs @@ -1,4 +1,5 @@ using Content.Client.GameObjects; +using Content.Client.GameObjects.Components.Power; using Content.Client.GameObjects.Components.Storage; using Content.Client.Interfaces.GameObjects; using SS14.Shared.ContentPack; @@ -43,6 +44,7 @@ namespace Content.Client factory.RegisterReference(); factory.Register(); factory.Register(); + factory.Register(); } } } diff --git a/Content.Client/GameObjects/Components/Power/PowerDebugTool.cs b/Content.Client/GameObjects/Components/Power/PowerDebugTool.cs new file mode 100644 index 0000000000..6a4e50e4b8 --- /dev/null +++ b/Content.Client/GameObjects/Components/Power/PowerDebugTool.cs @@ -0,0 +1,28 @@ +using Content.Shared.GameObjects; +using Content.Shared.GameObjects.Components.Power; +using SS14.Client.UserInterface.Controls; +using SS14.Client.UserInterface.CustomControls; +using SS14.Shared.GameObjects; +using SS14.Shared.Interfaces.GameObjects; +using SS14.Shared.Interfaces.Network; + +namespace Content.Client.GameObjects.Components.Power +{ + public class PowerDebugTool : SharedPowerDebugTool + { + public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null, IComponent component = null) + { + base.HandleMessage(message, netChannel, component); + + switch (message) + { + case OpenDataWindowMsg msg: + var window = new SS14Window(); + window.Contents.AddChild(new Label() { Text = msg.Data }); + window.AddToScreen(); + window.Open(); + break; + } + } + } +} diff --git a/Content.Server/Content.Server.csproj b/Content.Server/Content.Server.csproj index 378740744c..b229998a91 100644 --- a/Content.Server/Content.Server.csproj +++ b/Content.Server/Content.Server.csproj @@ -107,6 +107,8 @@ + + @@ -139,5 +141,4 @@ - - \ No newline at end of file + diff --git a/Content.Server/EntryPoint.cs b/Content.Server/EntryPoint.cs index 9891a2d5a4..3d61d030e4 100644 --- a/Content.Server/EntryPoint.cs +++ b/Content.Server/EntryPoint.cs @@ -68,6 +68,7 @@ namespace Content.Server //Power Components factory.Register(); factory.Register(); + factory.RegisterReference(); factory.Register(); factory.Register(); factory.Register(); @@ -87,6 +88,9 @@ namespace Content.Server factory.Register(); factory.Register(); + + factory.Register(); + factory.Register(); } /// diff --git a/Content.Server/GameObjects/Components/Power/PowerDebugTool.cs b/Content.Server/GameObjects/Components/Power/PowerDebugTool.cs new file mode 100644 index 0000000000..d205b85693 --- /dev/null +++ b/Content.Server/GameObjects/Components/Power/PowerDebugTool.cs @@ -0,0 +1,80 @@ +using System.Text; +using Content.Server.GameObjects.EntitySystems; +using Content.Shared.GameObjects.Components.Power; +using SS14.Server.Interfaces.GameObjects; +using SS14.Shared.GameObjects; +using SS14.Shared.Interfaces.GameObjects; +using SS14.Shared.Map; + +namespace Content.Server.GameObjects.Components.Power +{ + public class PowerDebugTool : SharedPowerDebugTool, IAfterAttack + { + void IAfterAttack.Afterattack(IEntity user, LocalCoordinates clicklocation, IEntity attacked) + { + if (attacked == null) + { + return; + } + + var builder = new StringBuilder(); + + if (attacked.TryGetComponent(out var node)) + { + builder.AppendFormat("Power Node:\n"); + if (node.Parent == null) + { + builder.Append(" No Powernet!\n"); + } + else + { + builder.AppendFormat(" Powernet: {0}\n", node.Parent.Uid); + } + } + + if (attacked.TryGetComponent(out var device)) + { + builder.AppendFormat(@"Power Device: + Load: {0} W + Priority: {1} + Drawtype: {2}, Connected: {3} + Powered: {4} +", device.Load, device.Priority, device.DrawType, device.Connected, device.Powered); + + if (device.Connected == DrawTypes.Provider || device.Connected == DrawTypes.Both) + { + builder.Append(" Providers:\n"); + foreach (var provider in device.AvailableProviders) + { + var providerTransform = provider.Owner.GetComponent(); + builder.AppendFormat(" {0} @ {1}", provider.Name, providerTransform.LocalPosition); + if (device.Provider == provider) + { + builder.Append(" (CURRENT)"); + } + builder.Append('\n'); + } + } + } + + if (attacked.TryGetComponent(out var storage)) + { + builder.AppendFormat(@"Power Storage: + Capacity: {0}, Charge: {1}, ChargeRate: {2}, DistributionRate: {3}, ChargePowernet: {4} +", storage.Capacity, storage.Charge, storage.ChargeRate, storage.DistributionRate, storage.ChargePowernet); + } + + OpenDataWindowClientSide(user, builder.ToString()); + } + + private void OpenDataWindowClientSide(IEntity user, string data) + { + if (!user.TryGetComponent(out var actor)) + { + return; + } + + SendNetworkMessage(new OpenDataWindowMsg(data), actor.playerSession.ConnectedClient); + } + } +} diff --git a/Content.Server/GameObjects/Components/Power/PowerDevice.cs b/Content.Server/GameObjects/Components/Power/PowerDevice.cs index f419b31616..7df5f041d6 100644 --- a/Content.Server/GameObjects/Components/Power/PowerDevice.cs +++ b/Content.Server/GameObjects/Components/Power/PowerDevice.cs @@ -4,6 +4,7 @@ using SS14.Shared.GameObjects; using SS14.Shared.Interfaces.GameObjects; using SS14.Shared.IoC; using SS14.Shared.Utility; +using System; using System.Collections.Generic; using System.Linq; using YamlDotNet.RepresentationModel; @@ -18,24 +19,45 @@ namespace Content.Server.GameObjects.Components.Power public override string Name => "PowerDevice"; /// - /// The method of draw we will try to use to place our load set via component parameter, defaults to using power providers + /// The method of draw we will try to use to place our load set via component parameter, defaults to using power providers /// - public virtual DrawTypes Drawtype { get; protected set; } = DrawTypes.Provider; + public virtual DrawTypes DrawType { get; protected set; } = DrawTypes.Provider; /// - /// The power draw method we are currently connected to and using + /// The power draw method we are currently connected to and using /// public DrawTypes Connected { get; protected set; } = DrawTypes.None; - public bool _powered = false; + public bool Powered { get; private set; } = false; + + /// - /// Status indicator variable for powered + /// Is an external power source currently available? /// - public virtual bool Powered + public bool ExternalPowered { - get => _powered; - set => SetPowered(value); + get => _externalPowered; + set + { + _externalPowered = value; + UpdatePowered(); + } } + private bool _externalPowered = false; + + /// + /// Is an internal power source currently available? + /// + public bool InternalPowered + { + get => _internalPowered; + set + { + _internalPowered = value; + UpdatePowered(); + } + } + private bool _internalPowered = false; /// /// Priority for powernet draw, lower will draw first, defined in powernet.cs @@ -50,7 +72,7 @@ namespace Content.Server.GameObjects.Components.Power public float Load { get => _load; - set { UpdateLoad(value); } + set => UpdateLoad(value); } /// @@ -60,20 +82,22 @@ namespace Content.Server.GameObjects.Components.Power private PowerProviderComponent _provider; + /// /// A power provider that will handle our load, if we are linked to any /// public PowerProviderComponent Provider { get => _provider; - set { + set + { Connected = DrawTypes.Provider; if (_provider != null) { _provider.RemoveDevice(this); } - if(value != null) + if (value != null) { _provider = value; _provider.AddDevice(this); @@ -85,11 +109,13 @@ namespace Content.Server.GameObjects.Components.Power } } + public event EventHandler OnPowerStateChanged; + public override void OnAdd() { base.OnAdd(); - if (Drawtype == DrawTypes.Both || Drawtype == DrawTypes.Node) + if (DrawType == DrawTypes.Node || DrawType == DrawTypes.Both) { if (!Owner.TryGetComponent(out PowerNodeComponent node)) { @@ -106,7 +132,7 @@ namespace Content.Server.GameObjects.Components.Power { if (Owner.TryGetComponent(out PowerNodeComponent node)) { - if(node.Parent != null) + if (node.Parent != null) { node.Parent.RemoveDevice(this); } @@ -123,7 +149,7 @@ namespace Content.Server.GameObjects.Components.Power { if (mapping.TryGetNode("Drawtype", out YamlNode node)) { - Drawtype = node.AsEnum(); + DrawType = node.AsEnum(); } if (mapping.TryGetNode("Load", out node)) { @@ -137,7 +163,7 @@ namespace Content.Server.GameObjects.Components.Power string IExamine.Examine() { - if(!Powered) + if (!Powered) { return "The device is not powered"; } @@ -148,44 +174,32 @@ namespace Content.Server.GameObjects.Components.Power { var oldLoad = _load; _load = value; - if(Connected == DrawTypes.Node) + if (Connected == DrawTypes.Node) { var node = Owner.GetComponent(); node.Parent.UpdateDevice(this, oldLoad); } - else if(Connected == DrawTypes.Provider) + else if (Connected == DrawTypes.Provider) { Provider.UpdateDevice(this, oldLoad); } } - /// - /// Changes behavior when receiving a command to become powered or depowered - /// - /// - public virtual void SetPowered(bool value) + private void UpdatePowered() { - //Let them set us to true - if (value == true) + var oldPowered = Powered; + Powered = ExternalPowered || InternalPowered; + if (oldPowered != Powered) { - _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)) + if (Powered) { - storage.DeductCharge(Load); - _powered = true; - return; + OnPowerStateChanged?.Invoke(this, new PowerStateEventArgs(true)); + } + else + { + OnPowerStateChanged?.Invoke(this, new PowerStateEventArgs(false)); } } - - //For some reason above we could not power ourselves, we depower - _powered = false; - return; } /// @@ -196,7 +210,7 @@ namespace Content.Server.GameObjects.Components.Power { AvailableProviders.Add(provider); - if(Connected != DrawTypes.Node) + if (Connected != DrawTypes.Node) { ConnectToBestProvider(); } @@ -234,7 +248,7 @@ namespace Content.Server.GameObjects.Components.Power } } - if(Provider != bestprovider) + if (Provider != bestprovider) Provider = bestprovider; } @@ -246,9 +260,15 @@ namespace Content.Server.GameObjects.Components.Power { if (!AvailableProviders.Contains(provider)) return; - + AvailableProviders.Remove(provider); + if (provider == Provider) + { + Provider = null; + ExternalPowered = false; + } + if (Connected != DrawTypes.Node) { ConnectToBestProvider(); @@ -260,7 +280,7 @@ namespace Content.Server.GameObjects.Components.Power /// /// /// - private void PowernetConnect(object sender, PowernetEventArgs eventarg) + protected virtual void PowernetConnect(object sender, PowernetEventArgs eventarg) { //This sets connected = none so it must be first Provider = null; @@ -274,7 +294,7 @@ namespace Content.Server.GameObjects.Components.Power /// /// /// - private void PowernetRegenerate(object sender, PowernetEventArgs eventarg) + protected virtual void PowernetRegenerate(object sender, PowernetEventArgs eventarg) { eventarg.Powernet.AddDevice(this); } @@ -284,13 +304,31 @@ namespace Content.Server.GameObjects.Components.Power /// /// /// - private void PowernetDisconnect(object sender, PowernetEventArgs eventarg) + protected virtual void PowernetDisconnect(object sender, PowernetEventArgs eventarg) { eventarg.Powernet.RemoveDevice(this); Connected = DrawTypes.None; ConnectToBestProvider(); } + + internal virtual void ProcessInternalPower(float frametime) + { + if (Owner.TryGetComponent(out var storage) && storage.CanDeductCharge(Load)) + { + // We still keep InternalPowered correct if connected externally, + // but don't use it. + if (!ExternalPowered) + { + storage.DeductCharge(Load); + } + InternalPowered = true; + } + else + { + InternalPowered = false; + } + } } public enum DrawTypes @@ -298,6 +336,16 @@ namespace Content.Server.GameObjects.Components.Power None = 0, Node = 1, Provider = 2, - Both = 3 + Both = 3, + } + + public class PowerStateEventArgs : EventArgs + { + public readonly bool Powered; + + public PowerStateEventArgs(bool powered) + { + Powered = powered; + } } } diff --git a/Content.Server/GameObjects/Components/Power/PowerNodeComponent.cs b/Content.Server/GameObjects/Components/Power/PowerNodeComponent.cs index a549c84d6a..7e51d77a52 100644 --- a/Content.Server/GameObjects/Components/Power/PowerNodeComponent.cs +++ b/Content.Server/GameObjects/Components/Power/PowerNodeComponent.cs @@ -13,7 +13,7 @@ namespace Content.Server.GameObjects.Components.Power public class PowerNodeComponent : Component { public override string Name => "PowerNode"; - + /// /// The powernet this node is connected to /// @@ -57,7 +57,7 @@ namespace Content.Server.GameObjects.Components.Power .Where(x => x.HasComponent()) .OrderByDescending(x => (x.GetComponent().WorldPosition - position).Length); var choose = wires.FirstOrDefault(); - if(choose != null) + if (choose != null) ConnectToPowernet(choose.GetComponent().Parent); } @@ -68,7 +68,7 @@ namespace Content.Server.GameObjects.Components.Power public void ConnectToPowernet(Powernet toconnect) { Parent = toconnect; - Parent.Nodelist.Add(this); + Parent.NodeList.Add(this); OnPowernetConnect?.Invoke(this, new PowernetEventArgs(Parent)); } @@ -79,10 +79,10 @@ namespace Content.Server.GameObjects.Components.Power 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.NodeList.Remove(this); Parent = toconnect; - Parent.Nodelist.Add(this); + Parent.NodeList.Add(this); OnPowernetRegenerate?.Invoke(this, new PowernetEventArgs(Parent)); } @@ -91,7 +91,11 @@ namespace Content.Server.GameObjects.Components.Power /// public void DisconnectFromPowernet() { - Parent.Nodelist.Remove(this); + if (Parent == null) + { + return; + } + Parent.NodeList.Remove(this); OnPowernetDisconnect?.Invoke(this, new PowernetEventArgs(Parent)); Parent = null; } diff --git a/Content.Server/GameObjects/Components/Power/PowerProviderComponent.cs b/Content.Server/GameObjects/Components/Power/PowerProviderComponent.cs index 332cc5b1a6..af5c810612 100644 --- a/Content.Server/GameObjects/Components/Power/PowerProviderComponent.cs +++ b/Content.Server/GameObjects/Components/Power/PowerProviderComponent.cs @@ -19,7 +19,7 @@ namespace Content.Server.GameObjects.Components.Power public override string Name => "PowerProvider"; /// - public override DrawTypes Drawtype { get; protected set; } = DrawTypes.Node; + public override DrawTypes DrawType { get; protected set; } = DrawTypes.Node; /// /// Variable that determines the range that the power provider will try to supply power to @@ -29,12 +29,22 @@ namespace Content.Server.GameObjects.Components.Power /// /// List storing all the power devices that we are currently providing power to /// - public SortedSet Deviceloadlist = new SortedSet(new Powernet.DevicePriorityCompare()); + public SortedSet DeviceLoadList = new SortedSet(new Powernet.DevicePriorityCompare()); public List DepoweredDevices = new List(); public override Powernet.Priority Priority { get; protected set; } = Powernet.Priority.Provider; + public override void OnRemove() + { + base.OnRemove(); + + foreach (var device in DeviceLoadList) + { + device.RemoveProvider(this); + } + } + public override void LoadParameters(YamlMappingNode mapping) { if (mapping.TryGetNode("Range", out YamlNode node)) @@ -47,78 +57,71 @@ namespace Content.Server.GameObjects.Components.Power } } - /// - public override void SetPowered(bool value) + internal override void ProcessInternalPower(float frametime) { - //Let them set us true, we must now power all the devices that rely on us for energy - if (value == true) + // Right now let's just assume that APCs don't have a power demand themselves and as such they're always marked as powered. + InternalPowered = true; + if (!Owner.TryGetComponent(out var storage)) + { + return; + } + + if (ExternalPowered) { 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)) + if (storage.CanDeductCharge(Load)) { - //Can the storage cover powering all our devices and us? If so power all - if (storage.CanDeductCharge(Load)) + PowerAllDevices(); + storage.DeductCharge(Load); + return; + } + + var remainingLoad = storage.AvailableCharge(); + var usedLoad = 0f; + foreach (var device in DeviceLoadList) + { + if (device.Load > remainingLoad) { - storage.DeductCharge(Load); - _powered = true; - return; + device.ExternalPowered = false; + DepoweredDevices.Add(device); } - //Does the storage even have any power to give us? If so power as much as we can - else if (storage.RequestAllCharge() != 0) + else { - var depowervalue = storage.RequestAllCharge() - Load; - _powered = true; - //See code in powernet for same functionality - foreach (var device in Deviceloadlist) + if (!device.ExternalPowered) { - device.Powered = false; - DepoweredDevices.Add(device); - depowervalue -= device.Load; - if (depowervalue < 0) - break; + device.ExternalPowered = true; + DepoweredDevices.Remove(device); } - return; - } - //Storage doesn't have anything, depower everything - else if (storage.RequestAllCharge() == 0) - { - DepowerAllDevices(); - return; + usedLoad += device.Load; + remainingLoad -= device.Load; } } - //For some reason above we could not power ourselves, we depower ourselves and all devices - DepowerAllDevices(); - return; + storage.DeductCharge(usedLoad); } - private void PowerAllDevices() { - _powered = true; foreach (var device in DepoweredDevices) { - device.Powered = true; + device.ExternalPowered = true; } DepoweredDevices.Clear(); } private void DepowerAllDevices() { - _powered = false; - foreach (var device in DepoweredDevices) + foreach (var device in DeviceLoadList) { - device.Powered = false; + device.ExternalPowered = false; } } - private void PowernetConnect(object sender, PowernetEventArgs eventarg) + protected override void PowernetConnect(object sender, PowernetEventArgs eventarg) { - eventarg.Powernet.AddDevice(this); - Connected = DrawTypes.Node; + base.PowernetConnect(sender, eventarg); //Find devices within range to take under our control var _emanager = IoCManager.Resolve(); @@ -132,25 +135,20 @@ namespace Content.Server.GameObjects.Components.Power var device = entity.GetComponent(); //Make sure the device can accept power providers to give it power - if (device.Drawtype == DrawTypes.Provider || device.Drawtype == DrawTypes.Both) + 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) + protected override void PowernetDisconnect(object sender, PowernetEventArgs eventarg) { - eventarg.Powernet.RemoveDevice(this); - Connected = DrawTypes.None; + base.PowernetDisconnect(sender, eventarg); //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) + foreach (var device in DeviceLoadList.ToList()) { device.RemoveProvider(this); } @@ -161,7 +159,7 @@ namespace Content.Server.GameObjects.Components.Power /// public void AddDevice(PowerDeviceComponent device) { - Deviceloadlist.Add(device); + DeviceLoadList.Add(device); Load += device.Load; if (!device.Powered) DepoweredDevices.Add(device); @@ -172,7 +170,7 @@ namespace Content.Server.GameObjects.Components.Power /// public void UpdateDevice(PowerDeviceComponent device, float oldLoad) { - if (Deviceloadlist.Contains(device)) + if (DeviceLoadList.Contains(device)) { Load -= oldLoad; Load += device.Load; @@ -184,10 +182,10 @@ namespace Content.Server.GameObjects.Components.Power /// public void RemoveDevice(PowerDeviceComponent device) { - if (Deviceloadlist.Contains(device)) + if (DeviceLoadList.Contains(device)) { Load -= device.Load; - Deviceloadlist.Remove(device); + DeviceLoadList.Remove(device); if (DepoweredDevices.Contains(device)) DepoweredDevices.Remove(device); } diff --git a/Content.Server/GameObjects/Components/Power/PowerStorageComponent.cs b/Content.Server/GameObjects/Components/Power/PowerStorageComponent.cs index 903e3d3669..2236351173 100644 --- a/Content.Server/GameObjects/Components/Power/PowerStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Power/PowerStorageComponent.cs @@ -33,7 +33,7 @@ namespace Content.Server.GameObjects.Components.Power /// Rate at which energy will be distributed to the powernet if needed /// public float DistributionRate { get; private set; } = 1000; - + private bool _chargepowernet = false; /// @@ -156,7 +156,7 @@ namespace Content.Server.GameObjects.Components.Power /// public void ChargePowerTick() { - Charge = Math.Max(Charge + ChargeRate, Capacity); + Charge = Math.Min(Charge + ChargeRate, Capacity); } /// diff --git a/Content.Server/GameObjects/Components/Power/PowerTransferComponent.cs b/Content.Server/GameObjects/Components/Power/PowerTransferComponent.cs index 6e54451ffa..877c68b516 100644 --- a/Content.Server/GameObjects/Components/Power/PowerTransferComponent.cs +++ b/Content.Server/GameObjects/Components/Power/PowerTransferComponent.cs @@ -25,7 +25,7 @@ namespace Content.Server.GameObjects.Components.Power public override void Initialize() { - if(Parent == null) + if (Parent == null) { SpreadPowernet(); } @@ -49,7 +49,7 @@ namespace Content.Server.GameObjects.Components.Power .Where(x => x.HasComponent()); //we have no parent so lets find a partner we can join his powernet - if(Parent == null || Regenerating) + if (Parent == null || Regenerating) { foreach (var wire in wires) { @@ -74,13 +74,13 @@ namespace Content.Server.GameObjects.Components.Power .Where(x => x.HasComponent()) .Select(x => x.GetComponent()); - foreach(var node in nodes) + foreach (var node in nodes) { - if(node.Parent == null) + if (node.Parent == null) { node.ConnectToPowernet(Parent); } - else if(node.Parent.Dirty) + else if (node.Parent.Dirty) { node.RegeneratePowernet(Parent); } @@ -95,7 +95,7 @@ namespace Content.Server.GameObjects.Components.Power ptc.ConnectToPowernet(Parent); SpreadPowernet(); } - else if(ptc.Parent != Parent && !ptc.Parent.Dirty) + else if (ptc.Parent != Parent && !ptc.Parent.Dirty) { Parent.MergePowernets(ptc.Parent); } @@ -109,7 +109,7 @@ namespace Content.Server.GameObjects.Components.Power public void ConnectToPowernet(Powernet toconnect) { Parent = toconnect; - Parent.Wirelist.Add(this); + Parent.WireList.Add(this); Regenerating = false; } @@ -118,7 +118,7 @@ namespace Content.Server.GameObjects.Components.Power /// public void DisconnectFromPowernet() { - Parent.Wirelist.Remove(this); + Parent.WireList.Remove(this); Parent.Dirty = true; Parent = null; } @@ -131,7 +131,7 @@ namespace Content.Server.GameObjects.Components.Power public bool Attackby(IEntity user, IEntity attackwith) { - if(attackwith.TryGetComponent(out WirecutterComponent wirecutter)) + if (attackwith.TryGetComponent(out WirecutterComponent wirecutter)) { Owner.Delete(); return true; diff --git a/Content.Server/GameObjects/Components/Power/PoweredLightComponent.cs b/Content.Server/GameObjects/Components/Power/PoweredLightComponent.cs new file mode 100644 index 0000000000..c2635b27dd --- /dev/null +++ b/Content.Server/GameObjects/Components/Power/PoweredLightComponent.cs @@ -0,0 +1,33 @@ +using SS14.Server.GameObjects; +using SS14.Shared.Enums; +using SS14.Shared.GameObjects; + +namespace Content.Server.GameObjects.Components.Power +{ + public class PoweredLightComponent : Component + { + public override string Name => "PoweredLight"; + + public override void Initialize() + { + base.Initialize(); + + var device = Owner.GetComponent(); + var sprite = Owner.GetComponent(); + var light = Owner.GetComponent(); + device.OnPowerStateChanged += (sender, args) => + { + if (args.Powered) + { + sprite.LayerSetTexture(0, "Objects/wall_light.png"); + light.State = LightState.On; + } + else + { + sprite.LayerSetTexture(0, "Objects/wall_light_off.png"); + light.State = LightState.Off; + } + }; + } + } +} diff --git a/Content.Server/GameObjects/Components/Power/Powernet.cs b/Content.Server/GameObjects/Components/Power/Powernet.cs index b2e8114c69..7a1f429ec7 100644 --- a/Content.Server/GameObjects/Components/Power/Powernet.cs +++ b/Content.Server/GameObjects/Components/Power/Powernet.cs @@ -15,28 +15,32 @@ namespace Content.Server.GameObjects.Components.Power public Powernet() { var EntitySystemManager = IoCManager.Resolve(); - EntitySystemManager.GetEntitySystem().Powernets.Add(this); + var powerSystem = EntitySystemManager.GetEntitySystem(); + powerSystem.Powernets.Add(this); + Uid = powerSystem.NewUid(); } + public int Uid { get; } + /// /// The entities that make up the powernet's physical location and allow powernet connection /// - public List Wirelist { get; set; } = new List(); + public List WireList { get; set; } = new List(); /// /// Entities that connect directly to the powernet through PTC above to add power or add power load /// - public List Nodelist { get; set; } = new List(); + public List NodeList { get; set; } = new List(); /// /// Subset of nodelist that adds a continuous power supply to the network /// - public Dictionary Generatorlist { get; set; } = new Dictionary(); + public Dictionary GeneratorList { get; set; } = new Dictionary(); /// /// Subset of nodelist that draw power, stores information on current continuous powernet load /// - public SortedSet Deviceloadlist { get; set; } = new SortedSet(new DevicePriorityCompare()); + public SortedSet DeviceLoadList { get; set; } = new SortedSet(new DevicePriorityCompare()); /// /// Comparer that keeps the device dictionary sorted by powernet priority @@ -156,9 +160,9 @@ namespace Content.Server.GameObjects.Components.Power var depowervalue = activeload - (activesupply + passivesupply); //Providers use same method to recreate functionality - foreach (var device in Deviceloadlist) + foreach (var device in DeviceLoadList) { - device.Powered = false; + device.ExternalPowered = false; DepoweredDevices.Add(device); depowervalue -= device.Load; if (depowervalue < 0) @@ -171,7 +175,7 @@ namespace Content.Server.GameObjects.Components.Power { foreach (var device in DepoweredDevices) { - device.Powered = true; + device.ExternalPowered = true; } DepoweredDevices.Clear(); } @@ -205,13 +209,13 @@ namespace Content.Server.GameObjects.Components.Power /// public void DirtyKill() { - Wirelist.Clear(); - while (Nodelist.Count != 0) + WireList.Clear(); + while (NodeList.Count != 0) { - Nodelist[0].DisconnectFromPowernet(); + NodeList[0].DisconnectFromPowernet(); } - Generatorlist.Clear(); - Deviceloadlist.Clear(); + GeneratorList.Clear(); + DeviceLoadList.Clear(); DepoweredDevices.Clear(); PowerStorageSupplierlist.Clear(); PowerStorageConsumerlist.Clear(); @@ -226,31 +230,31 @@ namespace Content.Server.GameObjects.Components.Power { //TODO: load balance reconciliation between powernets on merge tick here - foreach (var wire in toMerge.Wirelist) + foreach (var wire in toMerge.WireList) { wire.Parent = this; } - Wirelist.AddRange(toMerge.Wirelist); - toMerge.Wirelist.Clear(); + WireList.AddRange(toMerge.WireList); + toMerge.WireList.Clear(); - foreach (var node in toMerge.Nodelist) + foreach (var node in toMerge.NodeList) { node.Parent = this; } - Nodelist.AddRange(toMerge.Nodelist); - toMerge.Nodelist.Clear(); + NodeList.AddRange(toMerge.NodeList); + toMerge.NodeList.Clear(); - foreach (var generator in toMerge.Generatorlist) + foreach (var generator in toMerge.GeneratorList) { - Generatorlist.Add(generator.Key, generator.Value); + GeneratorList.Add(generator.Key, generator.Value); } - toMerge.Generatorlist.Clear(); + toMerge.GeneratorList.Clear(); - foreach (var device in toMerge.Deviceloadlist) + foreach (var device in toMerge.DeviceLoadList) { - Deviceloadlist.Add(device); + DeviceLoadList.Add(device); } - toMerge.Deviceloadlist.Clear(); + toMerge.DeviceLoadList.Clear(); DepoweredDevices.AddRange(toMerge.DepoweredDevices); toMerge.DepoweredDevices.Clear(); @@ -280,7 +284,7 @@ namespace Content.Server.GameObjects.Components.Power /// public void AddDevice(PowerDeviceComponent device) { - Deviceloadlist.Add(device); + DeviceLoadList.Add(device); Load += device.Load; if (!device.Powered) DepoweredDevices.Add(device); @@ -291,7 +295,7 @@ namespace Content.Server.GameObjects.Components.Power /// public void UpdateDevice(PowerDeviceComponent device, float oldLoad) { - if (Deviceloadlist.Contains(device)) + if (DeviceLoadList.Contains(device)) { Load -= oldLoad; Load += device.Load; @@ -303,10 +307,10 @@ namespace Content.Server.GameObjects.Components.Power /// public void RemoveDevice(PowerDeviceComponent device) { - if (Deviceloadlist.Contains(device)) + if (DeviceLoadList.Contains(device)) { Load -= device.Load; - Deviceloadlist.Remove(device); + DeviceLoadList.Remove(device); if (DepoweredDevices.Contains(device)) DepoweredDevices.Remove(device); } @@ -322,7 +326,7 @@ namespace Content.Server.GameObjects.Components.Power /// public void AddGenerator(PowerGeneratorComponent generator) { - Generatorlist.Add(generator, generator.Supply); + GeneratorList.Add(generator, generator.Supply); Supply += generator.Supply; } @@ -331,10 +335,10 @@ namespace Content.Server.GameObjects.Components.Power /// public void UpdateGenerator(PowerGeneratorComponent generator) { - if (Generatorlist.ContainsKey(generator)) + if (GeneratorList.ContainsKey(generator)) { - Supply -= Generatorlist[generator]; - Generatorlist[generator] = generator.Supply; + Supply -= GeneratorList[generator]; + GeneratorList[generator] = generator.Supply; Supply += generator.Supply; } } @@ -344,10 +348,10 @@ namespace Content.Server.GameObjects.Components.Power /// public void RemoveGenerator(PowerGeneratorComponent generator) { - if (Generatorlist.ContainsKey(generator)) + if (GeneratorList.ContainsKey(generator)) { - Supply -= Generatorlist[generator]; - Generatorlist.Remove(generator); + Supply -= GeneratorList[generator]; + GeneratorList.Remove(generator); } else { diff --git a/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs b/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs index a8a8307aa9..cf9cfb1abf 100644 --- a/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs @@ -31,18 +31,18 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee } - void IAfterAttack.Afterattack(IEntity user, LocalCoordinates clicklocation) + void IAfterAttack.Afterattack(IEntity user, LocalCoordinates clicklocation, IEntity attacked) { var location = user.GetComponent().LocalPosition; var angle = new Angle(clicklocation.ToWorld().Position - location.ToWorld().Position); var entities = IoCManager.Resolve().GetEntitiesInArc(user.GetComponent().LocalPosition, Range, angle, ArcWidth); - foreach(var entity in entities) + foreach (var entity in entities) { if (!entity.GetComponent().IsMapTransform || entity == user) continue; - - if(entity.TryGetComponent(out DamageableComponent damagecomponent)) + + if (entity.TryGetComponent(out DamageableComponent damagecomponent)) { damagecomponent.TakeDamage(DamageType.Brute, Damage); } diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/RangedWeapon.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/RangedWeapon.cs index d9aae20c2e..3edad9c967 100644 --- a/Content.Server/GameObjects/Components/Weapon/Ranged/RangedWeapon.cs +++ b/Content.Server/GameObjects/Components/Weapon/Ranged/RangedWeapon.cs @@ -9,9 +9,9 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged { public override string Name => "RangedWeapon"; - void IAfterAttack.Afterattack(IEntity user, LocalCoordinates clicklocation) + void IAfterAttack.Afterattack(IEntity user, LocalCoordinates clicklocation, IEntity attacked) { - if(UserCanFire(user) && WeaponCanFire()) + if (UserCanFire(user) && WeaponCanFire()) { Fire(user, clicklocation); } diff --git a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs index a48ed41659..7b6dce0985 100644 --- a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs @@ -65,7 +65,8 @@ namespace Content.Server.GameObjects.EntitySystems /// /// /// - void Afterattack(IEntity user, LocalCoordinates clicklocation); + /// The entity that was clicked on out of range. May be null if no entity was clicked on.true + void Afterattack(IEntity user, LocalCoordinates clicklocation, IEntity attacked); } /// @@ -198,7 +199,7 @@ namespace Content.Server.GameObjects.EntitySystems for (var i = 0; i < afterattacks.Count; i++) { - afterattacks[i].Afterattack(user, clicklocation); + afterattacks[i].Afterattack(user, clicklocation, null); } } @@ -229,7 +230,7 @@ namespace Content.Server.GameObjects.EntitySystems for (var i = 0; i < afterattacks.Count; i++) { - afterattacks[i].Afterattack(user, clicklocation); + afterattacks[i].Afterattack(user, clicklocation, attacked); } } @@ -315,7 +316,7 @@ namespace Content.Server.GameObjects.EntitySystems //See if we have a ranged attack interaction for (var i = 0; i < afterattacks.Count; i++) { - afterattacks[i].Afterattack(user, clicklocation); + afterattacks[i].Afterattack(user, clicklocation, attacked); } } } diff --git a/Content.Server/GameObjects/EntitySystems/PowerSystem.cs b/Content.Server/GameObjects/EntitySystems/PowerSystem.cs index f7af4d77e7..7de5fab966 100644 --- a/Content.Server/GameObjects/EntitySystems/PowerSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/PowerSystem.cs @@ -1,5 +1,7 @@ using Content.Server.GameObjects.Components.Power; using SS14.Shared.GameObjects.System; +using SS14.Shared.Interfaces.GameObjects; +using SS14.Shared.IoC; using System; using System.Collections.Generic; using System.Linq; @@ -12,6 +14,21 @@ namespace Content.Shared.GameObjects.EntitySystems { public List Powernets = new List(); + private IComponentManager componentManager; + + private int _lastUid = 0; + + public override void Initialize() + { + base.Initialize(); + componentManager = IoCManager.Resolve(); + } + + public int NewUid() + { + return ++_lastUid; + } + public override void Update(float frametime) { for (int i = 0; i < Powernets.Count; i++) @@ -20,12 +37,12 @@ namespace Content.Shared.GameObjects.EntitySystems if (powernet.Dirty) { //Tell all the wires of this net to be prepared to create/join new powernets - foreach (var wire in powernet.Wirelist) + foreach (var wire in powernet.WireList) { wire.Regenerating = true; } - foreach (var wire in powernet.Wirelist) + foreach (var wire in powernet.WireList) { //Only a few wires should pass this if check since each will create and take all the others into its powernet if (wire.Regenerating) @@ -38,10 +55,16 @@ namespace Content.Shared.GameObjects.EntitySystems } } - foreach(var powernet in Powernets) + foreach (var powernet in Powernets) { powernet.Update(frametime); } + + // Draw power for devices not connected to anything. + foreach (var device in componentManager.GetComponents()) + { + device.ProcessInternalPower(frametime); + } } } } diff --git a/Content.Shared/Content.Shared.csproj b/Content.Shared/Content.Shared.csproj index c1a950de18..70e509dc1e 100644 --- a/Content.Shared/Content.Shared.csproj +++ b/Content.Shared/Content.Shared.csproj @@ -72,6 +72,7 @@ + @@ -101,4 +102,4 @@ - \ No newline at end of file + diff --git a/Content.Shared/GameObjects/Components/Power/SharedPowerDebugTool.cs b/Content.Shared/GameObjects/Components/Power/SharedPowerDebugTool.cs new file mode 100644 index 0000000000..55c3feb69e --- /dev/null +++ b/Content.Shared/GameObjects/Components/Power/SharedPowerDebugTool.cs @@ -0,0 +1,24 @@ +using System; +using SS14.Shared.GameObjects; +using SS14.Shared.Serialization; + +namespace Content.Shared.GameObjects.Components.Power +{ + public class SharedPowerDebugTool : Component + { + public override string Name => "PowerDebugTool"; + public override uint? NetID => ContentNetIDs.POWER_DEBUG_TOOL; + + [Serializable, NetSerializable] + protected class OpenDataWindowMsg : ComponentMessage + { + public string Data { get; } + + public OpenDataWindowMsg(string data) + { + Directed = true; + Data = data; + } + } + } +} diff --git a/Content.Shared/GameObjects/ContentNetIDs.cs b/Content.Shared/GameObjects/ContentNetIDs.cs index afd6937958..f2d359196b 100644 --- a/Content.Shared/GameObjects/ContentNetIDs.cs +++ b/Content.Shared/GameObjects/ContentNetIDs.cs @@ -9,5 +9,6 @@ public const uint HANDS = 1003; public const uint STORAGE = 1005; public const uint INVENTORY = 1006; + public const uint POWER_DEBUG_TOOL = 1007; } } diff --git a/Resources/Prototypes/Entities/Power.yml b/Resources/Prototypes/Entities/Power.yml index 249bc8330f..1d83a8c6f6 100644 --- a/Resources/Prototypes/Entities/Power.yml +++ b/Resources/Prototypes/Entities/Power.yml @@ -57,6 +57,7 @@ - type: PowerProvider Range: 5 Priority: Provider + Load: 0 - type: entity parent: WPPnobattery diff --git a/Resources/Prototypes/Entities/PoweredLighting.yml b/Resources/Prototypes/Entities/PoweredLighting.yml new file mode 100644 index 0000000000..0cd57da13e --- /dev/null +++ b/Resources/Prototypes/Entities/PoweredLighting.yml @@ -0,0 +1,17 @@ +- type: entity + name: Light + id: poweredlight + parent: __engine_wall_light + components: + # So we can click on it for deletion. + - type: BoundingBox + - type: Sprite + texture: Objects/wall_light_off.png + + - type: PowerDevice + load: 1 + priority: Low + + - type: PoweredLight + - type: PointLight + state: Off diff --git a/Resources/Prototypes/Entities/Tools.yml b/Resources/Prototypes/Entities/Tools.yml index 9fb88cb60c..18f9dad7b5 100644 --- a/Resources/Prototypes/Entities/Tools.yml +++ b/Resources/Prototypes/Entities/Tools.yml @@ -81,3 +81,4 @@ texture: Objects/multitool.png - type: Icon texture: Objects/multitool.png + - type: PowerDebugTool diff --git a/engine b/engine index dc80060757..6f4ea205ef 160000 --- a/engine +++ b/engine @@ -1 +1 @@ -Subproject commit dc80060757a740260af0b4e63ed6ff7591947812 +Subproject commit 6f4ea205efdd273bf7dfa29fdd78096877505e9f