Optimise drains (#32230)

* Optimise drains

If it's still a problem then we do what I did for rmc14 and just dump all the active drains onto a job to getentitiesinrange in parallel.

* Fixes
This commit is contained in:
metalgearsloth
2024-09-28 15:16:54 +10:00
committed by GitHub
parent caac678fa6
commit dd376e4e84
2 changed files with 16 additions and 26 deletions

View File

@@ -1,5 +1,4 @@
using Content.Server.DoAfter; using Content.Server.DoAfter;
using Content.Server.Fluids.Components;
using Content.Server.Popups; using Content.Server.Popups;
using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Audio; using Content.Shared.Audio;
@@ -13,9 +12,7 @@ using Content.Shared.Fluids.Components;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Tag; using Content.Shared.Tag;
using Content.Shared.Verbs; using Content.Shared.Verbs;
using Robust.Server.GameObjects;
using Robust.Shared.Audio.Systems; using Robust.Shared.Audio.Systems;
using Robust.Shared.Collections;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Utility; using Robust.Shared.Utility;
@@ -32,19 +29,27 @@ public sealed class DrainSystem : SharedDrainSystem
[Dependency] private readonly TagSystem _tagSystem = default!; [Dependency] private readonly TagSystem _tagSystem = default!;
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!; [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly PuddleSystem _puddleSystem = default!; [Dependency] private readonly PuddleSystem _puddleSystem = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private readonly HashSet<Entity<PuddleComponent>> _puddles = new();
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<DrainComponent, MapInitEvent>(OnDrainMapInit);
SubscribeLocalEvent<DrainComponent, GetVerbsEvent<Verb>>(AddEmptyVerb); SubscribeLocalEvent<DrainComponent, GetVerbsEvent<Verb>>(AddEmptyVerb);
SubscribeLocalEvent<DrainComponent, ExaminedEvent>(OnExamined); SubscribeLocalEvent<DrainComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<DrainComponent, AfterInteractUsingEvent>(OnInteract); SubscribeLocalEvent<DrainComponent, AfterInteractUsingEvent>(OnInteract);
SubscribeLocalEvent<DrainComponent, DrainDoAfterEvent>(OnDoAfter); SubscribeLocalEvent<DrainComponent, DrainDoAfterEvent>(OnDoAfter);
} }
private void OnDrainMapInit(Entity<DrainComponent> ent, ref MapInitEvent args)
{
// Randomise puddle drains so roundstart ones don't all dump at the same time.
ent.Comp.Accumulator = _random.NextFloat(ent.Comp.DrainFrequency);
}
private void AddEmptyVerb(Entity<DrainComponent> entity, ref GetVerbsEvent<Verb> args) private void AddEmptyVerb(Entity<DrainComponent> entity, ref GetVerbsEvent<Verb> args)
{ {
if (!args.CanAccess || !args.CanInteract || args.Using == null) if (!args.CanAccess || !args.CanInteract || args.Using == null)
@@ -118,9 +123,6 @@ public sealed class DrainSystem : SharedDrainSystem
{ {
base.Update(frameTime); base.Update(frameTime);
var managerQuery = GetEntityQuery<SolutionContainerManagerComponent>(); var managerQuery = GetEntityQuery<SolutionContainerManagerComponent>();
var xformQuery = GetEntityQuery<TransformComponent>();
var puddleQuery = GetEntityQuery<PuddleComponent>();
var puddles = new ValueList<(Entity<PuddleComponent> Entity, string Solution)>();
var query = EntityQueryEnumerator<DrainComponent>(); var query = EntityQueryEnumerator<DrainComponent>();
while (query.MoveNext(out var uid, out var drain)) while (query.MoveNext(out var uid, out var drain))
@@ -158,22 +160,10 @@ public sealed class DrainSystem : SharedDrainSystem
// This will ensure that UnitsPerSecond is per second... // This will ensure that UnitsPerSecond is per second...
var amount = drain.UnitsPerSecond * drain.DrainFrequency; var amount = drain.UnitsPerSecond * drain.DrainFrequency;
if (!xformQuery.TryGetComponent(uid, out var xform)) _puddles.Clear();
continue; _lookup.GetEntitiesInRange(Transform(uid).Coordinates, drain.Range, _puddles);
puddles.Clear(); if (_puddles.Count == 0)
foreach (var entity in _lookup.GetEntitiesInRange(_transform.GetMapCoordinates(uid, xform), drain.Range))
{
// No InRangeUnobstructed because there's no collision group that fits right now
// and these are placed by mappers and not buildable/movable so shouldnt really be a problem...
if (puddleQuery.TryGetComponent(entity, out var puddle))
{
puddles.Add(((entity, puddle), puddle.SolutionName));
}
}
if (puddles.Count == 0)
{ {
_ambientSoundSystem.SetAmbience(uid, false); _ambientSoundSystem.SetAmbience(uid, false);
continue; continue;
@@ -181,13 +171,13 @@ public sealed class DrainSystem : SharedDrainSystem
_ambientSoundSystem.SetAmbience(uid, true); _ambientSoundSystem.SetAmbience(uid, true);
amount /= puddles.Count; amount /= _puddles.Count;
foreach (var (puddle, solution) in puddles) foreach (var puddle in _puddles)
{ {
// Queue the solution deletion if it's empty. EvaporationSystem might also do this // Queue the solution deletion if it's empty. EvaporationSystem might also do this
// but queuedelete should be pretty safe. // but queuedelete should be pretty safe.
if (!_solutionContainerSystem.ResolveSolution(puddle.Owner, solution, ref puddle.Comp.Solution, out var puddleSolution)) if (!_solutionContainerSystem.ResolveSolution(puddle.Owner, puddle.Comp.SolutionName, ref puddle.Comp.Solution, out var puddleSolution))
{ {
EntityManager.QueueDeleteEntity(puddle); EntityManager.QueueDeleteEntity(puddle);
continue; continue;

View File

@@ -52,7 +52,7 @@ public sealed partial class DrainComponent : Component
/// drain puddles from. /// drain puddles from.
/// </summary> /// </summary>
[DataField] [DataField]
public float Range = 2f; public float Range = 2.5f;
/// <summary> /// <summary>
/// How often in seconds the drain checks for puddles around it. /// How often in seconds the drain checks for puddles around it.