Solar panel optimizations (#5392)
* Rewrite solar panel update scheduling * Use predicate to filter out non-anchored entities from solar raytrace * Remove unused dependency * Cache physics system Co-authored-by: Tomeno <tomeno@lulzsec.co.uk>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Solar.Components;
|
using Content.Server.Solar.Components;
|
||||||
@@ -10,7 +11,6 @@ using Robust.Shared.IoC;
|
|||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
|
||||||
|
|
||||||
namespace Content.Server.Solar.EntitySystems
|
namespace Content.Server.Solar.EntitySystems
|
||||||
{
|
{
|
||||||
@@ -20,8 +20,8 @@ namespace Content.Server.Solar.EntitySystems
|
|||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
internal sealed class PowerSolarSystem : EntitySystem
|
internal sealed class PowerSolarSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
|
||||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||||
|
[Dependency] private readonly SharedPhysicsSystem _physicsSystem = default!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum panel angular velocity range - used to stop people rotating panels fast enough that the lag prevention becomes noticable
|
/// 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
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float SunOcclusionCheckDistance = 20;
|
public float SunOcclusionCheckDistance = 20;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 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.
|
|
||||||
/// </summary>
|
|
||||||
public TimeSpan SolarCoverageUpdateInterval = TimeSpan.FromSeconds(5);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A random interval used to stagger solar coverage updates reliably.
|
|
||||||
/// </summary>
|
|
||||||
public TimeSpan SolarCoverageUpdateRandomInterval = TimeSpan.FromSeconds(5);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TODO: *Should be moved into the solar tracker when powernet allows for it.*
|
/// TODO: *Should be moved into the solar tracker when powernet allows for it.*
|
||||||
/// The current target panel rotation.
|
/// The current target panel rotation.
|
||||||
@@ -75,6 +62,12 @@ namespace Content.Server.Solar.EntitySystems
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float TotalPanelPower = 0;
|
public float TotalPanelPower = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue of panels to update each cycle.
|
||||||
|
/// </summary>
|
||||||
|
private readonly Queue<SolarPanelComponent> _updateQueue = new();
|
||||||
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<SolarPanelComponent, MapInitEvent>(OnMapInit);
|
SubscribeLocalEvent<SolarPanelComponent, MapInitEvent>(OnMapInit);
|
||||||
@@ -110,21 +103,21 @@ namespace Content.Server.Solar.EntitySystems
|
|||||||
TargetPanelRotation += TargetPanelVelocity * frameTime;
|
TargetPanelRotation += TargetPanelVelocity * frameTime;
|
||||||
TargetPanelRotation = TargetPanelRotation.Reduced();
|
TargetPanelRotation = TargetPanelRotation.Reduced();
|
||||||
|
|
||||||
TotalPanelPower = 0;
|
if (_updateQueue.Count > 0)
|
||||||
|
|
||||||
foreach (var panel in EntityManager.EntityQuery<SolarPanelComponent>())
|
|
||||||
{
|
{
|
||||||
if (panel.TimeOfNextCoverageUpdate < _gameTiming.CurTime)
|
var panel = _updateQueue.Dequeue();
|
||||||
{
|
if (panel.Running)
|
||||||
// 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;
|
|
||||||
UpdatePanelCoverage(panel);
|
UpdatePanelCoverage(panel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TotalPanelPower = 0;
|
||||||
|
foreach (var panel in EntityManager.EntityQuery<SolarPanelComponent>())
|
||||||
|
{
|
||||||
|
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.
|
// 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.
|
// 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 ray = new CollisionRay(entity.Transform.WorldPosition, TowardsSun.ToWorldVec(), (int) CollisionGroup.Opaque);
|
||||||
var rayCastResults = Get<SharedPhysicsSystem>().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())
|
if (rayCastResults.Any())
|
||||||
coverage = 0;
|
coverage = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user