using System.Diagnostics.CodeAnalysis; using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Rules.Components; using Content.Server.Station.Components; using Robust.Shared.Collections; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Random; namespace Content.Server.GameTicking.Rules; public abstract partial class GameRuleSystem where T: IComponent { protected EntityQueryEnumerator QueryActiveRules() { return EntityQueryEnumerator(); } /// /// Utility function for finding a random event-eligible station entity /// protected bool TryGetRandomStation([NotNullWhen(true)] out EntityUid? station, Func? filter = null) { var stations = new ValueList(Count()); filter ??= _ => true; var query = AllEntityQuery(); while (query.MoveNext(out var uid, out _)) { if (!filter(uid)) continue; stations.Add(uid); } if (stations.Count == 0) { station = null; return false; } // TODO: Engine PR. station = stations[RobustRandom.Next(stations.Count)]; return true; } protected bool TryFindRandomTile(out Vector2i tile, [NotNullWhen(true)] out EntityUid? targetStation, out EntityUid targetGrid, out EntityCoordinates targetCoords) { tile = default; targetStation = EntityUid.Invalid; targetGrid = EntityUid.Invalid; targetCoords = EntityCoordinates.Invalid; if (TryGetRandomStation(out targetStation)) { return TryFindRandomTileOnStation((targetStation.Value, Comp(targetStation.Value)), out tile, out targetGrid, out targetCoords); } return false; } protected bool TryFindRandomTileOnStation(Entity station, out Vector2i tile, out EntityUid targetGrid, out EntityCoordinates targetCoords) { tile = default; targetCoords = EntityCoordinates.Invalid; targetGrid = EntityUid.Invalid; var possibleTargets = station.Comp.Grids; if (possibleTargets.Count == 0) { targetGrid = EntityUid.Invalid; return false; } targetGrid = RobustRandom.Pick(possibleTargets); if (!TryComp(targetGrid, out var gridComp)) return false; var found = false; var aabb = gridComp.LocalAABB; for (var i = 0; i < 10; i++) { var randomX = RobustRandom.Next((int) aabb.Left, (int) aabb.Right); var randomY = RobustRandom.Next((int) aabb.Bottom, (int) aabb.Top); tile = new Vector2i(randomX, randomY); if (_atmosphere.IsTileSpace(targetGrid, Transform(targetGrid).MapUid, tile) || _atmosphere.IsTileAirBlocked(targetGrid, tile, mapGridComp: gridComp)) { continue; } found = true; targetCoords = _map.GridTileToLocal(targetGrid, gridComp, tile); break; } return found; } }