Add evac shuttle test. (#27152)

* Add evac shuttle test.

* Fix typo in comment
This commit is contained in:
Leon Friedrich
2024-04-20 17:57:55 +12:00
committed by GitHub
parent 4594700d19
commit 12bb476a2d
7 changed files with 138 additions and 19 deletions

View File

@@ -0,0 +1,111 @@
using System.Linq;
using Content.Server.GameTicking;
using Content.Server.Shuttles.Components;
using Content.Server.Shuttles.Systems;
using Content.Server.Station.Components;
using Content.Shared.CCVar;
using Content.Shared.Shuttles.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Map.Components;
namespace Content.IntegrationTests.Tests.Station;
[TestFixture]
[TestOf(typeof(EmergencyShuttleSystem))]
public sealed class EvacShuttleTest
{
/// <summary>
/// Ensure that the emergency shuttle can be called, and that it will travel to centcomm
/// </summary>
[Test]
public async Task EmergencyEvacTest()
{
await using var pair = await PoolManager.GetServerClient(new PoolSettings { DummyTicker = true, Dirty = true });
var server = pair.Server;
var entMan = server.EntMan;
var ticker = server.System<GameTicker>();
var shuttleEnabled = pair.Server.CfgMan.GetCVar(CCVars.EmergencyShuttleEnabled);
pair.Server.CfgMan.SetCVar(CCVars.GameMap, "Saltern");
pair.Server.CfgMan.SetCVar(CCVars.GameDummyTicker, false);
pair.Server.CfgMan.SetCVar(CCVars.EmergencyShuttleEnabled, true);
await server.WaitPost(() => ticker.RestartRound());
await pair.RunTicksSync(25);
Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.InRound));
// Find the station, centcomm, and shuttle, and ftl map.
Assert.That(entMan.Count<StationCentcommComponent>(), Is.EqualTo(1));
Assert.That(entMan.Count<StationEmergencyShuttleComponent>(), Is.EqualTo(1));
Assert.That(entMan.Count<StationDataComponent>(), Is.EqualTo(1));
Assert.That(entMan.Count<EmergencyShuttleComponent>(), Is.EqualTo(1));
Assert.That(entMan.Count<FTLMapComponent>(), Is.EqualTo(0));
var station = (Entity<StationCentcommComponent>) entMan.AllComponentsList<StationCentcommComponent>().Single();
var data = entMan.GetComponent<StationDataComponent>(station);
var shuttleData = entMan.GetComponent<StationEmergencyShuttleComponent>(station);
var saltern = data.Grids.Single();
Assert.That(entMan.HasComponent<MapGridComponent>(saltern));
var shuttle = shuttleData.EmergencyShuttle!.Value;
Assert.That(entMan.HasComponent<EmergencyShuttleComponent>(shuttle));
Assert.That(entMan.HasComponent<MapGridComponent>(shuttle));
var centcomm = station.Comp.Entity!.Value;
Assert.That(entMan.HasComponent<MapGridComponent>(centcomm));
var centcommMap = station.Comp.MapEntity!.Value;
Assert.That(entMan.HasComponent<MapComponent>(centcommMap));
Assert.That(server.Transform(centcomm).MapUid, Is.EqualTo(centcommMap));
var salternXform = server.Transform(saltern);
Assert.That(salternXform.MapUid, Is.Not.Null);
Assert.That(salternXform.MapUid, Is.Not.EqualTo(centcommMap));
var shuttleXform = server.Transform(shuttle);
Assert.That(shuttleXform.MapUid, Is.Not.Null);
Assert.That(shuttleXform.MapUid, Is.EqualTo(centcommMap));
// Set up shuttle timing
var evacSys = server.System<EmergencyShuttleSystem>();
evacSys.TransitTime = ShuttleSystem.DefaultTravelTime; // Absolute minimum transit time, so the test has to run for at least this long
// TODO SHUTTLE fix spaghetti
var dockTime = server.CfgMan.GetCVar(CCVars.EmergencyShuttleDockTime);
server.CfgMan.SetCVar(CCVars.EmergencyShuttleDockTime, 2);
async Task RunSeconds(float seconds)
{
await pair.RunTicksSync((int) Math.Ceiling(seconds / server.Timing.TickPeriod.TotalSeconds));
}
// Call evac shuttle.
await pair.WaitCommand("callshuttle 0:02");
await RunSeconds(3);
// Shuttle should have arrived on the station
Assert.That(shuttleXform.MapUid, Is.EqualTo(salternXform.MapUid));
await RunSeconds(2);
// Shuttle should be FTLing back to centcomm
Assert.That(entMan.Count<FTLMapComponent>(), Is.EqualTo(1));
var ftl = (Entity<FTLMapComponent>) entMan.AllComponentsList<FTLMapComponent>().Single();
Assert.That(entMan.HasComponent<MapComponent>(ftl));
Assert.That(ftl.Owner, Is.Not.EqualTo(centcommMap));
Assert.That(ftl.Owner, Is.Not.EqualTo(salternXform.MapUid));
Assert.That(shuttleXform.MapUid, Is.EqualTo(ftl.Owner));
// Shuttle should have arrived at centcomm
await RunSeconds(ShuttleSystem.DefaultTravelTime);
Assert.That(shuttleXform.MapUid, Is.EqualTo(centcommMap));
// Round should be ending now
Assert.That(ticker.RunLevel, Is.EqualTo(GameRunLevel.PostRound));
server.CfgMan.SetCVar(CCVars.EmergencyShuttleDockTime, dockTime);
pair.Server.CfgMan.SetCVar(CCVars.EmergencyShuttleEnabled, shuttleEnabled);
await pair.CleanReturnAsync();
}
}

