diff --git a/Content.Server/RoundEnd/RoundEndSystem.cs b/Content.Server/RoundEnd/RoundEndSystem.cs
index 3a8331f3f7..758e2e3146 100644
--- a/Content.Server/RoundEnd/RoundEndSystem.cs
+++ b/Content.Server/RoundEnd/RoundEndSystem.cs
@@ -145,11 +145,15 @@ namespace Content.Server.RoundEnd
public void RequestRoundEnd(TimeSpan countdownTime, EntityUid? requester = null, bool checkCooldown = true, string text = "round-end-system-shuttle-called-announcement", string name = "Station")
{
- if (_gameTicker.RunLevel != GameRunLevel.InRound) return;
+ if (_gameTicker.RunLevel != GameRunLevel.InRound)
+ return;
- if (checkCooldown && _cooldownTokenSource != null) return;
+ if (checkCooldown && _cooldownTokenSource != null)
+ return;
+
+ if (_countdownTokenSource != null)
+ return;
- if (_countdownTokenSource != null) return;
_countdownTokenSource = new();
if (requester != null)
diff --git a/Content.Server/Shuttles/Components/StationEmergencyShuttleComponent.cs b/Content.Server/Shuttles/Components/StationEmergencyShuttleComponent.cs
index bdfdcb273a..58d23ee432 100644
--- a/Content.Server/Shuttles/Components/StationEmergencyShuttleComponent.cs
+++ b/Content.Server/Shuttles/Components/StationEmergencyShuttleComponent.cs
@@ -13,7 +13,7 @@ public sealed partial class StationEmergencyShuttleComponent : Component
///
/// The emergency shuttle assigned to this station.
///
- [ViewVariables, Access(typeof(ShuttleSystem), typeof(EmergencyShuttleSystem), Friend = AccessPermissions.ReadWrite)]
+ [DataField, Access(typeof(ShuttleSystem), typeof(EmergencyShuttleSystem), Friend = AccessPermissions.ReadWrite)]
public EntityUid? EmergencyShuttle;
///
diff --git a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs
index 16a5e26b54..2a68f7a1be 100644
--- a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs
+++ b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs
@@ -83,9 +83,9 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
SubscribeLocalEvent(OnRoundStart);
SubscribeLocalEvent(OnRoundCleanup);
- SubscribeLocalEvent(OnStationStartup);
+ SubscribeLocalEvent(OnStationStartup);
SubscribeLocalEvent(OnCentcommShutdown);
- SubscribeLocalEvent(OnStationPostInit);
+ SubscribeLocalEvent(OnStationInit);
SubscribeLocalEvent(OnEmergencyFTL);
SubscribeLocalEvent(OnEmergencyFTLComplete);
@@ -259,10 +259,13 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
///
public void CallEmergencyShuttle(EntityUid stationUid, StationEmergencyShuttleComponent? stationShuttle = null)
{
- if (!Resolve(stationUid, ref stationShuttle) ||
- !TryComp(stationShuttle.EmergencyShuttle, out var xform) ||
+ if (!Resolve(stationUid, ref stationShuttle))
+ return;
+
+ if (!TryComp(stationShuttle.EmergencyShuttle, out var xform) ||
!TryComp(stationShuttle.EmergencyShuttle, out var shuttle))
{
+ Log.Error($"Attempted to call an emergency shuttle for an uninitialized station? Station: {ToPrettyString(stationUid)}. Shuttle: {ToPrettyString(stationShuttle.EmergencyShuttle)}");
return;
}
@@ -320,8 +323,10 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
}
}
- private void OnStationPostInit(EntityUid uid, StationCentcommComponent component, ref StationPostInitEvent args)
+ private void OnStationInit(EntityUid uid, StationCentcommComponent component, MapInitEvent args)
{
+ // This is handled on map-init, so that centcomm has finished initializing by the time the StationPostInitEvent
+ // gets raised
if (!_emergencyShuttleEnabled)
return;
@@ -332,12 +337,12 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
return;
}
- AddCentcomm(component);
+ AddCentcomm(uid, component);
}
- private void OnStationStartup(EntityUid uid, StationEmergencyShuttleComponent component, ComponentStartup args)
+ private void OnStationStartup(Entity ent, ref StationPostInitEvent args)
{
- AddEmergencyShuttle(uid, component);
+ AddEmergencyShuttle((ent, ent));
}
///
@@ -374,19 +379,22 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
var centcommQuery = AllEntityQuery();
- while (centcommQuery.MoveNext(out var centcomm))
+ while (centcommQuery.MoveNext(out var uid, out var centcomm))
{
- AddCentcomm(centcomm);
+ AddCentcomm(uid, centcomm);
}
var query = AllEntityQuery();
while (query.MoveNext(out var uid, out var comp))
- AddEmergencyShuttle(uid, comp);
+ {
+ AddEmergencyShuttle((uid, comp));
+ }
}
- private void AddCentcomm(StationCentcommComponent component)
+ private void AddCentcomm(EntityUid station, StationCentcommComponent component)
{
+ DebugTools.Assert(LifeStage(station)>= EntityLifeStage.MapInitialized);
if (component.MapEntity != null || component.Entity != null)
{
Log.Warning("Attempted to re-add an existing centcomm map.");
@@ -402,7 +410,7 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
if (!Exists(otherComp.MapEntity) || !Exists(otherComp.Entity))
{
- Log.Error($"Disconvered invalid centcomm component?");
+ Log.Error($"Discovered invalid centcomm component?");
ClearCentcomm(otherComp);
continue;
}
@@ -451,6 +459,7 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
component.MapEntity = map;
component.Entity = grid;
_shuttle.TryAddFTLDestination(mapId, false, out _);
+ Log.Info($"Created centcomm grid {ToPrettyString(grid)} on map {ToPrettyString(map)} for station {ToPrettyString(station)}");
}
public HashSet GetCentcommMaps()
@@ -467,49 +476,67 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
return maps;
}
- private void AddEmergencyShuttle(EntityUid uid, StationEmergencyShuttleComponent component)
+ private void AddEmergencyShuttle(Entity ent)
{
- if (!_emergencyShuttleEnabled
- || component.EmergencyShuttle != null ||
- !TryComp(uid, out var centcomm)
- || !TryComp(centcomm.MapEntity, out MapComponent? map))
+ if (!Resolve(ent.Owner, ref ent.Comp1, ref ent.Comp2))
+ return;
+
+ if (!_emergencyShuttleEnabled)
+ return;
+
+ if (ent.Comp1.EmergencyShuttle != null )
{
+ if (Exists(ent.Comp1.EmergencyShuttle))
+ {
+ Log.Error($"Attempted to add an emergency shuttle to {ToPrettyString(ent)}, despite a shuttle already existing?");
+ return;
+ }
+
+ Log.Error($"Encountered deleted emergency shuttle during initialization of {ToPrettyString(ent)}");
+ ent.Comp1.EmergencyShuttle = null;
+ }
+
+ if (!TryComp(ent.Comp2.MapEntity, out MapComponent? map))
+ {
+ Log.Error($"Failed to add emergency shuttle - centcomm has not been initialized? {ToPrettyString(ent)}");
return;
}
// Load escape shuttle
- var shuttlePath = component.EmergencyShuttlePath;
+ var shuttlePath = ent.Comp1.EmergencyShuttlePath;
var shuttle = _map.LoadGrid(map.MapId, shuttlePath.ToString(), new MapLoadOptions()
{
// Should be far enough... right? I'm too lazy to bounds check CentCom rn.
- Offset = new Vector2(500f + centcomm.ShuttleIndex, 0f),
+ Offset = new Vector2(500f + ent.Comp2.ShuttleIndex, 0f),
// fun fact: if you just fucking yeet centcomm into nullspace anytime you try to spawn the shuttle, then any distance is far enough. so lets not do that
LoadMap = false,
});
if (shuttle == null)
{
- Log.Error($"Unable to spawn emergency shuttle {shuttlePath} for {ToPrettyString(uid)}");
+ Log.Error($"Unable to spawn emergency shuttle {shuttlePath} for {ToPrettyString(ent)}");
return;
}
- centcomm.ShuttleIndex += Comp(shuttle.Value).LocalAABB.Width + ShuttleSpawnBuffer;
+ ent.Comp2.ShuttleIndex += Comp(shuttle.Value).LocalAABB.Width + ShuttleSpawnBuffer;
// Update indices for all centcomm comps pointing to same map
var query = AllEntityQuery();
while (query.MoveNext(out var comp))
{
- if (comp == centcomm || comp.MapEntity != centcomm.MapEntity)
+ if (comp == ent.Comp2 || comp.MapEntity != ent.Comp2.MapEntity)
continue;
- comp.ShuttleIndex = centcomm.ShuttleIndex;
+ comp.ShuttleIndex = ent.Comp2.ShuttleIndex;
}
- component.EmergencyShuttle = shuttle;
+ ent.Comp1.EmergencyShuttle = shuttle;
EnsureComp(shuttle.Value);
EnsureComp(shuttle.Value);
EnsureComp(shuttle.Value);
+
+ Log.Info($"Added emergency shuttle {ToPrettyString(shuttle)} for station {ToPrettyString(ent)} and centcomm {ToPrettyString(ent.Comp2.Entity)}");
}
///
diff --git a/Content.Server/Station/Events/StationPostInitEvent.cs b/Content.Server/Station/Events/StationPostInitEvent.cs
index 4f7927cee5..54b8eeeb31 100644
--- a/Content.Server/Station/Events/StationPostInitEvent.cs
+++ b/Content.Server/Station/Events/StationPostInitEvent.cs
@@ -4,6 +4,8 @@ namespace Content.Server.Station.Events;
///
/// Raised directed on a station after it has been initialized, as well as broadcast.
+/// This gets raised after the entity has been map-initialized, and the station's centcomm map/entity (if any) has been
+/// set up.
///
[ByRefEvent]
public readonly record struct StationPostInitEvent(Entity Station);
diff --git a/Content.Server/Station/Systems/StationSystem.cs b/Content.Server/Station/Systems/StationSystem.cs
index 408b3ebc55..2ab33b62a5 100644
--- a/Content.Server/Station/Systems/StationSystem.cs
+++ b/Content.Server/Station/Systems/StationSystem.cs
@@ -294,8 +294,6 @@ public sealed class StationSystem : EntitySystem
// Use overrides for setup.
var station = EntityManager.SpawnEntity(stationConfig.StationPrototype, MapCoordinates.Nullspace, stationConfig.StationComponentOverrides);
-
-
if (name is not null)
RenameStation(station, name, false);
@@ -346,6 +344,9 @@ public sealed class StationSystem : EntitySystem
}
}
+ if (LifeStage(station) < EntityLifeStage.MapInitialized)
+ throw new Exception($"Station must be man-initialized");
+
var ev = new StationPostInitEvent((station, data));
RaiseLocalEvent(station, ref ev, true);