Refactor map loading & saving (#34020)
This commit is contained in:
@@ -11,6 +11,8 @@ using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.EntitySerialization.Systems;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Body
|
||||
{
|
||||
@@ -57,7 +59,6 @@ namespace Content.IntegrationTests.Tests.Body
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||
var mapLoader = entityManager.System<MapLoaderSystem>();
|
||||
var mapSys = entityManager.System<SharedMapSystem>();
|
||||
@@ -69,17 +70,13 @@ namespace Content.IntegrationTests.Tests.Body
|
||||
GridAtmosphereComponent relevantAtmos = default;
|
||||
var startingMoles = 0.0f;
|
||||
|
||||
var testMapName = "Maps/Test/Breathing/3by3-20oxy-80nit.yml";
|
||||
var testMapName = new ResPath("Maps/Test/Breathing/3by3-20oxy-80nit.yml");
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
mapSys.CreateMap(out var mapId);
|
||||
Assert.That(mapLoader.TryLoad(mapId, testMapName, out var roots));
|
||||
|
||||
var query = entityManager.GetEntityQuery<MapGridComponent>();
|
||||
var grids = roots.Where(x => query.HasComponent(x));
|
||||
Assert.That(grids, Is.Not.Empty);
|
||||
grid = grids.First();
|
||||
Assert.That(mapLoader.TryLoadGrid(mapId, testMapName, out var gridEnt));
|
||||
grid = gridEnt!.Value.Owner;
|
||||
});
|
||||
|
||||
Assert.That(grid, Is.Not.Null, $"Test blueprint {testMapName} not found.");
|
||||
@@ -148,18 +145,13 @@ namespace Content.IntegrationTests.Tests.Body
|
||||
RespiratorComponent respirator = null;
|
||||
EntityUid human = default;
|
||||
|
||||
var testMapName = "Maps/Test/Breathing/3by3-20oxy-80nit.yml";
|
||||
var testMapName = new ResPath("Maps/Test/Breathing/3by3-20oxy-80nit.yml");
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
mapSys.CreateMap(out var mapId);
|
||||
|
||||
Assert.That(mapLoader.TryLoad(mapId, testMapName, out var ents), Is.True);
|
||||
var query = entityManager.GetEntityQuery<MapGridComponent>();
|
||||
grid = ents
|
||||
.Select<EntityUid, EntityUid?>(x => x)
|
||||
.FirstOrDefault((uid) => uid.HasValue && query.HasComponent(uid.Value), null);
|
||||
Assert.That(grid, Is.Not.Null);
|
||||
Assert.That(mapLoader.TryLoadGrid(mapId, testMapName, out var gridEnt));
|
||||
grid = gridEnt!.Value.Owner;
|
||||
});
|
||||
|
||||
Assert.That(grid, Is.Not.Null, $"Test blueprint {testMapName} not found.");
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Systems;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.EntitySerialization.Systems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Body;
|
||||
|
||||
@@ -111,13 +112,12 @@ public sealed class SaveLoadReparentTest
|
||||
Is.Not.Empty
|
||||
);
|
||||
|
||||
const string mapPath = $"/{nameof(SaveLoadReparentTest)}{nameof(Test)}map.yml";
|
||||
var mapPath = new ResPath($"/{nameof(SaveLoadReparentTest)}{nameof(Test)}map.yml");
|
||||
|
||||
mapLoader.SaveMap(mapId, mapPath);
|
||||
maps.DeleteMap(mapId);
|
||||
Assert.That(mapLoader.TrySaveMap(mapId, mapPath));
|
||||
mapSys.DeleteMap(mapId);
|
||||
|
||||
mapSys.CreateMap(out mapId);
|
||||
Assert.That(mapLoader.TryLoad(mapId, mapPath, out _), Is.True);
|
||||
Assert.That(mapLoader.TryLoadMap(mapPath, out var map, out _), Is.True);
|
||||
|
||||
var query = EnumerateQueryEnumerator(
|
||||
entities.EntityQueryEnumerator<BodyComponent>()
|
||||
@@ -173,7 +173,7 @@ public sealed class SaveLoadReparentTest
|
||||
});
|
||||
}
|
||||
|
||||
maps.DeleteMap(mapId);
|
||||
entities.DeleteEntity(map);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#nullable enable
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Minds;
|
||||
@@ -37,8 +38,8 @@ public sealed partial class MindTests
|
||||
Assert.That(pair.Client.EntMan.EntityCount, Is.EqualTo(0));
|
||||
|
||||
// Create a new map.
|
||||
int mapId = 1;
|
||||
await pair.Server.WaitPost(() => conHost.ExecuteCommand($"addmap {mapId}"));
|
||||
MapId mapId = default;
|
||||
await pair.Server.WaitPost(() => pair.Server.System<SharedMapSystem>().CreateMap(out mapId));
|
||||
await pair.RunTicksSync(5);
|
||||
|
||||
// Client is not attached to anything
|
||||
@@ -54,7 +55,7 @@ public sealed partial class MindTests
|
||||
Assert.That(pair.Client.EntMan.EntityExists(pair.Client.AttachedEntity));
|
||||
Assert.That(pair.Server.EntMan.EntityExists(pair.PlayerData?.Mind));
|
||||
var xform = pair.Client.Transform(pair.Client.AttachedEntity!.Value);
|
||||
Assert.That(xform.MapID, Is.EqualTo(new MapId(mapId)));
|
||||
Assert.That(xform.MapID, Is.EqualTo(mapId));
|
||||
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ 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;
|
||||
@@ -17,6 +16,9 @@ using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Content.Shared.Station.Components;
|
||||
using Robust.Shared.EntitySerialization;
|
||||
using Robust.Shared.EntitySerialization.Systems;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Utility;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
|
||||
@@ -36,10 +38,7 @@ namespace Content.IntegrationTests.Tests
|
||||
|
||||
private static readonly string[] Grids =
|
||||
{
|
||||
"/Maps/centcomm.yml",
|
||||
"/Maps/Shuttles/cargo.yml",
|
||||
"/Maps/Shuttles/emergency.yml",
|
||||
"/Maps/Shuttles/infiltrator.yml",
|
||||
"/Maps/centcomm.yml"
|
||||
};
|
||||
|
||||
private static readonly string[] GameMaps =
|
||||
@@ -81,33 +80,72 @@ namespace Content.IntegrationTests.Tests
|
||||
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);
|
||||
var path = new ResPath(mapFile);
|
||||
|
||||
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
|
||||
Assert.That(mapLoader.TryLoadGrid(mapId, path, out var grid));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Failed to load map {mapFile}, was it saved as a map instead of a grid?", ex);
|
||||
}
|
||||
|
||||
try
|
||||
mapSystem.DeleteMap(mapId);
|
||||
});
|
||||
await server.WaitRunTicks(1);
|
||||
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asserts that shuttles are loadable and have been saved as grids and not maps.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ShuttlesLoadableTest()
|
||||
{
|
||||
await using var pair = await PoolManager.GetServerClient();
|
||||
var server = pair.Server;
|
||||
|
||||
var entManager = server.ResolveDependency<IEntityManager>();
|
||||
var resMan = server.ResolveDependency<IResourceManager>();
|
||||
var mapLoader = entManager.System<MapLoaderSystem>();
|
||||
var mapSystem = entManager.System<SharedMapSystem>();
|
||||
var cfg = server.ResolveDependency<IConfigurationManager>();
|
||||
Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False);
|
||||
|
||||
var shuttleFolder = new ResPath("/Maps/Shuttles");
|
||||
var shuttles = resMan
|
||||
.ContentFindFiles(shuttleFolder)
|
||||
.Where(filePath =>
|
||||
filePath.Extension == "yml" && !filePath.Filename.StartsWith(".", StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
mapManager.DeleteMap(mapId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Failed to delete map {mapFile}", ex);
|
||||
}
|
||||
foreach (var path in shuttles)
|
||||
{
|
||||
mapSystem.CreateMap(out var mapId);
|
||||
try
|
||||
{
|
||||
Assert.That(mapLoader.TryLoadGrid(mapId, path, out _),
|
||||
$"Failed to load shuttle {path}, was it saved as a map instead of a grid?");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Failed to load shuttle {path}, was it saved as a map instead of a grid?",
|
||||
ex);
|
||||
}
|
||||
mapSystem.DeleteMap(mapId);
|
||||
}
|
||||
});
|
||||
});
|
||||
await server.WaitRunTicks(1);
|
||||
|
||||
@@ -121,12 +159,15 @@ namespace Content.IntegrationTests.Tests
|
||||
var server = pair.Server;
|
||||
|
||||
var resourceManager = server.ResolveDependency<IResourceManager>();
|
||||
var loader = server.System<MapLoaderSystem>();
|
||||
|
||||
var mapFolder = new ResPath("/Maps");
|
||||
var maps = resourceManager
|
||||
.ContentFindFiles(mapFolder)
|
||||
.Where(filePath => filePath.Extension == "yml" && !filePath.Filename.StartsWith(".", StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
|
||||
var v7Maps = new List<ResPath>();
|
||||
foreach (var map in maps)
|
||||
{
|
||||
var rootedPath = map.ToRootedPath();
|
||||
@@ -149,13 +190,69 @@ namespace Content.IntegrationTests.Tests
|
||||
|
||||
var root = yamlStream.Documents[0].RootNode;
|
||||
var meta = root["meta"];
|
||||
var postMapInit = meta["postmapinit"].AsBool();
|
||||
var version = meta["format"].AsInt();
|
||||
|
||||
if (version >= 7)
|
||||
{
|
||||
v7Maps.Add(map);
|
||||
continue;
|
||||
}
|
||||
|
||||
var postMapInit = meta["postmapinit"].AsBool();
|
||||
Assert.That(postMapInit, Is.False, $"Map {map.Filename} was saved postmapinit");
|
||||
}
|
||||
|
||||
var deps = server.ResolveDependency<IEntitySystemManager>().DependencyCollection;
|
||||
foreach (var map in v7Maps)
|
||||
{
|
||||
Assert.That(IsPreInit(map, loader, deps));
|
||||
}
|
||||
|
||||
// Check that the test actually does manage to catch post-init maps and isn't just blindly passing everything.
|
||||
// To that end, create a new post-init map and try verify it.
|
||||
var mapSys = server.System<SharedMapSystem>();
|
||||
MapId id = default;
|
||||
await server.WaitPost(() => mapSys.CreateMap(out id, runMapInit: false));
|
||||
await server.WaitPost(() => server.EntMan.Spawn(null, new MapCoordinates(0, 0, id)));
|
||||
|
||||
// First check that a pre-init version passes
|
||||
var path = new ResPath($"{nameof(NoSavedPostMapInitTest)}.yml");
|
||||
Assert.That(loader.TrySaveMap(id, path));
|
||||
Assert.That(IsPreInit(path, loader, deps));
|
||||
|
||||
// and the post-init version fails.
|
||||
await server.WaitPost(() => mapSys.InitializeMap(id));
|
||||
Assert.That(loader.TrySaveMap(id, path));
|
||||
Assert.That(IsPreInit(path, loader, deps), Is.False);
|
||||
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
|
||||
private bool IsPreInit(ResPath map, MapLoaderSystem loader, IDependencyCollection deps)
|
||||
{
|
||||
if (!loader.TryReadFile(map, out var data))
|
||||
{
|
||||
Assert.Fail($"Failed to read {map}");
|
||||
return false;
|
||||
}
|
||||
|
||||
var reader = new EntityDeserializer(deps, data, DeserializationOptions.Default);
|
||||
if (!reader.TryProcessData())
|
||||
{
|
||||
Assert.Fail($"Failed to process {map}");
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var mapId in reader.MapYamlIds)
|
||||
{
|
||||
var mapData = reader.YamlEntities[mapId];
|
||||
if (mapData.PostInit)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[Test, TestCaseSource(nameof(GameMaps))]
|
||||
public async Task GameMapsLoadableTest(string mapProto)
|
||||
{
|
||||
@@ -172,16 +269,16 @@ namespace Content.IntegrationTests.Tests
|
||||
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);
|
||||
MapId mapId;
|
||||
try
|
||||
{
|
||||
ticker.LoadGameMap(protoManager.Index<GameMapPrototype>(mapProto), mapId, null);
|
||||
var opts = DeserializationOptions.Default with {InitializeMaps = true};
|
||||
ticker.LoadGameMap(protoManager.Index<GameMapPrototype>(mapProto), out mapId, opts);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -218,21 +315,17 @@ namespace Content.IntegrationTests.Tests
|
||||
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(mapLoader.TryLoadGrid(shuttleMap, shuttlePath, out var shuttle),
|
||||
$"Failed to load {shuttlePath}");
|
||||
|
||||
Assert.That(
|
||||
shuttleSystem.TryFTLDock(shuttle,
|
||||
entManager.GetComponent<ShuttleComponent>(shuttle), targetGrid.Value),
|
||||
shuttleSystem.TryFTLDock(shuttle!.Value.Owner,
|
||||
entManager.GetComponent<ShuttleComponent>(shuttle!.Value.Owner),
|
||||
targetGrid.Value),
|
||||
$"Unable to dock {shuttlePath} to {mapProto}");
|
||||
#pragma warning restore NUnit2045
|
||||
}
|
||||
|
||||
mapManager.DeleteMap(shuttleMap);
|
||||
mapSystem.DeleteMap(shuttleMap);
|
||||
|
||||
if (entManager.HasComponent<StationJobsComponent>(station))
|
||||
{
|
||||
@@ -269,7 +362,7 @@ namespace Content.IntegrationTests.Tests
|
||||
|
||||
try
|
||||
{
|
||||
mapManager.DeleteMap(mapId);
|
||||
mapSystem.DeleteMap(mapId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -333,11 +426,9 @@ namespace Content.IntegrationTests.Tests
|
||||
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();
|
||||
@@ -348,7 +439,7 @@ namespace Content.IntegrationTests.Tests
|
||||
.Where(filePath => filePath.Extension == "yml" && !filePath.Filename.StartsWith(".", StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
|
||||
var mapNames = new List<string>();
|
||||
var mapPaths = new List<ResPath>();
|
||||
foreach (var map in maps)
|
||||
{
|
||||
if (gameMaps.Contains(map))
|
||||
@@ -359,32 +450,46 @@ namespace Content.IntegrationTests.Tests
|
||||
{
|
||||
continue;
|
||||
}
|
||||
mapNames.Add(rootedPath.ToString());
|
||||
mapPaths.Add(rootedPath);
|
||||
}
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
foreach (var mapName in mapNames)
|
||||
// This bunch of files contains a random mixture of both map and grid files.
|
||||
// TODO MAPPING organize files
|
||||
var opts = MapLoadOptions.Default with
|
||||
{
|
||||
DeserializationOptions = DeserializationOptions.Default with
|
||||
{
|
||||
InitializeMaps = true,
|
||||
LogOrphanedGrids = false
|
||||
}
|
||||
};
|
||||
|
||||
HashSet<Entity<MapComponent>> maps;
|
||||
foreach (var path in mapPaths)
|
||||
{
|
||||
mapSystem.CreateMap(out var mapId);
|
||||
try
|
||||
{
|
||||
Assert.That(mapLoader.TryLoad(mapId, mapName, out _));
|
||||
Assert.That(mapLoader.TryLoadGeneric(path, out maps, out _, opts));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Failed to load map {mapName}", ex);
|
||||
throw new Exception($"Failed to load map {path}", ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
mapManager.DeleteMap(mapId);
|
||||
foreach (var map in maps)
|
||||
{
|
||||
server.EntMan.DeleteEntity(map);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Failed to delete map {mapName}", ex);
|
||||
throw new Exception($"Failed to delete map {path}", ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Salvage;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.EntitySerialization.Systems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.IntegrationTests.Tests;
|
||||
@@ -24,7 +21,6 @@ public sealed class SalvageTest
|
||||
|
||||
var entManager = server.ResolveDependency<IEntityManager>();
|
||||
var mapLoader = entManager.System<MapLoaderSystem>();
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
|
||||
var cfg = server.ResolveDependency<IConfigurationManager>();
|
||||
var mapSystem = entManager.System<SharedMapSystem>();
|
||||
@@ -34,13 +30,10 @@ public sealed class SalvageTest
|
||||
{
|
||||
foreach (var salvage in prototypeManager.EnumeratePrototypes<SalvageMapPrototype>())
|
||||
{
|
||||
var mapFile = salvage.MapPath;
|
||||
|
||||
mapSystem.CreateMap(out var mapId);
|
||||
try
|
||||
{
|
||||
Assert.That(mapLoader.TryLoad(mapId, mapFile.ToString(), out var roots));
|
||||
Assert.That(roots.Where(uid => entManager.HasComponent<MapGridComponent>(uid)), Is.Not.Empty);
|
||||
Assert.That(mapLoader.TryLoadGrid(mapId, salvage.MapPath, out var grid));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -49,7 +42,7 @@ public sealed class SalvageTest
|
||||
|
||||
try
|
||||
{
|
||||
mapManager.DeleteMap(mapId);
|
||||
mapSystem.DeleteMap(mapId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using Content.Shared.CCVar;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.EntitySerialization.Systems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -16,7 +17,7 @@ namespace Content.IntegrationTests.Tests
|
||||
[Test]
|
||||
public async Task SaveLoadMultiGridMap()
|
||||
{
|
||||
const string mapPath = @"/Maps/Test/TestMap.yml";
|
||||
var mapPath = new ResPath("/Maps/Test/TestMap.yml");
|
||||
|
||||
await using var pair = await PoolManager.GetServerClient();
|
||||
var server = pair.Server;
|
||||
@@ -31,7 +32,7 @@ namespace Content.IntegrationTests.Tests
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
var dir = new ResPath(mapPath).Directory;
|
||||
var dir = mapPath.Directory;
|
||||
resManager.UserData.CreateDir(dir);
|
||||
|
||||
mapSystem.CreateMap(out var mapId);
|
||||
@@ -47,15 +48,17 @@ namespace Content.IntegrationTests.Tests
|
||||
mapSystem.SetTile(mapGrid, new Vector2i(0, 0), new Tile(typeId: 2, flags: 1, variant: 254));
|
||||
}
|
||||
|
||||
Assert.Multiple(() => mapLoader.SaveMap(mapId, mapPath));
|
||||
Assert.Multiple(() => mapManager.DeleteMap(mapId));
|
||||
Assert.That(mapLoader.TrySaveMap(mapId, mapPath));
|
||||
mapSystem.DeleteMap(mapId);
|
||||
});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
|
||||
MapId newMap = default;
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
Assert.That(mapLoader.TryLoad(new MapId(10), mapPath, out _));
|
||||
Assert.That(mapLoader.TryLoadMap(mapPath, out var map, out _));
|
||||
newMap = map!.Value.Comp.MapId;
|
||||
});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
@@ -63,7 +66,7 @@ namespace Content.IntegrationTests.Tests
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
{
|
||||
if (!mapManager.TryFindGridAt(new MapId(10), new Vector2(10, 10), out var gridUid, out var mapGrid) ||
|
||||
if (!mapManager.TryFindGridAt(newMap, new Vector2(10, 10), out var gridUid, out var mapGrid) ||
|
||||
!sEntities.TryGetComponent<TransformComponent>(gridUid, out var gridXform))
|
||||
{
|
||||
Assert.Fail();
|
||||
@@ -77,7 +80,7 @@ namespace Content.IntegrationTests.Tests
|
||||
});
|
||||
}
|
||||
{
|
||||
if (!mapManager.TryFindGridAt(new MapId(10), new Vector2(-8, -8), out var gridUid, out var mapGrid) ||
|
||||
if (!mapManager.TryFindGridAt(newMap, new Vector2(-8, -8), out var gridUid, out var mapGrid) ||
|
||||
!sEntities.TryGetComponent<TransformComponent>(gridUid, out var gridXform))
|
||||
{
|
||||
Assert.Fail();
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Maps;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.EntitySerialization.Systems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Map.Events;
|
||||
using Robust.Shared.Serialization.Markdown.Mapping;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.IntegrationTests.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests that a map's yaml does not change when saved consecutively.
|
||||
/// Tests that a grid's yaml does not change when saved consecutively.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public sealed class SaveLoadSaveTest
|
||||
{
|
||||
[Test]
|
||||
public async Task SaveLoadSave()
|
||||
public async Task CreateSaveLoadSaveGrid()
|
||||
{
|
||||
await using var pair = await PoolManager.GetServerClient();
|
||||
var server = pair.Server;
|
||||
@@ -30,22 +30,21 @@ namespace Content.IntegrationTests.Tests
|
||||
var cfg = server.ResolveDependency<IConfigurationManager>();
|
||||
Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False);
|
||||
|
||||
var testSystem = server.System<SaveLoadSaveTestSystem>();
|
||||
testSystem.Enabled = true;
|
||||
|
||||
var rp1 = new ResPath("/save load save 1.yml");
|
||||
var rp2 = new ResPath("/save load save 2.yml");
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
mapSystem.CreateMap(out var mapId0);
|
||||
// TODO: Properly find the "main" station grid.
|
||||
var grid0 = mapManager.CreateGridEntity(mapId0);
|
||||
mapLoader.Save(grid0.Owner, "save load save 1.yml");
|
||||
entManager.RunMapInit(grid0.Owner, entManager.GetComponent<MetaDataComponent>(grid0));
|
||||
Assert.That(mapLoader.TrySaveGrid(grid0.Owner, rp1));
|
||||
mapSystem.CreateMap(out var mapId1);
|
||||
EntityUid grid1 = default!;
|
||||
#pragma warning disable NUnit2045
|
||||
Assert.That(mapLoader.TryLoad(mapId1, "save load save 1.yml", out var roots, new MapLoadOptions() { LoadMap = false }), $"Failed to load test map {TestMap}");
|
||||
Assert.DoesNotThrow(() =>
|
||||
{
|
||||
grid1 = roots.First(uid => entManager.HasComponent<MapGridComponent>(uid));
|
||||
});
|
||||
#pragma warning restore NUnit2045
|
||||
mapLoader.Save(grid1, "save load save 2.yml");
|
||||
Assert.That(mapLoader.TryLoadGrid(mapId1, rp1, out var grid1));
|
||||
Assert.That(mapLoader.TrySaveGrid(grid1!.Value, rp2));
|
||||
});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
@@ -54,14 +53,12 @@ namespace Content.IntegrationTests.Tests
|
||||
string one;
|
||||
string two;
|
||||
|
||||
var rp1 = new ResPath("/save load save 1.yml");
|
||||
await using (var stream = userData.Open(rp1, FileMode.Open))
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
one = await reader.ReadToEndAsync();
|
||||
}
|
||||
|
||||
var rp2 = new ResPath("/save load save 2.yml");
|
||||
await using (var stream = userData.Open(rp2, FileMode.Open))
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
@@ -87,6 +84,7 @@ namespace Content.IntegrationTests.Tests
|
||||
TestContext.Error.WriteLine(twoTmp);
|
||||
}
|
||||
});
|
||||
testSystem.Enabled = false;
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
|
||||
@@ -101,8 +99,12 @@ namespace Content.IntegrationTests.Tests
|
||||
await using var pair = await PoolManager.GetServerClient();
|
||||
var server = pair.Server;
|
||||
var mapLoader = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<MapLoaderSystem>();
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var mapSystem = server.System<SharedMapSystem>();
|
||||
var mapSys = server.System<SharedMapSystem>();
|
||||
var testSystem = server.System<SaveLoadSaveTestSystem>();
|
||||
testSystem.Enabled = true;
|
||||
|
||||
var rp1 = new ResPath("/load save ticks save 1.yml");
|
||||
var rp2 = new ResPath("/load save ticks save 2.yml");
|
||||
|
||||
MapId mapId = default;
|
||||
var cfg = server.ResolveDependency<IConfigurationManager>();
|
||||
@@ -111,10 +113,10 @@ namespace Content.IntegrationTests.Tests
|
||||
// Load bagel.yml as uninitialized map, and save it to ensure it's up to date.
|
||||
server.Post(() =>
|
||||
{
|
||||
mapSystem.CreateMap(out mapId, runMapInit: false);
|
||||
mapManager.SetMapPaused(mapId, true);
|
||||
Assert.That(mapLoader.TryLoad(mapId, TestMap, out _), $"Failed to load test map {TestMap}");
|
||||
mapLoader.SaveMap(mapId, "load save ticks save 1.yml");
|
||||
var path = new ResPath(TestMap);
|
||||
Assert.That(mapLoader.TryLoadMap(path, out var map, out _), $"Failed to load test map {TestMap}");
|
||||
mapId = map!.Value.Comp.MapId;
|
||||
Assert.That(mapLoader.TrySaveMap(mapId, rp1));
|
||||
});
|
||||
|
||||
// Run 5 ticks.
|
||||
@@ -122,7 +124,7 @@ namespace Content.IntegrationTests.Tests
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
mapLoader.SaveMap(mapId, "/load save ticks save 2.yml");
|
||||
Assert.That(mapLoader.TrySaveMap(mapId, rp2));
|
||||
});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
@@ -131,13 +133,13 @@ namespace Content.IntegrationTests.Tests
|
||||
string one;
|
||||
string two;
|
||||
|
||||
await using (var stream = userData.Open(new ResPath("/load save ticks save 1.yml"), FileMode.Open))
|
||||
await using (var stream = userData.Open(rp1, FileMode.Open))
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
one = await reader.ReadToEndAsync();
|
||||
}
|
||||
|
||||
await using (var stream = userData.Open(new ResPath("/load save ticks save 2.yml"), FileMode.Open))
|
||||
await using (var stream = userData.Open(rp2, FileMode.Open))
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
two = await reader.ReadToEndAsync();
|
||||
@@ -163,7 +165,8 @@ namespace Content.IntegrationTests.Tests
|
||||
}
|
||||
});
|
||||
|
||||
await server.WaitPost(() => mapManager.DeleteMap(mapId));
|
||||
testSystem.Enabled = false;
|
||||
await server.WaitPost(() => mapSys.DeleteMap(mapId));
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
|
||||
@@ -184,29 +187,31 @@ namespace Content.IntegrationTests.Tests
|
||||
var server = pair.Server;
|
||||
|
||||
var mapLoader = server.System<MapLoaderSystem>();
|
||||
var mapSystem = server.System<SharedMapSystem>();
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var mapSys = server.System<SharedMapSystem>();
|
||||
var userData = server.ResolveDependency<IResourceManager>().UserData;
|
||||
var cfg = server.ResolveDependency<IConfigurationManager>();
|
||||
Assert.That(cfg.GetCVar(CCVars.GridFill), Is.False);
|
||||
var testSystem = server.System<SaveLoadSaveTestSystem>();
|
||||
testSystem.Enabled = true;
|
||||
|
||||
MapId mapId = default;
|
||||
const string fileA = "/load tick load a.yml";
|
||||
const string fileB = "/load tick load b.yml";
|
||||
MapId mapId1 = default;
|
||||
MapId mapId2 = default;
|
||||
var fileA = new ResPath("/load tick load a.yml");
|
||||
var fileB = new ResPath("/load tick load b.yml");
|
||||
string yamlA;
|
||||
string yamlB;
|
||||
|
||||
// Load & save the first map
|
||||
server.Post(() =>
|
||||
{
|
||||
mapSystem.CreateMap(out mapId, runMapInit: false);
|
||||
mapManager.SetMapPaused(mapId, true);
|
||||
Assert.That(mapLoader.TryLoad(mapId, TestMap, out _), $"Failed to load test map {TestMap}");
|
||||
mapLoader.SaveMap(mapId, fileA);
|
||||
var path = new ResPath(TestMap);
|
||||
Assert.That(mapLoader.TryLoadMap(path, out var map, out _), $"Failed to load test map {TestMap}");
|
||||
mapId1 = map!.Value.Comp.MapId;
|
||||
Assert.That(mapLoader.TrySaveMap(mapId1, fileA));
|
||||
});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
await using (var stream = userData.Open(new ResPath(fileA), FileMode.Open))
|
||||
await using (var stream = userData.Open(fileA, FileMode.Open))
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
yamlA = await reader.ReadToEndAsync();
|
||||
@@ -217,16 +222,15 @@ namespace Content.IntegrationTests.Tests
|
||||
// Load & save the second map
|
||||
server.Post(() =>
|
||||
{
|
||||
mapManager.DeleteMap(mapId);
|
||||
mapSystem.CreateMap(out mapId, runMapInit: false);
|
||||
mapManager.SetMapPaused(mapId, true);
|
||||
Assert.That(mapLoader.TryLoad(mapId, TestMap, out _), $"Failed to load test map {TestMap}");
|
||||
mapLoader.SaveMap(mapId, fileB);
|
||||
var path = new ResPath(TestMap);
|
||||
Assert.That(mapLoader.TryLoadMap(path, out var map, out _), $"Failed to load test map {TestMap}");
|
||||
mapId2 = map!.Value.Comp.MapId;
|
||||
Assert.That(mapLoader.TrySaveMap(mapId2, fileB));
|
||||
});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
|
||||
await using (var stream = userData.Open(new ResPath(fileB), FileMode.Open))
|
||||
await using (var stream = userData.Open(fileB, FileMode.Open))
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
yamlB = await reader.ReadToEndAsync();
|
||||
@@ -234,8 +238,32 @@ namespace Content.IntegrationTests.Tests
|
||||
|
||||
Assert.That(yamlA, Is.EqualTo(yamlB));
|
||||
|
||||
await server.WaitPost(() => mapManager.DeleteMap(mapId));
|
||||
testSystem.Enabled = false;
|
||||
await server.WaitPost(() => mapSys.DeleteMap(mapId1));
|
||||
await server.WaitPost(() => mapSys.DeleteMap(mapId2));
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple system that modifies the data saved to a yaml file by removing the timestamp.
|
||||
/// Required by some tests that validate that re-saving a map does not modify it.
|
||||
/// </summary>
|
||||
private sealed class SaveLoadSaveTestSystem : EntitySystem
|
||||
{
|
||||
public bool Enabled;
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<AfterSerializationEvent>(OnAfterSave);
|
||||
}
|
||||
|
||||
private void OnAfterSave(AfterSerializationEvent ev)
|
||||
{
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
// Remove timestamp.
|
||||
((MappingDataNode)ev.Node["meta"]).Remove("time");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,12 @@ using System.Numerics;
|
||||
using Content.Server.Shuttles.Systems;
|
||||
using Content.Tests;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.EntitySerialization.Systems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Shuttle;
|
||||
|
||||
@@ -106,8 +108,9 @@ public sealed class DockTest : ContentUnitTest
|
||||
{
|
||||
mapGrid = entManager.AddComponent<MapGridComponent>(map.MapUid);
|
||||
entManager.DeleteEntity(map.Grid);
|
||||
Assert.That(entManager.System<MapLoaderSystem>().TryLoad(otherMap.MapId, "/Maps/Shuttles/emergency.yml", out var rootUids));
|
||||
shuttle = rootUids[0];
|
||||
var path = new ResPath("/Maps/Shuttles/emergency.yml");
|
||||
Assert.That(entManager.System<MapLoaderSystem>().TryLoadGrid(otherMap.MapId, path, out var grid));
|
||||
shuttle = grid!.Value.Owner;
|
||||
|
||||
var dockingConfig = dockingSystem.GetDockingConfig(shuttle, map.MapUid);
|
||||
Assert.That(dockingConfig, Is.EqualTo(null));
|
||||
|
||||
Reference in New Issue
Block a user