Convert TimedSpawnerComponent to use an Update loop (#37785)

Convert TimedSpawnerComponent to use an Update loop
This commit is contained in:
Tayrtahn
2025-05-24 13:35:17 -04:00
committed by GitHub
parent 8264f6cd3b
commit f4efaaeb72
2 changed files with 32 additions and 16 deletions

View File

@@ -1,6 +1,6 @@
using System.Threading; using Robust.Shared.Prototypes;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server.Spawners.Components; namespace Content.Server.Spawners.Components;
@@ -10,6 +10,7 @@ namespace Content.Server.Spawners.Components;
/// and min/max number of entities to spawn. /// and min/max number of entities to spawn.
/// </summary> /// </summary>
[RegisterComponent, EntityCategory("Spawner")] [RegisterComponent, EntityCategory("Spawner")]
[AutoGenerateComponentPause]
public sealed partial class TimedSpawnerComponent : Component, ISerializationHooks public sealed partial class TimedSpawnerComponent : Component, ISerializationHooks
{ {
/// <summary> /// <summary>
@@ -30,7 +31,7 @@ public sealed partial class TimedSpawnerComponent : Component, ISerializationHoo
/// Length of the interval between spawn attempts. /// Length of the interval between spawn attempts.
/// </summary> /// </summary>
[DataField] [DataField]
public int IntervalSeconds = 60; public TimeSpan IntervalSeconds = TimeSpan.FromSeconds(60);
/// <summary> /// <summary>
/// The minimum number of entities that can be spawned when an interval elapses. /// The minimum number of entities that can be spawned when an interval elapses.
@@ -44,7 +45,11 @@ public sealed partial class TimedSpawnerComponent : Component, ISerializationHoo
[DataField] [DataField]
public int MaximumEntitiesSpawned = 1; public int MaximumEntitiesSpawned = 1;
public CancellationTokenSource? TokenSource; /// <summary>
/// The time at which the current interval will have elapsed and entities may be spawned.
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
public TimeSpan NextFire = TimeSpan.Zero;
void ISerializationHooks.AfterDeserialization() void ISerializationHooks.AfterDeserialization()
{ {

View File

@@ -1,25 +1,41 @@
using System.Threading;
using Content.Server.Spawners.Components; using Content.Server.Spawners.Components;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Server.Spawners.EntitySystems; namespace Content.Server.Spawners.EntitySystems;
public sealed class SpawnerSystem : EntitySystem public sealed class SpawnerSystem : EntitySystem
{ {
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<TimedSpawnerComponent, ComponentInit>(OnSpawnerInit);
SubscribeLocalEvent<TimedSpawnerComponent, ComponentShutdown>(OnTimedSpawnerShutdown); SubscribeLocalEvent<TimedSpawnerComponent, MapInitEvent>(OnMapInit);
} }
private void OnSpawnerInit(EntityUid uid, TimedSpawnerComponent component, ComponentInit args) public override void Update(float frameTime)
{ {
component.TokenSource?.Cancel(); base.Update(frameTime);
component.TokenSource = new CancellationTokenSource();
uid.SpawnRepeatingTimer(TimeSpan.FromSeconds(component.IntervalSeconds), () => OnTimerFired(uid, component), component.TokenSource.Token); var curTime = _timing.CurTime;
var query = EntityQueryEnumerator<TimedSpawnerComponent>();
while (query.MoveNext(out var uid, out var timedSpawner))
{
if (timedSpawner.NextFire > curTime)
continue;
OnTimerFired(uid, timedSpawner);
timedSpawner.NextFire += timedSpawner.IntervalSeconds;
}
}
private void OnMapInit(Entity<TimedSpawnerComponent> ent, ref MapInitEvent args)
{
ent.Comp.NextFire = _timing.CurTime + ent.Comp.IntervalSeconds;
} }
private void OnTimerFired(EntityUid uid, TimedSpawnerComponent component) private void OnTimerFired(EntityUid uid, TimedSpawnerComponent component)
@@ -36,9 +52,4 @@ public sealed class SpawnerSystem : EntitySystem
SpawnAtPosition(entity, coordinates); SpawnAtPosition(entity, coordinates);
} }
} }
private void OnTimedSpawnerShutdown(EntityUid uid, TimedSpawnerComponent component, ComponentShutdown args)
{
component.TokenSource?.Cancel();
}
} }