add StationTrackerComponent (#36803)
* maybe I am cooking * logmissing * copy paste oops * add some stuff * review * fix * rerun tests --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
This commit is contained in:
@@ -5,7 +5,7 @@ namespace Content.Client.Station;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// This handles letting the client know stations are a thing. Only really used by an admin menu.
|
/// This handles letting the client know stations are a thing. Only really used by an admin menu.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class StationSystem : EntitySystem
|
public sealed partial class StationSystem : SharedStationSystem
|
||||||
{
|
{
|
||||||
private readonly List<(string Name, NetEntity Entity)> _stations = new();
|
private readonly List<(string Name, NetEntity Entity)> _stations = new();
|
||||||
|
|
||||||
@@ -15,11 +15,14 @@ public sealed class StationSystem : EntitySystem
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// I'd have this just invoke an entity query, but we're on the client and the client barely knows about stations.
|
/// I'd have this just invoke an entity query, but we're on the client and the client barely knows about stations.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
// TODO: Stations have a global PVS override now, this can probably be changed into a query.
|
||||||
public IReadOnlyList<(string Name, NetEntity Entity)> Stations => _stations;
|
public IReadOnlyList<(string Name, NetEntity Entity)> Stations => _stations;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeNetworkEvent<StationsUpdatedEvent>(StationsUpdated);
|
SubscribeNetworkEvent<StationsUpdatedEvent>(StationsUpdated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Content.Server.Station.Systems;
|
|||||||
/// For jobs, look at StationJobSystem. For spawning, look at StationSpawningSystem.
|
/// For jobs, look at StationJobSystem. For spawning, look at StationSpawningSystem.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public sealed class StationSystem : EntitySystem
|
public sealed partial class StationSystem : SharedStationSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly ILogManager _logManager = default!;
|
[Dependency] private readonly ILogManager _logManager = default!;
|
||||||
[Dependency] private readonly IPlayerManager _player = default!;
|
[Dependency] private readonly IPlayerManager _player = default!;
|
||||||
@@ -48,6 +48,8 @@ public sealed class StationSystem : EntitySystem
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
_sawmill = _logManager.GetSawmill("station");
|
_sawmill = _logManager.GetSawmill("station");
|
||||||
|
|
||||||
_gridQuery = GetEntityQuery<MapGridComponent>();
|
_gridQuery = GetEntityQuery<MapGridComponent>();
|
||||||
@@ -60,6 +62,9 @@ public sealed class StationSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<StationMemberComponent, ComponentShutdown>(OnStationGridDeleted);
|
SubscribeLocalEvent<StationMemberComponent, ComponentShutdown>(OnStationGridDeleted);
|
||||||
SubscribeLocalEvent<StationMemberComponent, PostGridSplitEvent>(OnStationSplitEvent);
|
SubscribeLocalEvent<StationMemberComponent, PostGridSplitEvent>(OnStationSplitEvent);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<StationGridAddedEvent>(OnStationGridAdded);
|
||||||
|
SubscribeLocalEvent<StationGridRemovedEvent>(OnStationGridRemoved);
|
||||||
|
|
||||||
_player.PlayerStatusChanged += OnPlayerStatusChanged;
|
_player.PlayerStatusChanged += OnPlayerStatusChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,6 +95,18 @@ public sealed class StationSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateTrackersOnGrid(EntityUid gridId, EntityUid? station)
|
||||||
|
{
|
||||||
|
var query = EntityQueryEnumerator<StationTrackerComponent, TransformComponent>();
|
||||||
|
while (query.MoveNext(out var uid, out var tracker, out var xform))
|
||||||
|
{
|
||||||
|
if (xform.GridUid == gridId)
|
||||||
|
{
|
||||||
|
SetStation((uid, tracker), station);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region Event handlers
|
#region Event handlers
|
||||||
|
|
||||||
private void OnStationAdd(EntityUid uid, StationDataComponent component, ComponentStartup args)
|
private void OnStationAdd(EntityUid uid, StationDataComponent component, ComponentStartup args)
|
||||||
@@ -107,6 +124,9 @@ public sealed class StationSystem : EntitySystem
|
|||||||
foreach (var grid in component.Grids)
|
foreach (var grid in component.Grids)
|
||||||
{
|
{
|
||||||
RemComp<StationMemberComponent>(grid);
|
RemComp<StationMemberComponent>(grid);
|
||||||
|
|
||||||
|
// If the station gets deleted, we raise the event for every grid that was a part of it
|
||||||
|
RaiseLocalEvent(new StationGridRemovedEvent(grid, uid));
|
||||||
}
|
}
|
||||||
|
|
||||||
RaiseNetworkEvent(new StationsUpdatedEvent(GetStationNames()), Filter.Broadcast());
|
RaiseNetworkEvent(new StationsUpdatedEvent(GetStationNames()), Filter.Broadcast());
|
||||||
@@ -159,6 +179,18 @@ public sealed class StationSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnStationGridAdded(StationGridAddedEvent ev)
|
||||||
|
{
|
||||||
|
// When a grid is added to a station, update all trackers on that grid
|
||||||
|
UpdateTrackersOnGrid(ev.GridId, ev.Station);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStationGridRemoved(StationGridRemovedEvent ev)
|
||||||
|
{
|
||||||
|
// When a grid is removed from a station, update all trackers on that grid to null
|
||||||
|
UpdateTrackersOnGrid(ev.GridId, null);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Event handlers
|
#endregion Event handlers
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -353,7 +385,7 @@ public sealed class StationSystem : EntitySystem
|
|||||||
stationMember.Station = station;
|
stationMember.Station = station;
|
||||||
stationData.Grids.Add(mapGrid);
|
stationData.Grids.Add(mapGrid);
|
||||||
|
|
||||||
RaiseLocalEvent(station, new StationGridAddedEvent(mapGrid, false), true);
|
RaiseLocalEvent(station, new StationGridAddedEvent(mapGrid, station, false), true);
|
||||||
|
|
||||||
_sawmill.Info($"Adding grid {mapGrid} to station {Name(station)} ({station})");
|
_sawmill.Info($"Adding grid {mapGrid} to station {Name(station)} ({station})");
|
||||||
}
|
}
|
||||||
@@ -376,7 +408,7 @@ public sealed class StationSystem : EntitySystem
|
|||||||
RemComp<StationMemberComponent>(mapGrid);
|
RemComp<StationMemberComponent>(mapGrid);
|
||||||
stationData.Grids.Remove(mapGrid);
|
stationData.Grids.Remove(mapGrid);
|
||||||
|
|
||||||
RaiseLocalEvent(station, new StationGridRemovedEvent(mapGrid), true);
|
RaiseLocalEvent(station, new StationGridRemovedEvent(mapGrid, station), true);
|
||||||
_sawmill.Info($"Removing grid {mapGrid} from station {Name(station)} ({station})");
|
_sawmill.Info($"Removing grid {mapGrid} from station {Name(station)} ({station})");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,15 +585,21 @@ public sealed class StationGridAddedEvent : EntityEventArgs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public EntityUid GridId;
|
public EntityUid GridId;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// EntityUid of the station this grid was added to.
|
||||||
|
/// </summary>
|
||||||
|
public EntityUid Station;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates that the event was fired during station setup,
|
/// Indicates that the event was fired during station setup,
|
||||||
/// so that it can be ignored if StationInitializedEvent was already handled.
|
/// so that it can be ignored if StationInitializedEvent was already handled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsSetup;
|
public bool IsSetup;
|
||||||
|
|
||||||
public StationGridAddedEvent(EntityUid gridId, bool isSetup)
|
public StationGridAddedEvent(EntityUid gridId, EntityUid station, bool isSetup)
|
||||||
{
|
{
|
||||||
GridId = gridId;
|
GridId = gridId;
|
||||||
|
Station = station;
|
||||||
IsSetup = isSetup;
|
IsSetup = isSetup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -577,9 +615,15 @@ public sealed class StationGridRemovedEvent : EntityEventArgs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public EntityUid GridId;
|
public EntityUid GridId;
|
||||||
|
|
||||||
public StationGridRemovedEvent(EntityUid gridId)
|
/// <summary>
|
||||||
|
/// EntityUid of the station this grid was added to.
|
||||||
|
/// </summary>
|
||||||
|
public EntityUid Station;
|
||||||
|
|
||||||
|
public StationGridRemovedEvent(EntityUid gridId, EntityUid station)
|
||||||
{
|
{
|
||||||
GridId = gridId;
|
GridId = gridId;
|
||||||
|
Station = station;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
18
Content.Shared/Station/Components/StationTrackerComponent.cs
Normal file
18
Content.Shared/Station/Components/StationTrackerComponent.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Station.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Component that tracks which station an entity is currently on.
|
||||||
|
/// Mainly used for UI purposes on the client to easily get station-specific data like alert levels.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedStationSystem))]
|
||||||
|
public sealed partial class StationTrackerComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The station this entity is currently on, if any.
|
||||||
|
/// Null when in space or not on any grid.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public EntityUid? Station;
|
||||||
|
}
|
||||||
111
Content.Shared/Station/SharedStationSystem.cs
Normal file
111
Content.Shared/Station/SharedStationSystem.cs
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
using Content.Shared.Station.Components;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
|
||||||
|
namespace Content.Shared.Station;
|
||||||
|
|
||||||
|
public abstract partial class SharedStationSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly MetaDataSystem _meta = default!;
|
||||||
|
|
||||||
|
private EntityQuery<TransformComponent> _xformQuery;
|
||||||
|
private EntityQuery<StationMemberComponent> _stationMemberQuery;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
_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.
|
||||||
|
/// </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)
|
||||||
|
{
|
||||||
|
if (!Resolve(ent, ref ent.Comp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ent.Comp.Station == station)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ent.Comp.Station = station;
|
||||||
|
Dirty(ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the station an entity is currently on, if any.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public EntityUid? GetCurrentStation(Entity<StationTrackerComponent?> ent)
|
||||||
|
{
|
||||||
|
if (!Resolve(ent, ref ent.Comp, logMissing: false))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return ent.Comp.Station;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user