Add evac shuttle test. (#27152)
* Add evac shuttle test. * Fix typo in comment
This commit is contained in:
111
Content.IntegrationTests/Tests/Station/EvacShuttleTest.cs
Normal file
111
Content.IntegrationTests/Tests/Station/EvacShuttleTest.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -707,7 +707,7 @@ namespace Content.Shared.CCVar
|
|||||||
|
|
||||||
public static readonly CVarDef<bool> CombatModeIndicatorsPointShow =
|
public static readonly CVarDef<bool> CombatModeIndicatorsPointShow =
|
||||||
CVarDef.Create("hud.combat_mode_indicators_point_show", true, CVar.ARCHIVE | CVar.CLIENTONLY);
|
CVarDef.Create("hud.combat_mode_indicators_point_show", true, CVar.ARCHIVE | CVar.CLIENTONLY);
|
||||||
|
|
||||||
public static readonly CVarDef<bool> LoocAboveHeadShow =
|
public static readonly CVarDef<bool> LoocAboveHeadShow =
|
||||||
CVarDef.Create("hud.show_looc_above_head", true, CVar.ARCHIVE | CVar.CLIENTONLY);
|
CVarDef.Create("hud.show_looc_above_head", true, CVar.ARCHIVE | CVar.CLIENTONLY);
|
||||||
|
|
||||||
@@ -1213,7 +1213,7 @@ namespace Content.Shared.CCVar
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly CVarDef<bool> OocEnableDuringRound =
|
public static readonly CVarDef<bool> OocEnableDuringRound =
|
||||||
CVarDef.Create("ooc.enable_during_round", false, CVar.NOTIFY | CVar.REPLICATED | CVar.SERVER);
|
CVarDef.Create("ooc.enable_during_round", false, CVar.NOTIFY | CVar.REPLICATED | CVar.SERVER);
|
||||||
|
|
||||||
public static readonly CVarDef<bool> ShowOocPatronColor =
|
public static readonly CVarDef<bool> ShowOocPatronColor =
|
||||||
CVarDef.Create("ooc.show_ooc_patron_color", true, CVar.ARCHIVE | CVar.REPLICATED | CVar.CLIENT);
|
CVarDef.Create("ooc.show_ooc_patron_color", true, CVar.ARCHIVE | CVar.REPLICATED | CVar.CLIENT);
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user