Move some Station methods into shared (#38976)

This commit is contained in:
Nemanja
2025-08-08 11:22:34 -04:00
committed by GitHub
parent 3d9e1f64a9
commit 1374ceea47
41 changed files with 298 additions and 351 deletions

View File

@@ -1,11 +1,14 @@
using System.Linq;
using Content.Shared.Station.Components;
using JetBrains.Annotations;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
namespace Content.Shared.Station;
public abstract partial class SharedStationSystem : EntitySystem
{
[Dependency] private readonly SharedMapSystem _map = default!;
[Dependency] private readonly MetaDataSystem _meta = default!;
private EntityQuery<TransformComponent> _xformQuery;
@@ -16,96 +19,164 @@ public abstract partial class SharedStationSystem : EntitySystem
{
base.Initialize();
InitializeTracker();
_xformQuery = GetEntityQuery<TransformComponent>();
_stationMemberQuery = GetEntityQuery<StationMemberComponent>();
SubscribeLocalEvent<StationTrackerComponent, MapInitEvent>(OnTrackerMapInit);
SubscribeLocalEvent<StationTrackerComponent, ComponentRemove>(OnTrackerRemove);
SubscribeLocalEvent<StationTrackerComponent, GridUidChangedEvent>(OnTrackerGridChanged);
SubscribeLocalEvent<StationTrackerComponent, MetaFlagRemoveAttemptEvent>(OnMetaFlagRemoveAttempt);
}
private void OnTrackerMapInit(Entity<StationTrackerComponent> ent, ref MapInitEvent args)
{
_meta.AddFlag(ent, MetaDataFlags.ExtraTransformEvents);
UpdateStationTracker(ent.AsNullable());
}
private void OnTrackerRemove(Entity<StationTrackerComponent> ent, ref ComponentRemove args)
{
_meta.RemoveFlag(ent, MetaDataFlags.ExtraTransformEvents);
}
private void OnTrackerGridChanged(Entity<StationTrackerComponent> ent, ref GridUidChangedEvent args)
{
UpdateStationTracker((ent, ent.Comp, args.Transform));
}
private void OnMetaFlagRemoveAttempt(Entity<StationTrackerComponent> ent, ref MetaFlagRemoveAttemptEvent args)
{
if ((args.ToRemove & MetaDataFlags.ExtraTransformEvents) != 0 &&
ent.Comp.LifeStage <= ComponentLifeStage.Running)
{
args.ToRemove &= ~MetaDataFlags.ExtraTransformEvents;
}
}
/// <summary>
/// Updates the station tracker component based on entity's current location.
/// Gets the largest member grid from a station.
/// </summary>
[PublicAPI]
public void UpdateStationTracker(Entity<StationTrackerComponent?, TransformComponent?> ent)
{
if (!Resolve(ent, ref ent.Comp1))
return;
var xform = ent.Comp2;
if (!_xformQuery.Resolve(ent, ref xform))
return;
// Entity is in nullspace or not on a grid
if (xform.MapID == MapId.Nullspace || xform.GridUid == null)
{
SetStation(ent, null);
return;
}
// Check if the grid is part of a station
if (!_stationMemberQuery.TryGetComponent(xform.GridUid.Value, out var stationMember))
{
SetStation(ent, null);
return;
}
SetStation(ent, stationMember.Station);
}
/// <summary>
/// Sets the station for a StationTrackerComponent.
/// </summary>
[PublicAPI]
public void SetStation(Entity<StationTrackerComponent?> ent, EntityUid? station)
public EntityUid? GetLargestGrid(Entity<StationDataComponent?> ent)
{
if (!Resolve(ent, ref ent.Comp))
return;
return null;
if (ent.Comp.Station == station)
return;
EntityUid? largestGrid = null;
Box2 largestBounds = new Box2();
ent.Comp.Station = station;
Dirty(ent);
foreach (var gridUid in ent.Comp.Grids)
{
if (!TryComp<MapGridComponent>(gridUid, out var grid) ||
grid.LocalAABB.Size.LengthSquared() < largestBounds.Size.LengthSquared())
continue;
largestBounds = grid.LocalAABB;
largestGrid = gridUid;
}
return largestGrid;
}
/// <summary>
/// Gets the station an entity is currently on, if any.
/// Returns the total number of tiles contained in the station's grids.
/// </summary>
[PublicAPI]
public EntityUid? GetCurrentStation(Entity<StationTrackerComponent?> ent)
public int GetTileCount(Entity<StationDataComponent?> ent)
{
if (!Resolve(ent, ref ent.Comp, logMissing: false))
if (!Resolve(ent, ref ent.Comp))
return 0;
var count = 0;
foreach (var gridUid in ent.Comp.Grids)
{
if (!TryComp<MapGridComponent>(gridUid, out var grid))
continue;
count += _map.GetAllTiles(gridUid, grid).Count();
}
return count;
}
[PublicAPI]
public EntityUid? GetOwningStation(EntityUid? entity, TransformComponent? xform = null)
{
if (entity == null)
return null;
return ent.Comp.Station;
return GetOwningStation(entity.Value, xform);
}
/// <summary>
/// Gets the station that "owns" the given entity (essentially, the station the grid it's on is attached to)
/// </summary>
/// <param name="entity">Entity to find the owner of.</param>
/// <param name="xform">Resolve pattern, transform of the entity.</param>
/// <returns>The owning station, if any.</returns>
/// <remarks>
/// This does not remember what station an entity started on, it simply checks where it is currently located.
/// </remarks>
public EntityUid? GetOwningStation(EntityUid entity, TransformComponent? xform = null)
{
if (!Resolve(entity, ref xform))
throw new ArgumentException("Tried to use an abstract entity!", nameof(entity));
if (TryComp<StationTrackerComponent>(entity, out var stationTracker))
{
// We have a specific station we are tracking and are tethered to.
return stationTracker.Station;
}
if (HasComp<StationDataComponent>(entity))
{
// We are the station, just return ourselves.
return entity;
}
if (HasComp<MapGridComponent>(entity))
{
// We are the station, just check ourselves.
return CompOrNull<StationMemberComponent>(entity)?.Station;
}
if (xform.GridUid == EntityUid.Invalid)
{
Log.Debug("Unable to get owning station - GridUid invalid.");
return null;
}
return CompOrNull<StationMemberComponent>(xform.GridUid)?.Station;
}
public List<EntityUid> GetStations()
{
var stations = new List<EntityUid>();
var query = EntityQueryEnumerator<StationDataComponent>();
while (query.MoveNext(out var uid, out _))
{
stations.Add(uid);
}
return stations;
}
public HashSet<EntityUid> GetStationsSet()
{
var stations = new HashSet<EntityUid>();
var query = EntityQueryEnumerator<StationDataComponent>();
while (query.MoveNext(out var uid, out _))
{
stations.Add(uid);
}
return stations;
}
public List<(string Name, NetEntity Entity)> GetStationNames()
{
var stations = GetStationsSet();
var stats = new List<(string Name, NetEntity Station)>();
foreach (var weh in stations)
{
stats.Add((MetaData(weh).EntityName, GetNetEntity(weh)));
}
return stats;
}
/// <summary>
/// Returns the first station that has a grid in a certain map.
/// If the map has no stations, null is returned instead.
/// </summary>
/// <remarks>
/// If there are multiple stations on a map it is probably arbitrary which one is returned.
/// </remarks>
public EntityUid? GetStationInMap(MapId map)
{
var query = EntityQueryEnumerator<StationDataComponent>();
while (query.MoveNext(out var uid, out var data))
{
foreach (var gridUid in data.Grids)
{
if (Transform(gridUid).MapID == map)
{
return uid;
}
}
}
return null;
}
}