View File

@@ -192,6 +192,8 @@ namespace Content.Server.RoundEnd
LastCountdownStart = _gameTiming.CurTime; LastCountdownStart = _gameTiming.CurTime;
ExpectedCountdownEnd = _gameTiming.CurTime + countdownTime; ExpectedCountdownEnd = _gameTiming.CurTime + countdownTime;
// TODO full game saves
Timer.Spawn(countdownTime, _shuttle.CallEmergencyShuttle, _countdownTokenSource.Token); Timer.Spawn(countdownTime, _shuttle.CallEmergencyShuttle, _countdownTokenSource.Token);
ActivateCooldown(); ActivateCooldown();
@@ -337,6 +339,8 @@ namespace Content.Server.RoundEnd
{ {
_cooldownTokenSource?.Cancel(); _cooldownTokenSource?.Cancel();
_cooldownTokenSource = new(); _cooldownTokenSource = new();
// TODO full game saves
Timer.Spawn(DefaultCooldownDuration, () => Timer.Spawn(DefaultCooldownDuration, () =>
{ {
_cooldownTokenSource.Cancel(); _cooldownTokenSource.Cancel();

View File

@@ -14,6 +14,8 @@ namespace Content.Server.Shuttles.Components;
[RegisterComponent] [RegisterComponent]
public sealed partial class FTLComponent : Component public sealed partial class FTLComponent : Component
{ {
// TODO Full game save / add datafields
[ViewVariables] [ViewVariables]
public FTLState State = FTLState.Available; public FTLState State = FTLState.Available;
@@ -23,6 +25,7 @@ public sealed partial class FTLComponent : Component
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public float StartupTime = 0f; public float StartupTime = 0f;
// Because of sphagetti, actual travel time is Math.Max(TravelTime, DefaultArrivalTime)
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public float TravelTime = 0f; public float TravelTime = 0f;

View File

@@ -19,6 +19,8 @@ using Timer = Robust.Shared.Timing.Timer;
namespace Content.Server.Shuttles.Systems; namespace Content.Server.Shuttles.Systems;
// TODO full game saves
// Move state data into the emergency shuttle component
public sealed partial class EmergencyShuttleSystem public sealed partial class EmergencyShuttleSystem
{ {
/* /*
@@ -55,7 +57,7 @@ public sealed partial class EmergencyShuttleSystem
/// <summary> /// <summary>
/// How long it will take for the emergency shuttle to arrive at CentComm. /// How long it will take for the emergency shuttle to arrive at CentComm.
/// </summary> /// </summary>
public float TransitTime { get; private set; } public float TransitTime;
/// <summary> /// <summary>
/// <see cref="CCVars.EmergencyShuttleAuthorizeTime"/> /// <see cref="CCVars.EmergencyShuttleAuthorizeTime"/>
@@ -132,6 +134,14 @@ public sealed partial class EmergencyShuttleSystem
var minTime = -(TransitTime - (ShuttleSystem.DefaultStartupTime + ShuttleSystem.DefaultTravelTime + 1f)); var minTime = -(TransitTime - (ShuttleSystem.DefaultStartupTime + ShuttleSystem.DefaultTravelTime + 1f));
// TODO: I know this is shit but I already just cleaned up a billion things. // TODO: I know this is shit but I already just cleaned up a billion things.
// This is very cursed spaghetti code. I don't even know what the fuck this is doing or why it exists.
// But I think it needs to be less than or equal to zero or the shuttle might never leave???
// TODO Shuttle AAAAAAAAAAAAAAAAAAAAAAAAA
// Clean this up, just have a single timer with some state system.
// I.e., dont infer state from the current interval that the accumulator is in???
minTime = Math.Min(0, minTime); // ????
if (_consoleAccumulator < minTime) if (_consoleAccumulator < minTime)
{ {
return; return;

View File

@@ -40,6 +40,10 @@ public sealed partial class ShuttleSystem
public const float FTLMassLimit = 300f; public const float FTLMassLimit = 300f;
// I'm too lazy to make CVars. // I'm too lazy to make CVars.
// >:(
// Confusingly, some of them already are cvars?
// I.e., shuttle transit time???
// TODO Shuttle: fix spaghetti
private readonly SoundSpecifier _startupSound = new SoundPathSpecifier("/Audio/Effects/Shuttle/hyperspace_begin.ogg") private readonly SoundSpecifier _startupSound = new SoundPathSpecifier("/Audio/Effects/Shuttle/hyperspace_begin.ogg")
{ {

View File

@@ -112,26 +112,12 @@ public sealed class StationSystem : EntitySystem
{ {
var dict = new Dictionary<string, List<EntityUid>>(); var dict = new Dictionary<string, List<EntityUid>>();
void AddGrid(string station, EntityUid grid)
{
if (dict.ContainsKey(station))
{
dict[station].Add(grid);
}
else
{
dict[station] = new List<EntityUid> {grid};
}
}
// Iterate over all BecomesStation // Iterate over all BecomesStation
foreach (var grid in ev.Grids) foreach (var grid in ev.Grids)
{ {
// We still setup the grid // We still setup the grid
if (!TryComp<BecomesStationComponent>(grid, out var becomesStation)) if (TryComp<BecomesStationComponent>(grid, out var becomesStation))
continue; dict.GetOrNew(becomesStation.Id).Add(grid);
AddGrid(becomesStation.Id, grid);
} }
if (!dict.Any()) if (!dict.Any())

View File

@@ -1446,6 +1446,7 @@ namespace Content.Shared.CCVar
/// <summary> /// <summary>
/// The minimum time for the emergency shuttle to arrive at centcomm. /// The minimum time for the emergency shuttle to arrive at centcomm.
/// Actual minimum travel time cannot be less than <see cref="ShuttleSystem.DefaultArrivalTime"/>
/// </summary> /// </summary>
public static readonly CVarDef<float> EmergencyShuttleMinTransitTime = public static readonly CVarDef<float> EmergencyShuttleMinTransitTime =
CVarDef.Create("shuttle.emergency_transit_time_min", 60f, CVar.SERVERONLY); CVarDef.Create("shuttle.emergency_transit_time_min", 60f, CVar.SERVERONLY);