using Content.Shared._ES.Core.Timer.Components; using JetBrains.Annotations; using Robust.Shared.Spawners; using Robust.Shared.Timing; using Robust.Shared.Utility; namespace Content.Shared._ES.Core.Timer; /// /// This handles /// public sealed class ESTimedDespawnSystem : EntitySystem { [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; private readonly HashSet _toDelete = []; /// public override void Initialize() { SubscribeLocalEvent(OnMapInit); } private void OnMapInit(Entity ent, ref MapInitEvent args) { SetLifetime(ent.AsNullable(), ent.Comp.Lifetime); } /// /// Sets the lifetime of the entity, adjusting the despawn time to compensate /// [PublicAPI] public void SetLifetime(Entity ent, TimeSpan lifetime) { if (!Resolve(ent, ref ent.Comp)) return; DebugTools.Assert(lifetime >= TimeSpan.Zero, "Lifetime must be positive"); ent.Comp.Lifetime = lifetime; ent.Comp.DespawnTime = _timing.CurTime + ent.Comp.Lifetime; _appearance.SetData(ent, ESTimedDespawnVisuals.DespawnTime, ent.Comp.DespawnTime); Dirty(ent); } /// /// Gets the amount of time this entity will be alive before despawning /// [PublicAPI] public TimeSpan GetLifetime(Entity ent) { if (!Resolve(ent, ref ent.Comp)) return TimeSpan.Zero; return ent.Comp.Lifetime; } /// /// Sets the lifetime of the entity, adjusting the despawn time to compensate /// [PublicAPI] public void SetDespawnTime(Entity ent, TimeSpan despawnTime) { SetLifetime(ent, despawnTime - _timing.CurTime); } /// /// Gets the time at which the entity will despawn /// [PublicAPI] public TimeSpan GetDespawnTime(Entity ent) { if (!Resolve(ent, ref ent.Comp)) return TimeSpan.Zero; return ent.Comp.DespawnTime; } /// /// Returns how far along through the timedDespawn the entity is (as a percentage [0, 1]) /// [PublicAPI] public double GetProgress(Entity ent) { if (!Resolve(ent, ref ent.Comp)) return 0; return Math.Clamp((_timing.CurTime - ent.Comp.SpawnTime) / ent.Comp.Lifetime, 0, 1); } public override void Update(float frameTime) { base.Update(frameTime); _toDelete.Clear(); var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var comp)) { if (_timing.CurTime < comp.DespawnTime) continue; _toDelete.Add(uid); } foreach (var toDelete in _toDelete) { // Same event as engine TimedDespawn var ev = new TimedDespawnEvent(); RaiseLocalEvent(toDelete, ref ev); PredictedQueueDel(toDelete); } } }