diff --git a/Content.Server/Solar/EntitySystems/PowerSolarSystem.cs b/Content.Server/Solar/EntitySystems/PowerSolarSystem.cs index a2400f1469..366cab3885 100644 --- a/Content.Server/Solar/EntitySystems/PowerSolarSystem.cs +++ b/Content.Server/Solar/EntitySystems/PowerSolarSystem.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using Content.Server.Power.Components; using Content.Server.Solar.Components; @@ -10,7 +11,6 @@ using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Random; -using Robust.Shared.Timing; namespace Content.Server.Solar.EntitySystems { @@ -20,8 +20,8 @@ namespace Content.Server.Solar.EntitySystems [UsedImplicitly] internal sealed class PowerSolarSystem : EntitySystem { - [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly IRobustRandom _robustRandom = default!; + [Dependency] private readonly SharedPhysicsSystem _physicsSystem = default!; /// /// Maximum panel angular velocity range - used to stop people rotating panels fast enough that the lag prevention becomes noticable @@ -44,19 +44,6 @@ namespace Content.Server.Solar.EntitySystems /// public float SunOcclusionCheckDistance = 20; - /// - /// This is the per-second value used to reduce solar panel coverage updates - /// (and the resulting occlusion raycasts) - /// to within sane boundaries. - /// Keep in mind, this is not exact, as the random interval is also applied. - /// - public TimeSpan SolarCoverageUpdateInterval = TimeSpan.FromSeconds(5); - - /// - /// A random interval used to stagger solar coverage updates reliably. - /// - public TimeSpan SolarCoverageUpdateRandomInterval = TimeSpan.FromSeconds(5); - /// /// TODO: *Should be moved into the solar tracker when powernet allows for it.* /// The current target panel rotation. @@ -75,6 +62,12 @@ namespace Content.Server.Solar.EntitySystems /// public float TotalPanelPower = 0; + /// + /// Queue of panels to update each cycle. + /// + private readonly Queue _updateQueue = new(); + + public override void Initialize() { SubscribeLocalEvent(OnMapInit); @@ -110,21 +103,21 @@ namespace Content.Server.Solar.EntitySystems TargetPanelRotation += TargetPanelVelocity * frameTime; TargetPanelRotation = TargetPanelRotation.Reduced(); - TotalPanelPower = 0; - - foreach (var panel in EntityManager.EntityQuery()) + if (_updateQueue.Count > 0) { - if (panel.TimeOfNextCoverageUpdate < _gameTiming.CurTime) - { - // Coverage update time! - // There's supposed to be rotational logic here, but that implies putting it somewhere. - panel.Owner.Transform.WorldRotation = TargetPanelRotation; - // Setup the next coverage check. - TimeSpan future = SolarCoverageUpdateInterval + (SolarCoverageUpdateRandomInterval * _robustRandom.NextDouble()); - panel.TimeOfNextCoverageUpdate = _gameTiming.CurTime + future; + var panel = _updateQueue.Dequeue(); + if (panel.Running) UpdatePanelCoverage(panel); + } + else + { + TotalPanelPower = 0; + foreach (var panel in EntityManager.EntityQuery()) + { + TotalPanelPower += panel.MaxSupply * panel.Coverage; + panel.Owner.Transform.WorldRotation = TargetPanelRotation; + _updateQueue.Enqueue(panel); } - TotalPanelPower += panel.Coverage * panel.MaxSupply; } } @@ -163,7 +156,11 @@ namespace Content.Server.Solar.EntitySystems // Determine if the solar panel is occluded, and zero out coverage if so. // FIXME: The "Opaque" collision group doesn't seem to work right now. var ray = new CollisionRay(entity.Transform.WorldPosition, TowardsSun.ToWorldVec(), (int) CollisionGroup.Opaque); - var rayCastResults = Get().IntersectRay(entity.Transform.MapID, ray, SunOcclusionCheckDistance, entity); + var rayCastResults = _physicsSystem.IntersectRayWithPredicate( + entity.Transform.MapID, + ray, + SunOcclusionCheckDistance, + e => !e.Transform.Anchored || e == entity); if (rayCastResults.Any()) coverage = 0; }