Files
wwdpublic/Content.IntegrationTests/Tests/PostMapInitTest.cs
Jonathan 314db451f7 Box Station For EE (#1615)
# Description
Howdy, y'all, I apologize for the delay, but I've finally completed the
Box Station for EE. I've added a few things, including the supermatter
crystal (SM) with the thermal-electric generator (TEG) near the Atmos
Department TEG-KIT. I've also added all the job spawn points that were
available for now: NanotrasenRepresentative, BlueshieldOfficer,
Magistrate, AdministrativeAssistant, SeniorEngineer, SeniorPhysician,
SeniorResearcher, SeniorOfficer, MailCarrier, ForensicMantis,
Roboticist, MailCarrier, Reporter, StationAI, and MedicalBorg. Finally,
I added holopads in all departments with AI upload (all law circuit
boards).

<details><summary><h1>Media</h1></summary>
<p>

![Screenshot 2025-01-20
075641](https://github.com/user-attachments/assets/b41d0518-5bd8-48fd-ab7f-fcd3b4b8a585)
![Screenshot 2025-01-20
075630](https://github.com/user-attachments/assets/725d5af0-c238-4da3-8e8d-3944b1ecbbc3)
![Screenshot 2025-01-20
075617](https://github.com/user-attachments/assets/80e7c6f4-52b6-4754-80af-a4a1f9cafdf7)
![Screenshot 2025-01-20
075606](https://github.com/user-attachments/assets/e92b4c84-88e8-4aca-8f19-f1970406eeac)
![Screenshot 2025-01-20
075558](https://github.com/user-attachments/assets/fdbb4277-2982-4c77-81b2-73a7ee335340)
![Screenshot 2025-01-20
075552](https://github.com/user-attachments/assets/b298326e-132c-42c0-abce-3259a6d589b6)
![Screenshot 2025-01-20
075546](https://github.com/user-attachments/assets/66cda318-167f-4728-8e8c-e273f108bcbd)
![Screenshot 2025-01-20
075541](https://github.com/user-attachments/assets/22a586c8-7205-4caf-b87f-a55361c87015)
![Screenshot 2025-01-20
075535](https://github.com/user-attachments/assets/3413741d-574a-45ab-aba0-5c5bb8b315ee)
![Screenshot 2025-01-20
075521](https://github.com/user-attachments/assets/13dd5158-1956-4a16-b780-79a8b06e8efe)
![Screenshot 2025-01-20
075511](https://github.com/user-attachments/assets/efd8bd4a-8ddc-4c75-83fb-d20927f13487)
![Screenshot 2025-01-20
075505](https://github.com/user-attachments/assets/ccfb7557-dc62-4437-8472-3277973c9951)
![Screenshot 2025-01-20
075455](https://github.com/user-attachments/assets/6dd6b99b-c060-4fb8-b8d8-e7b007997f0e)
![Screenshot 2025-01-20
075449](https://github.com/user-attachments/assets/156f21d7-2856-48d0-b151-5b11d7d2f772)
![Screenshot 2025-01-20
075445](https://github.com/user-attachments/assets/2b30ddb3-1a9a-44b4-b57c-c3a6bc0deb33)
![Screenshot 2025-01-20
075433](https://github.com/user-attachments/assets/e0b22201-9cc7-48a0-abb2-da8a2b35673b)
![Screenshot 2025-01-20
075423](https://github.com/user-attachments/assets/4f2eb824-a9b1-4823-8215-361ee5d51240)
![Screenshot 2025-01-20
075400](https://github.com/user-attachments/assets/6dedfd3b-bb9d-418d-8138-dc42bb9edf80)
![Screenshot 2025-01-20
075339](https://github.com/user-attachments/assets/5b786512-7005-4a7e-b356-407734cee759)
![Screenshot 2025-01-20
075320](https://github.com/user-attachments/assets/0e6ecf0b-1a79-429e-96a0-ff9ba9185644)
![Screenshot 2025-01-20
075308](https://github.com/user-attachments/assets/e9954ada-ac51-4696-ae05-72a6bb6aac86)
![Screenshot 2025-01-20
044511](https://github.com/user-attachments/assets/b10ee8fd-9989-433a-be58-96e361e3f284)
![Screenshot 2025-01-20
044343](https://github.com/user-attachments/assets/9fcf6d20-c9ee-44d9-83e5-a2708fee750c)

</p>
</details>

---

# Changelog

<!--
You can add an author after the `🆑` to change the name that appears
in the changelog (ex: `🆑 Death`)
Leaving it blank will default to your GitHub display name
This includes all available types for the changelog
-->

🆑 Mike32oz
- add: Box Station, supermatter crystal, holopads, and Thermal-electric
generator.
- tweak: Box Station, Engineer, Medical, Epistemics, Cargo, Security,
and Service Departments.
- remove: Box Station, Particle Accelerator Room in Engineer
Departments.

---------

Signed-off-by: sleepyyapril <123355664+sleepyyapril@users.noreply.github.com>
Co-authored-by: stellar-novas <stellar_novas@riseup.net>
Co-authored-by: VMSolidus <evilexecutive@gmail.com>
Co-authored-by: sleepyyapril <123355664+sleepyyapril@users.noreply.github.com>

(cherry picked from commit 0f9a795dd9854c8b102514ab1d09257956fbf292)
2025-01-23 08:10:07 +03:00

409 lines
15 KiB
C#

using System.Collections.Generic;
using System.IO;
using System.Linq;
using Content.Server.GameTicking;
using Content.Server.Maps;
using Content.Server.Shuttles.Components;
using Content.Server.Shuttles.Systems;
using Content.Server.Spawners.Components;
using Content.Server.Station.Components;
using Content.Shared.CCVar;
using Content.Shared.Roles;
using Robust.Server.GameObjects;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using YamlDotNet.RepresentationModel;
namespace Content.IntegrationTests.Tests
{
[TestFixture]
public sealed class PostMapInitTest
{
private const bool SkipTestMaps = true;
private const string TestMapsPath = "/Maps/Test/";
private static readonly string[] NoSpawnMaps =
{
"CentCommMain",
"CentCommHarmony",
"Dart",
"NukieOutpost"
};
private static readonly string[] Grids =
{
"/Maps/CentralCommand/main.yml",
"/Maps/CentralCommand/harmony.yml", // Harmony CC version
"/Maps/Shuttles/cargo.yml",
"/Maps/Shuttles/emergency.yml",
"/Maps/Shuttles/infiltrator.yml",
};
private static readonly string[] GameMaps =
{
"Dev",
"TestTeg",
"CentCommMain",
"CentCommHarmony",
"MeteorArena",
"NukieOutpost",
"Core",
"Pebble", //DeltaV
"Edge", //DeltaV
"Saltern",
"Shoukou", //DeltaV
"Tortuga", //DeltaV
"Arena", //DeltaV
"Asterisk", //DeltaV
"Glacier", //DeltaV
"TheHive", //DeltaV
"Hammurabi", //DeltaV
"Lighthouse", //DeltaV
"Submarine", //DeltaV
"Gax",
"DryDock", //WWDP
"Moose", //WWDP
"WhiteBox", //WWDP
"Rad",
"Europa",
"Meta",
"Box"
};
/// <summary>
/// Asserts that specific files have been saved as grids and not maps.
/// </summary>
[Test, TestCaseSource(nameof(Grids))]
public async Task GridsLoadableTest(string mapFile)
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var entManager = server.ResolveDependency<IEntityManager>();
var mapLoader = entManager.System<MapLoaderSystem>();
var mapSystem = entManager.System<SharedMapSystem>();
var mapManager = server.ResolveDependency<IMapManager>();
var cfg = server.ResolveDependency<IConfigurationManager>();
Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False);
await server.WaitPost(() =>
{
mapSystem.CreateMap(out var mapId);
try
{
#pragma warning disable NUnit2045
Assert.That(mapLoader.TryLoad(mapId, mapFile, out var roots));
Assert.That(roots.Where(uid => entManager.HasComponent<MapGridComponent>(uid)), Is.Not.Empty);
#pragma warning restore NUnit2045
}
catch (Exception ex)
{
throw new Exception($"Failed to load map {mapFile}, was it saved as a map instead of a grid?", ex);
}
try
{
mapManager.DeleteMap(mapId);
}
catch (Exception ex)
{
throw new Exception($"Failed to delete map {mapFile}", ex);
}
});
await server.WaitRunTicks(1);
await pair.CleanReturnAsync();
}
[Test]
public async Task NoSavedPostMapInitTest()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var resourceManager = server.ResolveDependency<IResourceManager>();
var mapFolder = new ResPath("/Maps");
var maps = resourceManager
.ContentFindFiles(mapFolder)
.Where(filePath => filePath.Extension == "yml" && !filePath.Filename.StartsWith(".", StringComparison.Ordinal))
.ToArray();
foreach (var map in maps)
{
var rootedPath = map.ToRootedPath();
// ReSharper disable once RedundantLogicalConditionalExpressionOperand
if (SkipTestMaps && rootedPath.ToString().StartsWith(TestMapsPath, StringComparison.Ordinal))
{
continue;
}
if (!resourceManager.TryContentFileRead(rootedPath, out var fileStream))
{
Assert.Fail($"Map not found: {rootedPath}");
}
using var reader = new StreamReader(fileStream);
var yamlStream = new YamlStream();
yamlStream.Load(reader);
var root = yamlStream.Documents[0].RootNode;
var meta = root["meta"];
var postMapInit = meta["postmapinit"].AsBool();
Assert.That(postMapInit, Is.False, $"Map {map.Filename} was saved postmapinit");
}
await pair.CleanReturnAsync();
}
[Test, TestCaseSource(nameof(GameMaps))]
public async Task GameMapsLoadableTest(string mapProto)
{
await using var pair = await PoolManager.GetServerClient(new PoolSettings
{
Dirty = true // Stations spawn a bunch of nullspace entities and maps like centcomm.
});
var server = pair.Server;
var mapManager = server.ResolveDependency<IMapManager>();
var entManager = server.ResolveDependency<IEntityManager>();
var mapLoader = entManager.System<MapLoaderSystem>();
var mapSystem = entManager.System<SharedMapSystem>();
var protoManager = server.ResolveDependency<IPrototypeManager>();
var ticker = entManager.EntitySysManager.GetEntitySystem<GameTicker>();
var shuttleSystem = entManager.EntitySysManager.GetEntitySystem<ShuttleSystem>();
var xformQuery = entManager.GetEntityQuery<TransformComponent>();
var cfg = server.ResolveDependency<IConfigurationManager>();
Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False);
await server.WaitPost(() =>
{
mapSystem.CreateMap(out var mapId);
try
{
ticker.LoadGameMap(protoManager.Index<GameMapPrototype>(mapProto), mapId, null);
}
catch (Exception ex)
{
throw new Exception($"Failed to load map {mapProto}", ex);
}
mapSystem.CreateMap(out var shuttleMap);
var largest = 0f;
EntityUid? targetGrid = null;
var memberQuery = entManager.GetEntityQuery<StationMemberComponent>();
var grids = mapManager.GetAllGrids(mapId).ToList();
var gridUids = grids.Select(o => o.Owner).ToList();
targetGrid = gridUids.First();
foreach (var grid in grids)
{
var gridEnt = grid.Owner;
if (!memberQuery.HasComponent(gridEnt))
continue;
var area = grid.Comp.LocalAABB.Width * grid.Comp.LocalAABB.Height;
if (area > largest)
{
largest = area;
targetGrid = gridEnt;
}
}
// Test shuttle can dock.
// This is done inside gamemap test because loading the map takes ages and we already have it.
var station = entManager.GetComponent<StationMemberComponent>(targetGrid!.Value).Station;
if (entManager.TryGetComponent<StationEmergencyShuttleComponent>(station, out var stationEvac))
{
var shuttlePath = stationEvac.EmergencyShuttlePath;
#pragma warning disable NUnit2045
Assert.That(mapLoader.TryLoad(shuttleMap, shuttlePath.ToString(), out var roots));
EntityUid shuttle = default!;
Assert.DoesNotThrow(() =>
{
shuttle = roots.First(uid => entManager.HasComponent<MapGridComponent>(uid));
}, $"Failed to load {shuttlePath}");
Assert.That(
shuttleSystem.TryFTLDock(shuttle,
entManager.GetComponent<ShuttleComponent>(shuttle), targetGrid.Value),
$"Unable to dock {shuttlePath} to {mapProto}");
#pragma warning restore NUnit2045
}
mapManager.DeleteMap(shuttleMap);
if (entManager.HasComponent<StationJobsComponent>(station))
{
// Test that the map has valid latejoin spawn points or container spawn points
if (!NoSpawnMaps.Contains(mapProto))
{
var lateSpawns = 0;
lateSpawns += GetCountLateSpawn<SpawnPointComponent>(gridUids, entManager);
lateSpawns += GetCountLateSpawn<ContainerSpawnPointComponent>(gridUids, entManager);
Assert.That(lateSpawns, Is.GreaterThan(0), $"Found no latejoin spawn points on {mapProto}");
}
var comp = entManager.GetComponent<StationJobsComponent>(station);
var jobs = new HashSet<string>(comp.SetupAvailableJobs.Keys);
// Test all availableJobs have spawnPoints
// This is done inside gamemap test because loading the map takes ages and we already have it.
var spawnPoints = entManager.EntityQuery<SpawnPointComponent>()
.Where(x => x.SpawnType == SpawnPointType.Job)
.Select(x => x.Job!.ID);
jobs.ExceptWith(spawnPoints);
foreach (var jobId in jobs)
{
var exists = protoManager.TryIndex<JobPrototype>(jobId, out var jobPrototype);
if (!exists)
continue;
if (jobPrototype.JobEntity != null)
jobs.Remove(jobId);
}
Assert.That(jobs, Is.Empty, $"There is no spawnpoints for {string.Join(", ", jobs)} on {mapProto}.");
}
try
{
mapManager.DeleteMap(mapId);
}
catch (Exception ex)
{
throw new Exception($"Failed to delete map {mapProto}", ex);
}
});
await server.WaitRunTicks(1);
await pair.CleanReturnAsync();
}
private static int GetCountLateSpawn<T>(List<EntityUid> gridUids, IEntityManager entManager)
where T : ISpawnPoint, IComponent
{
var resultCount = 0;
var queryPoint = entManager.AllEntityQueryEnumerator<T, TransformComponent>();
#nullable enable
while (queryPoint.MoveNext(out T? comp, out var xform))
{
var spawner = (ISpawnPoint) comp;
if (spawner.SpawnType is not SpawnPointType.LateJoin
|| xform.GridUid == null
|| !gridUids.Contains(xform.GridUid.Value))
{
continue;
}
#nullable disable
resultCount++;
break;
}
return resultCount;
}
[Test]
public async Task AllMapsTested()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var protoMan = server.ResolveDependency<IPrototypeManager>();
var gameMaps = protoMan.EnumeratePrototypes<GameMapPrototype>()
.Where(x => !pair.IsTestPrototype(x))
.Select(x => x.ID)
.ToHashSet();
Assert.That(gameMaps.Remove(PoolManager.TestMap));
Assert.That(gameMaps, Is.EquivalentTo(GameMaps.ToHashSet()), "Game map prototype missing from test cases.");
await pair.CleanReturnAsync();
}
[Test]
public async Task NonGameMapsLoadableTest()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var mapLoader = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<MapLoaderSystem>();
var mapManager = server.ResolveDependency<IMapManager>();
var resourceManager = server.ResolveDependency<IResourceManager>();
var protoManager = server.ResolveDependency<IPrototypeManager>();
var cfg = server.ResolveDependency<IConfigurationManager>();
var mapSystem = server.System<SharedMapSystem>();
Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False);
var gameMaps = protoManager.EnumeratePrototypes<GameMapPrototype>().Select(o => o.MapPath).ToHashSet();
var mapFolder = new ResPath("/Maps");
var maps = resourceManager
.ContentFindFiles(mapFolder)
.Where(filePath => filePath.Extension == "yml" && !filePath.Filename.StartsWith(".", StringComparison.Ordinal))
.ToArray();
var mapNames = new List<string>();
foreach (var map in maps)
{
if (gameMaps.Contains(map))
continue;
var rootedPath = map.ToRootedPath();
if (SkipTestMaps && rootedPath.ToString().StartsWith(TestMapsPath, StringComparison.Ordinal))
{
continue;
}
mapNames.Add(rootedPath.ToString());
}
await server.WaitPost(() =>
{
Assert.Multiple(() =>
{
foreach (var mapName in mapNames)
{
mapSystem.CreateMap(out var mapId);
try
{
Assert.That(mapLoader.TryLoad(mapId, mapName, out _));
}
catch (Exception ex)
{
throw new Exception($"Failed to load map {mapName}", ex);
}
try
{
mapManager.DeleteMap(mapId);
}
catch (Exception ex)
{
throw new Exception($"Failed to delete map {mapName}", ex);
}
}
});
});
await server.WaitRunTicks(1);
await pair.CleanReturnAsync();
}
}
}