Convert TimedSpawnerComponent to use an Update loop (#37785)
Convert TimedSpawnerComponent to use an Update loop
This commit is contained in:
@@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user