2022-05-10 13:43:30 -05:00
using System.Linq ;
2022-06-23 20:11:03 +10:00
using Content.Server.Chat.Systems ;
2022-05-10 13:43:30 -05:00
using Content.Server.GameTicking ;
using Content.Server.Station.Components ;
using Content.Shared.CCVar ;
2022-07-21 17:30:00 -05:00
using Content.Shared.Station ;
2022-05-10 13:43:30 -05:00
using JetBrains.Annotations ;
2022-07-04 16:00:51 +10:00
using Robust.Server.Player ;
using Robust.Shared.Collections ;
2022-05-10 13:43:30 -05:00
using Robust.Shared.Configuration ;
2022-07-21 17:30:00 -05:00
using Robust.Shared.Enums ;
2022-05-10 13:43:30 -05:00
using Robust.Shared.Map ;
2022-11-22 13:12:04 +11:00
using Robust.Shared.Map.Components ;
2022-07-04 16:00:51 +10:00
using Robust.Shared.Player ;
2022-05-10 13:43:30 -05:00
using Robust.Shared.Random ;
namespace Content.Server.Station.Systems ;
/// <summary>
/// System that manages stations.
/// A station is, by default, just a name, optional map prototype, and optional grids.
/// For jobs, look at StationJobSystem. For spawning, look at StationSpawningSystem.
/// </summary>
[PublicAPI]
public sealed class StationSystem : EntitySystem
{
[Dependency] private readonly IConfigurationManager _configurationManager = default ! ;
[Dependency] private readonly ILogManager _logManager = default ! ;
[Dependency] private readonly IMapManager _mapManager = default ! ;
2022-07-04 16:00:51 +10:00
[Dependency] private readonly IPlayerManager _player = default ! ;
2022-05-10 13:43:30 -05:00
[Dependency] private readonly IRobustRandom _random = default ! ;
2022-06-03 21:37:35 +10:00
[Dependency] private readonly ChatSystem _chatSystem = default ! ;
2022-05-10 13:43:30 -05:00
[Dependency] private readonly GameTicker _gameTicker = default ! ;
2022-07-04 16:00:51 +10:00
[Dependency] private readonly SharedTransformSystem _transform = default ! ;
2022-05-10 13:43:30 -05:00
private ISawmill _sawmill = default ! ;
private readonly HashSet < EntityUid > _stations = new ( ) ;
/// <summary>
/// All stations that currently exist.
/// </summary>
/// <remarks>
/// I'd have this just invoke an entity query, but I want this to be a hashset for convenience and it allocating on use would be lame.
/// </remarks>
public IReadOnlySet < EntityUid > Stations = > _stations ;
private bool _randomStationOffset ;
private bool _randomStationRotation ;
private float _maxRandomStationOffset ;
/// <inheritdoc/>
public override void Initialize ( )
{
_sawmill = _logManager . GetSawmill ( "station" ) ;
SubscribeLocalEvent < GameRunLevelChangedEvent > ( OnRoundEnd ) ;
SubscribeLocalEvent < PreGameMapLoad > ( OnPreGameMapLoad ) ;
SubscribeLocalEvent < PostGameMapLoad > ( OnPostGameMapLoad ) ;
2022-08-07 15:53:07 +12:00
SubscribeLocalEvent < StationDataComponent , ComponentAdd > ( OnStationAdd ) ;
2022-05-10 13:43:30 -05:00
SubscribeLocalEvent < StationDataComponent , ComponentShutdown > ( OnStationDeleted ) ;
2022-08-07 15:53:07 +12:00
SubscribeLocalEvent < StationDataComponent , EntParentChangedMessage > ( OnParentChanged ) ;
2022-08-23 02:32:02 -05:00
SubscribeLocalEvent < StationMemberComponent , ComponentShutdown > ( OnStationGridDeleted ) ;
SubscribeLocalEvent < StationMemberComponent , PostGridSplitEvent > ( OnStationSplitEvent ) ;
2022-05-10 13:43:30 -05:00
_configurationManager . OnValueChanged ( CCVars . StationOffset , x = > _randomStationOffset = x , true ) ;
_configurationManager . OnValueChanged ( CCVars . MaxStationOffset , x = > _maxRandomStationOffset = x , true ) ;
_configurationManager . OnValueChanged ( CCVars . StationRotation , x = > _randomStationRotation = x , true ) ;
2022-07-21 17:30:00 -05:00
_player . PlayerStatusChanged + = OnPlayerStatusChanged ;
}
2022-08-23 02:32:02 -05:00
private void OnStationSplitEvent ( EntityUid uid , StationMemberComponent component , ref PostGridSplitEvent args )
{
AddGridToStation ( component . Station , args . Grid ) ; // Add the new grid as a member.
}
private void OnStationGridDeleted ( EntityUid uid , StationMemberComponent component , ComponentShutdown args )
{
if ( ! TryComp < StationDataComponent > ( component . Station , out var stationData ) )
return ;
stationData . Grids . Remove ( uid ) ;
}
2022-07-21 17:30:00 -05:00
public override void Shutdown ( )
{
base . Shutdown ( ) ;
_player . PlayerStatusChanged - = OnPlayerStatusChanged ;
}
2022-08-15 07:54:11 +12:00
/// <summary>
/// Called when the server shuts down or restarts to avoid uneccesarily logging mid-round station deletion errors.
/// </summary>
public void OnServerDispose ( )
{
_stations . Clear ( ) ;
}
2022-07-21 17:30:00 -05:00
private void OnPlayerStatusChanged ( object? sender , SessionStatusEventArgs e )
{
if ( e . NewStatus = = SessionStatus . Connected )
{
2022-11-22 13:49:48 +13:00
RaiseNetworkEvent ( new StationsUpdatedEvent ( _stations ) , e . Session ) ;
2022-07-21 17:30:00 -05:00
}
2022-05-10 13:43:30 -05:00
}
#region Event handlers
2022-08-07 15:53:07 +12:00
private void OnStationAdd ( EntityUid uid , StationDataComponent component , ComponentAdd args )
2022-05-10 13:43:30 -05:00
{
_stations . Add ( uid ) ;
2022-07-21 17:30:00 -05:00
RaiseNetworkEvent ( new StationsUpdatedEvent ( _stations ) , Filter . Broadcast ( ) ) ;
2022-05-10 13:43:30 -05:00
}
private void OnStationDeleted ( EntityUid uid , StationDataComponent component , ComponentShutdown args )
{
2022-08-08 09:22:46 +10:00
if ( _stations . Contains ( uid ) & & // Was not deleted via DeleteStation()
2022-08-28 15:13:59 -07:00
_gameTicker . RunLevel = = GameRunLevel . InRound & & // And not due to a round restart
_gameTicker . LobbyEnabled ) // If there isn't a lobby, this is probably sandbox, single player, or a test
2022-08-07 15:53:07 +12:00
{
2022-08-15 07:54:11 +12:00
// printing a stack trace, rather than throwing an exception so that entity deletion continues as normal.
Logger . Error ( $"Station entity {ToPrettyString(uid)} is getting deleted mid-round. Trace: {Environment.StackTrace}" ) ;
2022-08-07 15:53:07 +12:00
}
2022-07-21 17:30:00 -05:00
2022-08-23 02:32:02 -05:00
foreach ( var grid in component . Grids )
{
RemComp < StationMemberComponent > ( grid ) ;
}
2022-08-07 15:53:07 +12:00
_stations . Remove ( uid ) ;
2022-07-21 17:30:00 -05:00
RaiseNetworkEvent ( new StationsUpdatedEvent ( _stations ) , Filter . Broadcast ( ) ) ;
2022-05-10 13:43:30 -05:00
}
2022-08-07 15:53:07 +12:00
/// <summary>
/// If a station data entity is getting re-parented mid-round, this will log an error.
/// </summary>
/// <remarks>
/// This doesn't really achieve anything, it just for debugging any future station data bugs.
/// </remarks>
private void OnParentChanged ( EntityUid uid , StationDataComponent component , ref EntParentChangedMessage args )
{
if ( _gameTicker . RunLevel ! = GameRunLevel . InRound | |
MetaData ( uid ) . EntityLifeStage > = EntityLifeStage . MapInitialized | |
component . LifeStage < = ComponentLifeStage . Initializing )
{
return ;
}
// Yeah this doesn't actually stop the parent change..... it just ineffectually yells about it.
// STOP RIGHT THERE CRIMINAL SCUM
_sawmill . Error ( $"Station entity {ToPrettyString(uid)} is getting reparented from {ToPrettyString(args.OldParent ?? EntityUid.Invalid)} to {ToPrettyString(args.Transform.ParentUid)}" ) ;
}
2022-05-10 13:43:30 -05:00
private void OnPreGameMapLoad ( PreGameMapLoad ev )
{
// this is only for maps loaded during round setup!
if ( _gameTicker . RunLevel = = GameRunLevel . InRound )
return ;
if ( _randomStationOffset )
ev . Options . Offset + = _random . NextVector2 ( _maxRandomStationOffset ) ;
if ( _randomStationRotation )
ev . Options . Rotation = _random . NextAngle ( ) ;
}
private void OnPostGameMapLoad ( PostGameMapLoad ev )
{
2022-06-11 18:54:41 -07:00
var dict = new Dictionary < string , List < EntityUid > > ( ) ;
2022-05-10 13:43:30 -05:00
2022-06-11 18:54:41 -07:00
void AddGrid ( string station , EntityUid grid )
2022-05-10 13:43:30 -05:00
{
if ( dict . ContainsKey ( station ) )
{
dict [ station ] . Add ( grid ) ;
}
else
{
2022-06-11 18:54:41 -07:00
dict [ station ] = new List < EntityUid > { grid } ;
2022-05-10 13:43:30 -05:00
}
}
// Iterate over all BecomesStation
foreach ( var grid in ev . Grids )
{
// We still setup the grid
2022-06-11 18:54:41 -07:00
if ( ! TryComp < BecomesStationComponent > ( grid , out var becomesStation ) )
2022-05-10 13:43:30 -05:00
continue ;
AddGrid ( becomesStation . Id , grid ) ;
}
if ( ! dict . Any ( ) )
{
// Oh jeez, no stations got loaded.
2022-08-23 02:32:02 -05:00
// We'll yell about it, but the thing this used to do with creating a dummy is kinda pointless now.
_sawmill . Error ( $"There were no station grids for {ev.GameMap.ID}!" ) ;
2022-05-10 13:43:30 -05:00
}
// Iterate over all PartOfStation
2022-08-23 02:32:02 -05:00
// TODO: Remove this whenever pillar finally gets replaced. It's the sole user.
2022-05-10 13:43:30 -05:00
foreach ( var grid in ev . Grids )
{
2022-06-11 18:54:41 -07:00
if ( ! TryComp < PartOfStationComponent > ( grid , out var partOfStation ) )
2022-05-10 13:43:30 -05:00
continue ;
AddGrid ( partOfStation . Id , grid ) ;
}
foreach ( var ( id , gridIds ) in dict )
{
StationConfig ? stationConfig = null ;
if ( ev . GameMap . Stations . ContainsKey ( id ) )
stationConfig = ev . GameMap . Stations [ id ] ;
else
_sawmill . Error ( $"The station {id} in map {ev.GameMap.ID} does not have an associated station config!" ) ;
2022-06-11 18:54:41 -07:00
InitializeNewStation ( stationConfig , gridIds , ev . StationName ) ;
2022-05-10 13:43:30 -05:00
}
}
private void OnRoundEnd ( GameRunLevelChangedEvent eventArgs )
{
2022-08-23 02:32:02 -05:00
if ( eventArgs . New ! = GameRunLevel . PreRoundLobby )
return ;
2022-05-10 13:43:30 -05:00
foreach ( var entity in _stations )
{
2022-08-23 02:32:02 -05:00
DeleteStation ( entity ) ;
2022-05-10 13:43:30 -05:00
}
}
#endregion Event handlers
2022-08-08 09:22:46 +10:00
/// <summary>
/// Gets the largest member grid from a station.
/// </summary>
public EntityUid ? GetLargestGrid ( StationDataComponent component )
{
EntityUid ? largestGrid = null ;
Box2 largestBounds = new Box2 ( ) ;
foreach ( var gridUid in component . Grids )
{
2022-11-04 10:12:25 +11:00
if ( ! TryComp < MapGridComponent > ( gridUid , out var grid ) | |
2022-11-22 13:12:04 +11:00
grid . LocalAABB . Size . LengthSquared < largestBounds . Size . LengthSquared )
2022-08-08 09:22:46 +10:00
continue ;
2022-11-22 13:12:04 +11:00
largestBounds = grid . LocalAABB ;
2022-08-08 09:22:46 +10:00
largestGrid = gridUid ;
}
return largestGrid ;
}
2022-08-23 02:32:02 -05:00
/// <summary>
/// Tries to retrieve a filter for everything in the station the source is on.
/// </summary>
/// <param name="source">The entity to use to find the station.</param>
/// <param name="range">The range around the station</param>
/// <returns></returns>
public Filter GetInOwningStation ( EntityUid source , float range = 32f )
2022-07-04 01:29:38 -05:00
{
var station = GetOwningStation ( source ) ;
if ( TryComp < StationDataComponent > ( station , out var data ) )
{
return GetInStation ( data ) ;
}
return Filter . Empty ( ) ;
}
2022-07-04 16:00:51 +10:00
/// <summary>
/// Retrieves a filter for everything in a particular station or near its member grids.
/// </summary>
public Filter GetInStation ( StationDataComponent dataComponent , float range = 32f )
{
// Could also use circles if you wanted.
var bounds = new ValueList < Box2 > ( dataComponent . Grids . Count ) ;
var filter = Filter . Empty ( ) ;
var mapIds = new ValueList < MapId > ( ) ;
var xformQuery = GetEntityQuery < TransformComponent > ( ) ;
foreach ( var gridUid in dataComponent . Grids )
{
if ( ! _mapManager . TryGetGrid ( gridUid , out var grid ) | |
2022-08-23 02:32:02 -05:00
! xformQuery . TryGetComponent ( gridUid , out var xform ) )
continue ;
2022-07-04 16:00:51 +10:00
var mapId = xform . MapID ;
var position = _transform . GetWorldPosition ( xform , xformQuery ) ;
var bound = grid . LocalAABB . Enlarged ( range ) . Translated ( position ) ;
bounds . Add ( bound ) ;
if ( ! mapIds . Contains ( mapId ) )
{
2022-11-01 11:27:18 +11:00
mapIds . Add ( xform . MapID ) ;
2022-07-04 16:00:51 +10:00
}
}
foreach ( var session in Filter . GetAllPlayers ( _player ) )
{
var entity = session . AttachedEntity ;
2022-08-23 02:32:02 -05:00
if ( entity = = null | | ! xformQuery . TryGetComponent ( entity , out var xform ) )
continue ;
2022-07-04 16:00:51 +10:00
var mapId = xform . MapID ;
2022-08-23 02:32:02 -05:00
if ( ! mapIds . Contains ( mapId ) )
continue ;
2022-07-04 16:00:51 +10:00
var position = _transform . GetWorldPosition ( xform , xformQuery ) ;
foreach ( var bound in bounds )
{
2022-08-23 02:32:02 -05:00
if ( ! bound . Contains ( position ) )
continue ;
2022-07-04 16:00:51 +10:00
filter . AddPlayer ( session ) ;
break ;
}
}
return filter ;
}
2022-05-10 13:43:30 -05:00
/// <summary>
/// Generates a station name from the given config.
/// </summary>
public static string GenerateStationName ( StationConfig config )
{
return config . NameGenerator is not null
? config . NameGenerator . FormatName ( config . StationNameTemplate )
: config . StationNameTemplate ;
}
/// <summary>
/// Initializes a new station with the given information.
/// </summary>
/// <param name="stationConfig">The game map prototype used, if any.</param>
/// <param name="gridIds">All grids that should be added to the station.</param>
/// <param name="name">Optional override for the station name.</param>
/// <returns>The initialized station.</returns>
public EntityUid InitializeNewStation ( StationConfig ? stationConfig , IEnumerable < EntityUid > ? gridIds , string? name = null )
{
var station = Spawn ( null , new MapCoordinates ( 0 , 0 , _gameTicker . DefaultMap ) ) ;
2022-08-07 15:53:07 +12:00
// TODO SERIALIZATION The station data needs to be saveable somehow, but when a map gets saved, this entity
// won't be included because its in null-space. Also, what happens to shuttles on other maps?
2023-02-22 12:45:32 +11:00
_transform . DetachParentToNull ( station , Transform ( station ) ) ;
2022-08-07 15:53:07 +12:00
2022-05-10 13:43:30 -05:00
var data = AddComp < StationDataComponent > ( station ) ;
var metaData = MetaData ( station ) ;
data . StationConfig = stationConfig ;
if ( stationConfig is not null & & name is null )
{
2022-06-16 15:28:16 +10:00
name = GenerateStationName ( stationConfig ) ;
2022-05-10 13:43:30 -05:00
}
2022-06-16 15:28:16 +10:00
else if ( name is null )
2022-05-10 13:43:30 -05:00
{
_sawmill . Error ( $"When setting up station {station}, was unable to find a valid name in the config and no name was provided." ) ;
2022-06-16 15:28:16 +10:00
name = "unnamed station" ;
2022-05-10 13:43:30 -05:00
}
2022-06-16 15:28:16 +10:00
metaData . EntityName = name ;
2022-05-10 13:43:30 -05:00
RaiseLocalEvent ( new StationInitializedEvent ( station ) ) ;
_sawmill . Info ( $"Set up station {metaData.EntityName} ({station})." ) ;
foreach ( var grid in gridIds ? ? Array . Empty < EntityUid > ( ) )
{
2022-06-16 15:28:16 +10:00
AddGridToStation ( station , grid , null , data , name ) ;
2022-05-10 13:43:30 -05:00
}
return station ;
}
/// <summary>
/// Adds the given grid to a station.
/// </summary>
/// <param name="mapGrid">Grid to attach.</param>
/// <param name="station">Station to attach the grid to.</param>
/// <param name="gridComponent">Resolve pattern, grid component of mapGrid.</param>
/// <param name="stationData">Resolve pattern, station data component of station.</param>
2022-08-23 02:32:02 -05:00
/// <param name="name">The name to assign to the grid if any.</param>
2022-05-10 13:43:30 -05:00
/// <exception cref="ArgumentException">Thrown when mapGrid or station are not a grid or station, respectively.</exception>
2022-11-04 10:12:25 +11:00
public void AddGridToStation ( EntityUid station , EntityUid mapGrid , MapGridComponent ? gridComponent = null , StationDataComponent ? stationData = null , string? name = null )
2022-05-10 13:43:30 -05:00
{
if ( ! Resolve ( mapGrid , ref gridComponent ) )
throw new ArgumentException ( "Tried to initialize a station on a non-grid entity!" , nameof ( mapGrid ) ) ;
if ( ! Resolve ( station , ref stationData ) )
throw new ArgumentException ( "Tried to use a non-station entity as a station!" , nameof ( station ) ) ;
2022-06-16 15:28:16 +10:00
if ( ! string . IsNullOrEmpty ( name ) )
MetaData ( mapGrid ) . EntityName = name ;
2022-05-10 13:43:30 -05:00
var stationMember = AddComp < StationMemberComponent > ( mapGrid ) ;
stationMember . Station = station ;
2023-01-19 03:56:45 +01:00
stationData . Grids . Add ( gridComponent . Owner ) ;
2022-05-10 13:43:30 -05:00
2023-01-19 03:56:45 +01:00
RaiseLocalEvent ( station , new StationGridAddedEvent ( gridComponent . Owner , false ) , true ) ;
2022-05-10 13:43:30 -05:00
2023-01-19 03:56:45 +01:00
_sawmill . Info ( $"Adding grid {mapGrid}:{gridComponent.Owner} to station {Name(station)} ({station})" ) ;
2022-05-10 13:43:30 -05:00
}
/// <summary>
/// Removes the given grid from a station.
/// </summary>
/// <param name="station">Station to remove the grid from.</param>
/// <param name="mapGrid">Grid to remove</param>
/// <param name="gridComponent">Resolve pattern, grid component of mapGrid.</param>
/// <param name="stationData">Resolve pattern, station data component of station.</param>
/// <exception cref="ArgumentException">Thrown when mapGrid or station are not a grid or station, respectively.</exception>
2022-11-04 10:12:25 +11:00
public void RemoveGridFromStation ( EntityUid station , EntityUid mapGrid , MapGridComponent ? gridComponent = null , StationDataComponent ? stationData = null )
2022-05-10 13:43:30 -05:00
{
if ( ! Resolve ( mapGrid , ref gridComponent ) )
throw new ArgumentException ( "Tried to initialize a station on a non-grid entity!" , nameof ( mapGrid ) ) ;
if ( ! Resolve ( station , ref stationData ) )
throw new ArgumentException ( "Tried to use a non-station entity as a station!" , nameof ( station ) ) ;
RemComp < StationMemberComponent > ( mapGrid ) ;
2023-01-19 03:56:45 +01:00
stationData . Grids . Remove ( gridComponent . Owner ) ;
2022-05-10 13:43:30 -05:00
2023-01-19 03:56:45 +01:00
RaiseLocalEvent ( station , new StationGridRemovedEvent ( gridComponent . Owner ) , true ) ;
_sawmill . Info ( $"Removing grid {mapGrid}:{gridComponent.Owner} from station {Name(station)} ({station})" ) ;
2022-05-10 13:43:30 -05:00
}
/// <summary>
/// Renames the given station.
/// </summary>
/// <param name="station">Station to rename.</param>
/// <param name="name">The new name to apply.</param>
/// <param name="loud">Whether or not to announce the rename.</param>
/// <param name="stationData">Resolve pattern, station data component of station.</param>
/// <param name="metaData">Resolve pattern, metadata component of station.</param>
/// <exception cref="ArgumentException">Thrown when the given station is not a station.</exception>
public void RenameStation ( EntityUid station , string name , bool loud = true , StationDataComponent ? stationData = null , MetaDataComponent ? metaData = null )
{
if ( ! Resolve ( station , ref stationData , ref metaData ) )
throw new ArgumentException ( "Tried to use a non-station entity as a station!" , nameof ( station ) ) ;
var oldName = metaData . EntityName ;
metaData . EntityName = name ;
if ( loud )
{
2022-06-03 21:37:35 +10:00
_chatSystem . DispatchStationAnnouncement ( station , $"The station {oldName} has been renamed to {name}." ) ;
2022-05-10 13:43:30 -05:00
}
2022-06-22 09:53:41 +10:00
RaiseLocalEvent ( station , new StationRenamedEvent ( oldName , name ) , true ) ;
2022-05-10 13:43:30 -05:00
}
/// <summary>
/// Deletes the given station.
/// </summary>
/// <param name="station">Station to delete.</param>
/// <param name="stationData">Resolve pattern, station data component of station.</param>
/// <exception cref="ArgumentException">Thrown when the given station is not a station.</exception>
public void DeleteStation ( EntityUid station , StationDataComponent ? stationData = null )
{
if ( ! Resolve ( station , ref stationData ) )
throw new ArgumentException ( "Tried to use a non-station entity as a station!" , nameof ( station ) ) ;
2022-08-07 15:53:07 +12:00
// component shutdown will error if the station was not removed from _stations prior to deletion.
2022-05-10 13:43:30 -05:00
_stations . Remove ( station ) ;
Del ( station ) ;
}
/// <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 ) ) ;
2022-06-04 19:09:04 +10:00
if ( TryComp < StationDataComponent > ( entity , out _ ) )
{
// We are the station, just return ourselves.
return entity ;
}
2022-11-04 10:12:25 +11:00
if ( TryComp < MapGridComponent > ( entity , out _ ) )
2022-05-10 13:43:30 -05:00
{
// We are the station, just check ourselves.
return CompOrNull < StationMemberComponent > ( entity ) ? . Station ;
}
2022-06-20 12:14:35 +12:00
if ( xform . GridUid = = EntityUid . Invalid )
2022-05-10 13:43:30 -05:00
{
Logger . Debug ( "A" ) ;
return null ;
}
2022-06-20 12:14:35 +12:00
return CompOrNull < StationMemberComponent > ( xform . GridUid ) ? . Station ;
2022-05-10 13:43:30 -05:00
}
}
/// <summary>
/// Broadcast event fired when a station is first set up.
/// This is the ideal point to add components to it.
/// </summary>
[PublicAPI]
public sealed class StationInitializedEvent : EntityEventArgs
{
/// <summary>
/// Station this event is for.
/// </summary>
public EntityUid Station ;
public StationInitializedEvent ( EntityUid station )
{
Station = station ;
}
}
/// <summary>
/// Directed event fired on a station when a grid becomes a member of the station.
/// </summary>
[PublicAPI]
public sealed class StationGridAddedEvent : EntityEventArgs
{
/// <summary>
/// ID of the grid added to the station.
/// </summary>
2022-06-11 18:54:41 -07:00
public EntityUid GridId ;
2022-05-10 13:43:30 -05:00
/// <summary>
/// Indicates that the event was fired during station setup,
/// so that it can be ignored if StationInitializedEvent was already handled.
/// </summary>
public bool IsSetup ;
2022-06-11 18:54:41 -07:00
public StationGridAddedEvent ( EntityUid gridId , bool isSetup )
2022-05-10 13:43:30 -05:00
{
GridId = gridId ;
IsSetup = isSetup ;
}
}
/// <summary>
/// Directed event fired on a station when a grid is no longer a member of the station.
/// </summary>
[PublicAPI]
public sealed class StationGridRemovedEvent : EntityEventArgs
{
/// <summary>
/// ID of the grid removed from the station.
/// </summary>
2022-06-11 18:54:41 -07:00
public EntityUid GridId ;
2022-05-10 13:43:30 -05:00
2022-06-11 18:54:41 -07:00
public StationGridRemovedEvent ( EntityUid gridId )
2022-05-10 13:43:30 -05:00
{
GridId = gridId ;
}
}
/// <summary>
/// Directed event fired on a station when it is renamed.
/// </summary>
[PublicAPI]
public sealed class StationRenamedEvent : EntityEventArgs
{
/// <summary>
/// Prior name of the station.
/// </summary>
public string OldName ;
/// <summary>
/// New name of the station.
/// </summary>
public string NewName ;
public StationRenamedEvent ( string oldName , string newName )
{
OldName = oldName ;
NewName = newName ;
}
}