using Robust.Server.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Timing;
namespace Content.Server._NF.DangerTether;
///
/// A system to handle tethering dangerous objects, and deleting them when out of range of any tether.
/// Runs periodic checks to handle deletion.
///
public sealed class DangerTetherSystem : EntitySystem
{
[Dependency] private IGameTiming _timing = default!;
[Dependency] private TransformSystem _transform = default!;
private readonly TimeSpan _scanPeriod = TimeSpan.FromSeconds(0.5);
private TimeSpan _nextScan = TimeSpan.Zero;
private List<(MapCoordinates Position, float Distance)> _tethers = new();
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent(OnTetheredMapInit);
}
///
/// Update: periodically, check that all DangerTethered entities are in range of a tether.
/// If they aren't, delete them.
///
public override void Update(float frameTime)
{
base.Update(frameTime);
if (_timing.CurTime < _nextScan)
return;
_nextScan += _scanPeriod;
PopulateTetherList();
var tetheredQuery = EntityQueryEnumerator();
while (tetheredQuery.MoveNext(out var targetUid, out _))
{
if (!AnyTetherInRange(targetUid))
QueueDel(targetUid);
}
}
///
/// DangerTethered MapInit: must be in range of a tether, otherwise delete it.
///
private void OnTetheredMapInit(Entity ent, ref MapInitEvent args)
{
PopulateTetherList();
if (!AnyTetherInRange(ent))
QueueDel(ent);
}
private void PopulateTetherList()
{
_tethers.Clear();
var tetherQuery = EntityQueryEnumerator();
while (tetherQuery.MoveNext(out var tetherUid, out var tether))
{
_tethers.Add((_transform.GetMapCoordinates(tetherUid), tether.MaxDistance));
}
}
public bool AnyTetherInRange(EntityUid ent)
{
var targetCoords = _transform.GetMapCoordinates(ent);
foreach (var tetherEntry in _tethers)
{
if (tetherEntry.Position.MapId != targetCoords.MapId)
continue;
if (tetherEntry.Position.InRange(targetCoords, tetherEntry.Distance))
return true;
}
return false;
}
}