diff --git a/Content.Server/_NF/PublicTransit/Components/TransitShuttleComponent.cs b/Content.Server/_NF/PublicTransit/Components/TransitShuttleComponent.cs
index 8adf7a1137a..6696db5bdd8 100644
--- a/Content.Server/_NF/PublicTransit/Components/TransitShuttleComponent.cs
+++ b/Content.Server/_NF/PublicTransit/Components/TransitShuttleComponent.cs
@@ -2,6 +2,11 @@
namespace Content.Server._NF.PublicTransit.Components;
+///
+/// Added to a grid to have it act as an automated public transit bus.
+/// Public Transit system will add this procedurally to any grid designated as a 'bus' through the CVAR
+/// Mappers may add it to their shuttle if they wish, but this is going to force it's use and function as a public transit bus
+///
[RegisterComponent, Access(typeof(PublicTransitSystem))]
public sealed partial class TransitShuttleComponent : Component
{
diff --git a/Content.Server/_NF/PublicTransit/PublicTransitSystem.cs b/Content.Server/_NF/PublicTransit/PublicTransitSystem.cs
index 38ceb8f4447..80ac595f6f2 100644
--- a/Content.Server/_NF/PublicTransit/PublicTransitSystem.cs
+++ b/Content.Server/_NF/PublicTransit/PublicTransitSystem.cs
@@ -1,5 +1,3 @@
-
-using Content.Server.GameTicking.Events;
using Content.Server._NF.PublicTransit.Components;
using Content.Server.GameTicking;
using Content.Server.Shuttles.Components;
@@ -17,7 +15,7 @@
namespace Content.Server._NF.PublicTransit;
///
-/// If enabled spawns players on a separate arrivals station before they can transfer to the main station.
+/// If enabled, spawns a public trasnport grid as definied by cvar, to act as an automatic transit shuttle between designated grids
///
public sealed class PublicTransitSystem : EntitySystem
{
@@ -29,7 +27,7 @@ public sealed class PublicTransitSystem : EntitySystem
[Dependency] private readonly ShuttleSystem _shuttles = default!;
///
- /// If enabled then spawns players on an alternate map so they can take a shuttle to the station.
+ /// If enabled then spawns the bus and sets up the bus line.
///
public bool Enabled { get; private set; }
public float FlyTime = 50f;
@@ -42,12 +40,10 @@ public override void Initialize()
SubscribeLocalEvent(OnStationStartup);
SubscribeLocalEvent(OnStationShutdown);
-
SubscribeLocalEvent(OnShuttleStartup);
SubscribeLocalEvent(OnShuttleUnpaused);
SubscribeLocalEvent(OnShuttleTag);
- // Don't invoke immediately as it will get set in the natural course of things.
Enabled = _cfgManager.GetCVar(NF14CVars.PublicTransit);
FlyTime = _cfgManager.GetCVar(NF14CVars.PublicTransitFlyTime);
Counter = 0;
@@ -56,12 +52,15 @@ public override void Initialize()
_cfgManager.OnValueChanged(NF14CVars.PublicTransitFlyTime, SetFly);
}
+ ///
+ /// Hardcoded snippit to intercept FTL events. It catches the transit shuttle and ensures its looking for the "DockTransit" priority dock.
+ ///
private void OnShuttleTag(EntityUid uid, TransitShuttleComponent component, ref FTLTagEvent args)
{
if (args.Handled)
return;
- // Just saves mappers forgetting.
+ // Just saves mappers forgetting, or ensuring that a non-standard grid forced to be a bus will prioritize the "DockTransit" tagged docks
args.Handled = true;
args.Tag = "DockTransit";
}
@@ -69,37 +68,59 @@ private void OnShuttleTag(EntityUid uid, TransitShuttleComponent component, ref
public override void Shutdown()
{
base.Shutdown();
+ _cfgManager.UnsubValueChanged(NF14CVars.PublicTransitFlyTime, SetFly);
_cfgManager.UnsubValueChanged(NF14CVars.PublicTransit, SetTransit);
}
+ ///
+ /// Checks to make sure the grid is on the appropriate playfield, i.e., not in mapping space being worked on.
+ /// If so, adds the grid to the list of bus stops, but only if its not already there
+ ///
private void OnStationStartup(EntityUid uid, StationTransitComponent component, ComponentStartup args)
{
- if (Transform(uid).MapID == _ticker.DefaultMap)
+ if (Transform(uid).MapID == _ticker.DefaultMap) //best solution i could find because of componentinit/mapinit race conditions
{
- if (!StationList.Contains(uid))
- StationList.Add(uid);
- if (Enabled)
+ if (!StationList.Contains(uid)) //if the grid isnt already in
+ StationList.Add(uid); //add it to the list
+ if (Enabled) //and just in case this has been added dynamically mid-round, lets do a setup check
SetupPublicTransit();
}
}
+ ///
+ /// When a bus stop gets deleted in-game, we need to remove it from the list of bus stops, or else we get FTL problems
+ ///
private void OnStationShutdown(EntityUid uid, StationTransitComponent component, ComponentShutdown args)
{
if (StationList.Contains(uid))
StationList.Remove(uid);
}
+ ///
+ /// Again, this can and likely should be instructed to mappers to do, but just in case it was either forgotten or we are doing admemes,
+ /// we make sure that the bus is (mostly) griefer protected and that it cant be hijacked
+ ///
private void OnShuttleStartup(EntityUid uid, TransitShuttleComponent component, ComponentStartup args)
{
EnsureComp(uid);
EnsureComp(uid);
}
+ ///
+ /// ensuring that pausing the shuttle for any reason doesnt mess up our timing
+ ///
private void OnShuttleUnpaused(EntityUid uid, TransitShuttleComponent component, ref EntityUnpausedEvent args)
{
component.NextTransfer += args.PausedTime;
}
+ ///
+ /// Here is our bus stop list handler. Theres probably a better way...
+ /// First, sets our output to null just in case
+ /// then, makes sure that our counter/index isnt out of range (reaching the end of the list will force you back to the beginning, like a loop)
+ /// Then, it checks to make sure that there even is anything in the list
+ /// and if so, we return the next station, and then increment our counter for the next time its ran
+ ///
private bool TryGetNextStation(out EntityUid? station)
{
station = null;
@@ -115,6 +136,16 @@ private bool TryGetNextStation(out EntityUid? station)
return true;
}
+ ///
+ /// We check the current time every tick, and if its not yet time, we just ignore.
+ /// If the timer is ready, we send the shuttle on an FTL journey to the destination it has saved
+ /// then we check our bus list, and if it returns true with the next station, we cache it on the component and reset the timer
+ /// if it returns false or gives a bad grid, we are just going to FTL back to where we are and try again until theres a proper destination
+ /// This could cause unintended behavior, if a destination is deleted while it's next in the cache, the shuttle is going to be stuck in FTL space
+ /// However the timer is going to force it to FTL to the next bus stop
+ /// If it happens that all bus stops are deleted and we never get a valid stop again, we are going to be stuck FTL'ing forever in ftl space
+ /// but at that point, theres nowhere to return to anyway
+ ///
public override void Update(float frameTime)
{
base.Update(frameTime);
@@ -136,6 +167,13 @@ public override void Update(float frameTime)
}
}
+ ///
+ /// Here is handling a simple CVAR change to enable/disable the system
+ /// if the cvar is changed to enabled, we setup the transit system
+ /// if its changed to disabled, we delete any bus grids that exist
+ /// along with anyone/thing riding the bus
+ /// you've been warned
+ ///
private void SetTransit(bool obj)
{
Enabled = obj;
@@ -155,35 +193,48 @@ private void SetTransit(bool obj)
}
}
+ ///
+ /// Simple cache reflection
+ ///
private void SetFly(float obj)
{
FlyTime = obj;
}
+ ///
+ /// Here is where we handle setting up the transit system, including sanity checks.
+ /// This is called multiple times, from a few different sources, to ensure that if the system is activated dynamically
+ /// it will still function as intended
+ ///
private void SetupPublicTransit()
{
+ // If a public bus alraedy exists, we simply return. No need to set up the system again.
var query = EntityQueryEnumerator();
while (query.MoveNext(out var euid, out _))
{
if (!Deleted(euid))
return;
}
- // Spawn arrivals on a dummy map then dock it to the source.
+
+ // Spawn the bus onto a dummy map
var dummyMap = _mapManager.CreateMap();
var busMap = _cfgManager.GetCVar(NF14CVars.PublicTransitBusMap);
if (_loader.TryLoad(dummyMap, busMap, out var shuttleUids))
{
var shuttleComp = Comp(shuttleUids[0]);
+ // Here we are making sure that the shuttle has the TransitShuttle comp onto it, in case of dynamically changing the bus grid
var transitComp = EnsureComp(shuttleUids[0]);
+
+ //We run our bus station function to try to get a valid station to FTL to. If for some reason, there are no bus stops, we will instead just delete the shuttle
if (TryGetNextStation(out var station) && station is { Valid : true } destination)
{
- transitComp.NextStation = destination; //we set up a default in case theres only 1
- // EnsureComp(uid); Enable in the case we want to ensure EMP immune grid
-
+ //we set up a default in case the second time we call it fails for some reason
+ transitComp.NextStation = destination;
_shuttles.FTLTravel(shuttleUids[0], shuttleComp, destination, hyperspaceTime: 5f, dock: true);
- transitComp.NextTransfer = _timing.CurTime +
- TimeSpan.FromSeconds(_cfgManager.GetCVar(NF14CVars.PublicTransitWaitTime));
+ transitComp.NextTransfer = _timing.CurTime + TimeSpan.FromSeconds(_cfgManager.GetCVar(NF14CVars.PublicTransitWaitTime));
+ //since the initial cached value of the next station is actually the one we are 'starting' from, we need to run the
+ //bus stop list code one more time so that our first trip isnt just Frontier - Frontier
if (TryGetNextStation(out var firstStop) && firstStop is { Valid : true } firstDestination)
transitComp.NextStation = firstDestination;
}
@@ -196,7 +247,8 @@ private void SetupPublicTransit()
}
}
- // Don't start the arrivals shuttle immediately docked so power has a time to stabilise?
+ // the FTL sequence takes a few seconds to warm up and send the grid, so we give the temp dummy map
+ // some buffer time before calling a self-delete
var timer = AddComp(_mapManager.GetMapEntityId(dummyMap));
timer.Lifetime = 15f;
}