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
{
await server.WaitIdleAsync();
- var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var mapLoader = entityManager.System<MapLoaderSystem>();
var mapSys = entityManager.System<SharedMapSystem>();
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.");
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.");
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;
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);
+ 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>()
});
}
- maps.DeleteMap(mapId);
+ entities.DeleteEntity(map);
}
});
#nullable enable
using Robust.Shared.Console;
+using Robust.Shared.GameObjects;
using Robust.Shared.Map;
namespace Content.IntegrationTests.Tests.Minds;
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
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();
}
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.Components;
using Robust.Shared.Prototypes;
using Content.Shared.Station.Components;
-using FastAccessors;
+using Robust.Shared.EntitySerialization;
+using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.Utility;
using YamlDotNet.RepresentationModel;
"Amber",
"Loop"
-
+
};
/// <summary>
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
- {
- mapManager.DeleteMap(mapId);
- }
- catch (Exception ex)
- {
- throw new Exception($"Failed to delete map {mapFile}", ex);
- }
+ mapSystem.DeleteMap(mapId);
});
await server.WaitRunTicks(1);
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)
{
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))
{
try
{
- mapManager.DeleteMap(mapId);
+ mapSystem.DeleteMap(mapId);
}
catch (Exception ex)
{
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();
.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))
{
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.TryLoadEntities(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);
}
}
});
-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;
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>();
{
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)
{
try
{
- mapManager.DeleteMap(mapId);
+ mapSystem.DeleteMap(mapId);
}
catch (Exception ex)
{
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;
[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;
await server.WaitAssertion(() =>
{
- var dir = new ResPath(mapPath).Directory;
+ var dir = mapPath.Directory;
resManager.UserData.CreateDir(dir);
mapSystem.CreateMap(out var mapId);
}
Assert.Multiple(() => mapLoader.SaveMap(mapId, mapPath));
- Assert.Multiple(() => mapManager.DeleteMap(mapId));
+ Assert.Multiple(() => 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();
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();
});
}
{
- 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();
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;
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));
+ mapLoader.SaveGrid(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));
+ mapLoader.SaveGrid(grid1!.Value, rp2);
});
await server.WaitIdleAsync();
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))
{
TestContext.Error.WriteLine(twoTmp);
}
});
+ testSystem.Enabled = false;
await pair.CleanReturnAsync();
}
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>();
// 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;
+ mapLoader.SaveMap(mapId, rp1);
});
// Run 5 ticks.
await server.WaitPost(() =>
{
- mapLoader.SaveMap(mapId, "/load save ticks save 2.yml");
+ mapLoader.SaveMap(mapId, rp2);
});
await server.WaitIdleAsync();
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();
}
});
- await server.WaitPost(() => mapManager.DeleteMap(mapId));
+ testSystem.Enabled = false;
+ await server.WaitPost(() => mapSys.DeleteMap(mapId));
await pair.CleanReturnAsync();
}
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;
+ MapId mapId1 = default;
+ MapId mapId2 = default;
const string fileA = "/load tick load a.yml";
const string fileB = "/load tick load b.yml";
string yamlA;
// 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;
+ mapLoader.SaveMap(mapId1, fileA);
});
await server.WaitIdleAsync();
// 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;
+ mapLoader.SaveMap(mapId2, fileB);
});
await server.WaitIdleAsync();
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<AfterSaveEvent>(OnAfterSave);
+ }
+
+ private void OnAfterSave(AfterSaveEvent ev)
+ {
+ if (!Enabled)
+ return;
+
+ // Remove timestamp.
+ ((MappingDataNode)ev.Node["meta"]).Remove("time");
+ }
+ }
}
}
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;
{
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));
-using System.Linq;
using System.Numerics;
using Content.Server.GameTicking;
using Content.Server.Maps;
using Content.Shared.Administration;
-using Robust.Server.Maps;
using Robust.Shared.Console;
-using Robust.Shared.ContentPack;
+using Robust.Shared.EntitySerialization;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
var entityManager = IoCManager.Resolve<IEntityManager>();
var gameTicker = entityManager.EntitySysManager.GetEntitySystem<GameTicker>();
+ var mapSys = entityManager.EntitySysManager.GetEntitySystem<SharedMapSystem>();
if (args.Length is not (2 or 4 or 5))
{
return;
}
- if (prototypeManager.TryIndex<GameMapPrototype>(args[1], out var gameMap))
+ if (!prototypeManager.TryIndex<GameMapPrototype>(args[1], out var gameMap))
{
- if (!int.TryParse(args[0], out var mapId))
+ shell.WriteError($"The given map prototype {args[0]} is invalid.");
+ return;
+ }
+
+ if (!int.TryParse(args[0], out var mapId))
return;
- var loadOptions = new MapLoadOptions()
- {
- LoadMap = false,
- };
+ var stationName = args.Length == 5 ? args[4] : null;
- var stationName = args.Length == 5 ? args[4] : null;
+ Vector2? offset = null;
+ if (args.Length >= 4)
+ offset = new Vector2(int.Parse(args[2]), int.Parse(args[3]));
- if (args.Length >= 4 && int.TryParse(args[2], out var x) && int.TryParse(args[3], out var y))
- {
- loadOptions.Offset = new Vector2(x, y);
- }
- var grids = gameTicker.LoadGameMap(gameMap, new MapId(mapId), loadOptions, stationName);
- shell.WriteLine($"Loaded {grids.Count} grids.");
- }
- else
- {
- shell.WriteError($"The given map prototype {args[0]} is invalid.");
- }
+ var id = new MapId(mapId);
+
+ var grids = mapSys.MapExists(id)
+ ? gameTicker.MergeGameMap(gameMap, id, stationName: stationName, offset: offset)
+ : gameTicker.LoadGameMapWithId(gameMap, id, stationName: stationName, offset: offset);
+
+ shell.WriteLine($"Loaded {grids.Count} grids.");
}
public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
using Robust.Shared.Console;
using Robust.Shared.Map;
using System.Linq;
+using Robust.Shared.EntitySerialization.Systems;
namespace Content.Server.Administration.Commands;
-using Robust.Server.GameObjects;
-using Robust.Shared.Map;
-using Robust.Shared.Map.Components;
+using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.Network;
using Robust.Shared.Player;
+using Robust.Shared.Utility;
namespace Content.Server.Administration.Systems;
/// </summary>
public sealed class AdminTestArenaSystem : EntitySystem
{
- [Dependency] private readonly IMapManager _mapManager = default!;
- [Dependency] private readonly MapLoaderSystem _map = default!;
+ [Dependency] private readonly MapLoaderSystem _loader = default!;
[Dependency] private readonly MetaDataSystem _metaDataSystem = default!;
public const string ArenaMapPath = "/Maps/Test/admin_test_arena.yml";
{
return (arenaMap, arenaGrid);
}
- else
- {
- ArenaGrid[admin.UserId] = null;
- return (arenaMap, null);
- }
- }
- ArenaMap[admin.UserId] = _mapManager.GetMapEntityId(_mapManager.CreateMap());
- _metaDataSystem.SetEntityName(ArenaMap[admin.UserId], $"ATAM-{admin.Name}");
- var grids = _map.LoadMap(Comp<MapComponent>(ArenaMap[admin.UserId]).MapId, ArenaMapPath);
- if (grids.Count != 0)
- {
- _metaDataSystem.SetEntityName(grids[0], $"ATAG-{admin.Name}");
- ArenaGrid[admin.UserId] = grids[0];
- }
- else
- {
+
ArenaGrid[admin.UserId] = null;
+ return (arenaMap, null);
}
- return (ArenaMap[admin.UserId], ArenaGrid[admin.UserId]);
+ var path = new ResPath(ArenaMapPath);
+ if (!_loader.TryLoadMap(path, out var map, out var grids))
+ throw new Exception($"Failed to load admin arena");
+
+ ArenaMap[admin.UserId] = map.Value.Owner;
+ _metaDataSystem.SetEntityName(map.Value.Owner, $"ATAM-{admin.Name}");
+
+ var grid = grids.FirstOrNull();
+ ArenaGrid[admin.UserId] = grid?.Owner;
+ if (grid != null)
+ _metaDataSystem.SetEntityName(grid.Value.Owner, $"ATAG-{admin.Name}");
+
+ return (map.Value.Owner, grid?.Owner);
}
}
using System.Linq;
+using System.Numerics;
using Content.Server.Announcements;
using Content.Server.Discord;
using Content.Server.GameTicking.Events;
using Content.Shared.Preferences;
using JetBrains.Annotations;
using Prometheus;
-using Robust.Server.Maps;
using Robust.Shared.Asynchronous;
using Robust.Shared.Audio;
+using Robust.Shared.EntitySerialization;
+using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.Map;
+using Robust.Shared.Map.Components;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Random;
AddGamePresetRules();
- DefaultMap = _mapManager.CreateMap();
- _mapManager.AddUninitializedMap(DefaultMap);
-
var maps = new List<GameMapPrototype>();
// the map might have been force-set by something
// Let game rules dictate what maps we should load.
RaiseLocalEvent(new LoadingMapsEvent(maps));
- foreach (var map in maps)
+ if (maps.Count == 0)
{
- var toLoad = DefaultMap;
- if (maps[0] != map)
- {
- // Create other maps for the others since we need to.
- toLoad = _mapManager.CreateMap();
- _mapManager.AddUninitializedMap(toLoad);
- }
+ _map.CreateMap(out var mapId, runMapInit: false);
+ DefaultMap = mapId;
+ return;
+ }
+
+ for (var i = 0; i < maps.Count; i++)
+ {
+ LoadGameMap(maps[i], out var mapId);
+ DebugTools.Assert(!_map.IsInitialized(mapId));
- LoadGameMap(map, toLoad, null);
+ if (i == 0)
+ DefaultMap = mapId;
}
}
+ public PreGameMapLoad RaisePreLoad(
+ GameMapPrototype proto,
+ DeserializationOptions? opts = null,
+ Vector2? offset = null,
+ Angle? rot = null)
+ {
+ offset ??= proto.MaxRandomOffset != 0f
+ ? _robustRandom.NextVector2(proto.MaxRandomOffset)
+ : Vector2.Zero;
+
+ rot ??= proto.RandomRotation
+ ? _robustRandom.NextAngle()
+ : Angle.Zero;
+
+ opts ??= DeserializationOptions.Default;
+ var ev = new PreGameMapLoad(proto, opts.Value, offset.Value, rot.Value);
+ RaiseLocalEvent(ev);
+ return ev;
+ }
/// <summary>
/// Loads a new map, allowing systems interested in it to handle loading events.
/// In the base game, this is required to be used if you want to load a station.
+ /// This does not initialze maps, unles specified via the <see cref="DeserializationOptions"/>.
/// </summary>
- /// <param name="map">Game map prototype to load in.</param>
- /// <param name="targetMapId">Map to load into.</param>
- /// <param name="loadOptions">Map loading options, includes offset.</param>
+ /// <remarks>
+ /// This is basically a wrapper around a <see cref="MapLoaderSystem"/> method that auto generate
+ /// some <see cref="MapLoadOptions"/> using information in a prototype, and raise some events to allow content
+ /// to modify the options and react to the map creation.
+ /// </remarks>
+ /// <param name="proto">Game map prototype to load in.</param>
+ /// <param name="mapId">The id of the map that was loaded.</param>
+ /// <param name="options">Entity loading options, including whether the maps should be initialized.</param>
/// <param name="stationName">Name to assign to the loaded station.</param>
/// <returns>All loaded entities and grids.</returns>
- public IReadOnlyList<EntityUid> LoadGameMap(GameMapPrototype map, MapId targetMapId, MapLoadOptions? loadOptions, string? stationName = null)
+ public IReadOnlyList<EntityUid> LoadGameMap(
+ GameMapPrototype proto,
+ out MapId mapId,
+ DeserializationOptions? options = null,
+ string? stationName = null,
+ Vector2? offset = null,
+ Angle? rot = null)
{
- // Okay I specifically didn't set LoadMap here because this is typically called onto a new map.
- // whereas the command can also be used on an existing map.
- var loadOpts = loadOptions ?? new MapLoadOptions();
+ var ev = RaisePreLoad(proto, options, offset, rot);
- if (map.MaxRandomOffset != 0f)
- loadOpts.Offset = _robustRandom.NextVector2(map.MaxRandomOffset);
+ if (ev.GameMap.IsGrid)
+ {
+ var mapUid = _map.CreateMap(out mapId);
+ if (!_loader.TryLoadGrid(mapId,
+ ev.GameMap.MapPath,
+ out var grid,
+ ev.Options,
+ ev.Offset,
+ ev.Rotation))
+ {
+ throw new Exception($"Failed to load game-map grid {ev.GameMap.ID}");
+ }
- if (map.RandomRotation)
- loadOpts.Rotation = _robustRandom.NextAngle();
+ _metaData.SetEntityName(mapUid, proto.MapName);
+ var g = new List<EntityUid> {grid.Value.Owner};
+ RaiseLocalEvent(new PostGameMapLoad(proto, mapId, g, stationName));
+ return g;
+ }
- var ev = new PreGameMapLoad(targetMapId, map, loadOpts);
- RaiseLocalEvent(ev);
+ if (!_loader.TryLoadMap(ev.GameMap.MapPath,
+ out var map,
+ out var grids,
+ ev.Options,
+ ev.Offset,
+ ev.Rotation))
+ {
+ throw new Exception($"Failed to load game map {ev.GameMap.ID}");
+ }
+
+ mapId = map.Value.Comp.MapId;
+ _metaData.SetEntityName(map.Value.Owner, proto.MapName);
+ var gridUids = grids.Select(x => x.Owner).ToList();
+ RaiseLocalEvent(new PostGameMapLoad(proto, mapId, gridUids, stationName));
+ return gridUids;
+ }
+
+ /// <summary>
+ /// Variant of <see cref="LoadGameMap"/> that attempts to assign the provided <see cref="MapId"/> to the
+ /// loaded map.
+ /// </summary>
+ public IReadOnlyList<EntityUid> LoadGameMapWithId(
+ GameMapPrototype proto,
+ MapId mapId,
+ DeserializationOptions? opts = null,
+ string? stationName = null,
+ Vector2? offset = null,
+ Angle? rot = null)
+ {
+ var ev = RaisePreLoad(proto, opts, offset, rot);
+
+ if (ev.GameMap.IsGrid)
+ {
+ var mapUid = _map.CreateMap(mapId);
+ if (!_loader.TryLoadGrid(mapId,
+ ev.GameMap.MapPath,
+ out var grid,
+ ev.Options,
+ ev.Offset,
+ ev.Rotation))
+ {
+ throw new Exception($"Failed to load game-map grid {ev.GameMap.ID}");
+ }
- var gridIds = _map.LoadMap(targetMapId, ev.GameMap.MapPath.ToString(), ev.Options);
+ _metaData.SetEntityName(mapUid, proto.MapName);
+ var g = new List<EntityUid> {grid.Value.Owner};
+ RaiseLocalEvent(new PostGameMapLoad(proto, mapId, g, stationName));
+ return g;
+ }
- _metaData.SetEntityName(_mapManager.GetMapEntityId(targetMapId), map.MapName);
+ if (!_loader.TryLoadMapWithId(
+ mapId,
+ ev.GameMap.MapPath,
+ out var map,
+ out var grids,
+ ev.Options,
+ ev.Offset,
+ ev.Rotation))
+ {
+ throw new Exception($"Failed to load map");
+ }
- var gridUids = gridIds.ToList();
- RaiseLocalEvent(new PostGameMapLoad(map, targetMapId, gridUids, stationName));
+ _metaData.SetEntityName(map.Value.Owner, proto.MapName);
+ var gridUids = grids.Select(x => x.Owner).ToList();
+ RaiseLocalEvent(new PostGameMapLoad(proto, mapId, gridUids, stationName));
+ return gridUids;
+ }
+ /// <summary>
+ /// Variant of <see cref="LoadGameMap"/> that loads and then merges a game map onto an existing map.
+ /// </summary>
+ public IReadOnlyList<EntityUid> MergeGameMap(
+ GameMapPrototype proto,
+ MapId targetMap,
+ DeserializationOptions? opts = null,
+ string? stationName = null,
+ Vector2? offset = null,
+ Angle? rot = null)
+ {
+ // TODO MAP LOADING use a new event?
+ // This is quite different from the other methods, which will actually create a **new** map.
+ var ev = RaisePreLoad(proto, opts, offset, rot);
+
+ if (ev.GameMap.IsGrid)
+ {
+ if (!_loader.TryLoadGrid(targetMap,
+ ev.GameMap.MapPath,
+ out var grid,
+ ev.Options,
+ ev.Offset,
+ ev.Rotation))
+ {
+ throw new Exception($"Failed to load game-map grid {ev.GameMap.ID}");
+ }
+
+ var g = new List<EntityUid> {grid.Value.Owner};
+ // TODO MAP LOADING use a new event?
+ RaiseLocalEvent(new PostGameMapLoad(proto, targetMap, g, stationName));
+ return g;
+ }
+
+ if (!_loader.TryMergeMap(targetMap,
+ ev.GameMap.MapPath,
+ out var map,
+ out var grids,
+ ev.Options,
+ ev.Offset,
+ ev.Rotation))
+ {
+ throw new Exception($"Failed to load map");
+ }
+
+ var gridUids = grids.Select(x => x.Owner).ToList();
+
+ // TODO MAP LOADING use a new event?
+ RaiseLocalEvent(new PostGameMapLoad(proto, targetMap, gridUids, stationName));
return gridUids;
}
}
// MapInitialize *before* spawning players, our codebase is too shit to do it afterwards...
- _mapManager.DoMapInitialize(DefaultMap);
+ _map.InitializeMap(DefaultMap);
SpawnPlayers(readyPlayers, readyPlayerProfiles, force);
/// You likely want to subscribe to this after StationSystem.
/// </remarks>
[PublicAPI]
- public sealed class PreGameMapLoad : EntityEventArgs
+ public sealed class PreGameMapLoad(GameMapPrototype gameMap, DeserializationOptions options, Vector2 offset, Angle rotation) : EntityEventArgs
{
- public readonly MapId Map;
- public GameMapPrototype GameMap;
- public MapLoadOptions Options;
-
- public PreGameMapLoad(MapId map, GameMapPrototype gameMap, MapLoadOptions options)
- {
- Map = map;
- GameMap = gameMap;
- Options = options;
- }
+ public readonly GameMapPrototype GameMap = gameMap;
+ public DeserializationOptions Options = options;
+ public Vector2 Offset = offset;
+ public Angle Rotation = rotation;
}
-
/// <summary>
/// Event raised after the game loads a given map.
/// </summary>
using Robust.Server.GameStates;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Console;
+using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
[Dependency] private readonly IServerPreferencesManager _prefsManager = default!;
[Dependency] private readonly IServerDbManager _db = default!;
[Dependency] private readonly ChatSystem _chatSystem = default!;
- [Dependency] private readonly MapLoaderSystem _map = default!;
+ [Dependency] private readonly MapLoaderSystem _loader = default!;
+ [Dependency] private readonly SharedMapSystem _map = default!;
[Dependency] private readonly GhostSystem _ghost = default!;
[Dependency] private readonly SharedMindSystem _mind = default!;
[Dependency] private readonly PlayTimeTrackingSystem _playTimeTrackings = default!;
public ProtoId<GameMapPrototype>? GameMap;
/// <summary>
- /// A map path to load on a new map.
+ /// A map to load.
/// </summary>
[DataField]
public ResPath? MapPath;
+ /// <summary>
+ /// A grid to load on a new map.
+ /// </summary>
+ [DataField]
+ public ResPath? GridPath;
+
/// <summary>
/// A <see cref="PreloadedGridPrototype"/> to move to a new map.
/// If there are no instances left nothing is done.
+using System.Linq;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.GridPreloader;
using Content.Server.StationEvents.Events;
using Content.Shared.GameTicking.Components;
using Robust.Server.GameObjects;
-using Robust.Server.Maps;
+using Robust.Shared.EntitySerialization;
+using Robust.Shared.EntitySerialization.Systems;
+using Robust.Shared.Map;
using Robust.Shared.Prototypes;
+using Robust.Shared.Utility;
namespace Content.Server.GameTicking.Rules;
return;
}
- // grid preloading needs map to init after moving it
- var mapUid = _map.CreateMap(out var mapId, runMapInit: comp.PreloadedGrid == null);
-
- Log.Info($"Created map {mapId} for {ToPrettyString(uid):rule}");
-
+ MapId mapId;
IReadOnlyList<EntityUid> grids;
if (comp.GameMap != null)
{
+ // Component has one of three modes, only one of the three fields should ever be populated.
+ DebugTools.AssertNull(comp.MapPath);
+ DebugTools.AssertNull(comp.GridPath);
+ DebugTools.AssertNull(comp.PreloadedGrid);
+
var gameMap = _prototypeManager.Index(comp.GameMap.Value);
- grids = GameTicker.LoadGameMap(gameMap, mapId, new MapLoadOptions());
+ grids = GameTicker.LoadGameMap(gameMap, out mapId, null);
+ Log.Info($"Created map {mapId} for {ToPrettyString(uid):rule}");
}
else if (comp.MapPath is {} path)
{
- var options = new MapLoadOptions { LoadMap = true };
- if (!_mapLoader.TryLoad(mapId, path.ToString(), out var roots, options))
+ DebugTools.AssertNull(comp.GridPath);
+ DebugTools.AssertNull(comp.PreloadedGrid);
+
+ var opts = DeserializationOptions.Default with {InitializeMaps = true};
+ if (!_mapLoader.TryLoadMap(path, out var map, out var gridSet, opts))
{
Log.Error($"Failed to load map from {path}!");
- Del(mapUid);
ForceEndSelf(uid, rule);
return;
}
- grids = roots;
+ grids = gridSet.Select( x => x.Owner).ToList();
+ mapId = map.Value.Comp.MapId;
+ }
+ else if (comp.GridPath is { } gPath)
+ {
+ DebugTools.AssertNull(comp.PreloadedGrid);
+
+ // I fucking love it when "map paths" choses to ar
+ _map.CreateMap(out mapId);
+ var opts = DeserializationOptions.Default with {InitializeMaps = true};
+ if (!_mapLoader.TryLoadGrid(mapId, gPath, out var grid, opts))
+ {
+ Log.Error($"Failed to load grid from {gPath}!");
+ ForceEndSelf(uid, rule);
+ return;
+ }
+
+ grids = new List<EntityUid> {grid.Value.Owner};
}
else if (comp.PreloadedGrid is {} preloaded)
{
if (!_gridPreloader.TryGetPreloadedGrid(preloaded, out var loadedShuttle))
{
Log.Error($"Failed to get a preloaded grid with {preloaded}!");
- Del(mapUid);
ForceEndSelf(uid, rule);
return;
}
+ var mapUid = _map.CreateMap(out mapId, runMapInit: false);
_transform.SetParent(loadedShuttle.Value, mapUid);
grids = new List<EntityUid>() { loadedShuttle.Value };
_map.InitializeMap(mapUid);
else
{
Log.Error($"No valid map prototype or map path associated with the rule {ToPrettyString(uid)}");
- Del(mapUid);
ForceEndSelf(uid, rule);
return;
}
using Content.Shared.GridPreloader.Prototypes;
using Content.Shared.GridPreloader.Systems;
using Robust.Server.GameObjects;
-using Robust.Server.Maps;
using Robust.Shared.Configuration;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Content.Server.GameTicking;
using Content.Shared.GameTicking;
using JetBrains.Annotations;
+using Robust.Shared.EntitySerialization.Systems;
namespace Content.Server.GridPreloader;
public sealed class GridPreloaderSystem : SharedGridPreloaderSystem
{
for (var i = 0; i < proto.Copies; i++)
{
- var options = new MapLoadOptions
+ if (!_mapLoader.TryLoadGrid(mapId, proto.Path, out var grid))
{
- LoadMap = false,
- };
-
- if (!_mapLoader.TryLoad(mapId, proto.Path.ToString(), out var roots, options))
- continue;
-
- // only supports loading maps with one grid.
- if (roots.Count != 1)
+ Log.Error($"Failed to preload grid prototype {proto.ID}");
continue;
+ }
- var gridUid = roots[0];
-
- // gets grid + also confirms that the root we loaded is actually a grid
- if (!TryComp<MapGridComponent>(gridUid, out var mapGrid))
- continue;
+ var (gridUid, mapGrid) = grid.Value;
if (!TryComp<PhysicsComponent>(gridUid, out var physics))
continue;
using Content.Server.GameTicking;
using Content.Shared.Administration;
using Content.Shared.CCVar;
-using Robust.Server.GameObjects;
-using Robust.Server.Maps;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.ContentPack;
+using Robust.Shared.EntitySerialization;
+using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.Map;
+using Robust.Shared.Utility;
namespace Content.Server.Mapping
{
}
else
{
- var loadOptions = new MapLoadOptions {StoreMapUids = true};
- _entities.System<MapLoaderSystem>().TryLoad(mapId, args[1], out _, loadOptions);
+ var path = new ResPath(args[1]);
+ var opts = new DeserializationOptions {StoreYamlUids = true};
+ _entities.System<MapLoaderSystem>().TryLoadMapWithId(mapId, path, out _, out _, opts);
}
// was the map actually created or did it fail somehow?
using Content.Shared.Mapping;
using Robust.Server.GameObjects;
using Robust.Server.Player;
+using Robust.Shared.EntitySerialization;
+using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Serialization;
[Dependency] private readonly IServerNetManager _net = default!;
[Dependency] private readonly IPlayerManager _players = default!;
[Dependency] private readonly IEntitySystemManager _systems = default!;
+ [Dependency] private readonly IEntityManager _ent = default!;
private ISawmill _sawmill = default!;
private ZStdCompressionContext _zstd = default!;
if (!_players.TryGetSessionByChannel(message.MsgChannel, out var session) ||
!_admin.IsAdmin(session, true) ||
!_admin.HasAdminFlag(session, AdminFlags.Host) ||
- session.AttachedEntity is not { } player)
+ !_ent.TryGetComponent(session.AttachedEntity, out TransformComponent? xform) ||
+ xform.MapUid is not {} mapUid)
{
return;
}
- var mapId = _systems.GetEntitySystem<TransformSystem>().GetMapCoordinates(player).MapId;
- var mapEntity = _map.GetMapEntityIdOrThrow(mapId);
- var data = _systems.GetEntitySystem<MapLoaderSystem>().GetSaveData(mapEntity);
+ var data = _systems.GetEntitySystem<MapLoaderSystem>().SerializeEntityRecursive(mapUid).Node;
var document = new YamlDocument(data.ToYaml());
var stream = new YamlStream { document };
var writer = new StringWriter();
using Content.Shared.Administration;
using Content.Shared.CCVar;
using Robust.Server.GameObjects;
-using Robust.Server.Maps;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.ContentPack;
+using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.Map;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IResourceManager _resMan = default!;
- [Dependency] private readonly MapLoaderSystem _map = default!;
+ [Dependency] private readonly MapLoaderSystem _loader = default!;
// Not a comp because I don't want to deal with this getting saved onto maps ever
/// <summary>
var path = Path.Combine(saveDir, $"{DateTime.Now.ToString("yyyy-M-dd_HH.mm.ss")}-AUTO.yml");
_currentlyAutosaving[map] = (CalculateNextTime(), name);
Log.Info($"Autosaving map {name} ({map}) to {path}. Next save in {ReadableTimeLeft(map)} seconds.");
- _map.SaveMap(map, path);
+ _loader.SaveMap(map, path);
}
}
[DataField]
public float MaxRandomOffset = 1000f;
+ /// <summary>
+ /// Turns out some of the map files are actually secretly grids. Excellent. I love map loading code.
+ /// </summary>
+ [DataField] public bool IsGrid;
+
[DataField]
public bool RandomRotation = true;
using System.IO;
using System.Linq;
using Robust.Server.GameObjects;
-using Robust.Server.Maps;
using Robust.Shared.ContentPack;
+using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.Map.Events;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Markdown;
using System.Linq;
using Content.Server.Administration;
using Content.Shared.Administration;
-using Robust.Server.GameObjects;
-using Robust.Server.Maps;
using Robust.Shared.Console;
using Robust.Shared.ContentPack;
-using Robust.Shared.Map;
+using Robust.Shared.EntitySerialization;
+using Robust.Shared.EntitySerialization.Components;
+using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.Utility;
namespace Content.Server.Maps;
public sealed class ResaveCommand : LocalizedCommands
{
[Dependency] private readonly IEntityManager _entManager = default!;
- [Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IResourceManager _res = default!;
+ [Dependency] private readonly ILogManager _log = default!;
public override string Command => "resave";
{
var loader = _entManager.System<MapLoaderSystem>();
- foreach (var fn in _res.ContentFindFiles(new ResPath("/Maps/")))
+ var opts = MapLoadOptions.Default with
{
- var mapId = _mapManager.CreateMap();
- _mapManager.AddUninitializedMap(mapId);
- loader.Load(mapId, fn.ToString(), new MapLoadOptions()
+
+ DeserializationOptions = DeserializationOptions.Default with
+ {
+ StoreYamlUids = true,
+ LogOrphanedGrids = false
+ }
+ };
+
+ var log = _log.GetSawmill(Command);
+ var files = _res.ContentFindFiles(new ResPath("/Maps/")).ToList();
+
+ for (var i = 0; i < files.Count; i++)
+ {
+ var fn = files[i];
+ log.Info($"Re-saving file {i}/{files.Count} : {fn}");
+
+ if (!loader.TryLoadEntities(fn, out var result, opts))
+ continue;
+
+ if (result.Maps.Count != 1)
{
- StoreMapUids = true,
- LoadMap = true,
- });
+ shell.WriteError(
+ $"Multi-map or multi-grid files like {fn} are not yet supported by the {Command} command");
+ loader.Delete(result);
+ continue;
+ }
+
+ var map = result.Maps.First();
// Process deferred component removals.
_entManager.CullRemovedComponents();
- var mapUid = _mapManager.GetMapEntityId(mapId);
- var mapXform = _entManager.GetComponent<TransformComponent>(mapUid);
-
- if (_entManager.HasComponent<LoadedMapComponent>(mapUid) || mapXform.ChildCount != 1)
+ if (_entManager.HasComponent<LoadedMapComponent>(map))
{
- loader.SaveMap(mapId, fn.ToString());
+ loader.SaveMap(map.Comp.MapId, fn);
}
- else if (mapXform.ChildEnumerator.MoveNext(out var child))
+ else if (result.Grids.Count == 1)
{
- loader.Save(child, fn.ToString());
+ loader.SaveGrid(result.Grids.First(), fn);
+ }
+ else
+ {
+ shell.WriteError($"Failed to resave {fn}");
}
- _mapManager.DeleteMap(mapId);
+ loader.Delete(result);
}
+
+ shell.WriteLine($"Resaved all maps");
}
}
using Robust.Shared.Collections;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
+using Robust.Shared.EntitySerialization;
+using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
+using Robust.Shared.Utility;
namespace Content.Server.Procedural;
return Transform(uid).MapID;
}
- var mapId = _mapManager.CreateMap();
- _mapManager.AddUninitializedMap(mapId);
- _loader.Load(mapId, proto.AtlasPath.ToString());
- var mapUid = _mapManager.GetMapEntityId(mapId);
- _mapManager.SetMapPaused(mapId, true);
- comp = AddComp<DungeonAtlasTemplateComponent>(mapUid);
+ var opts = new MapLoadOptions
+ {
+ DeserializationOptions = DeserializationOptions.Default with {PauseMaps = true},
+ ExpectedCategory = FileCategory.Map
+ };
+
+ if (!_loader.TryLoadEntities(proto.AtlasPath, out var res, opts) || !res.Maps.TryFirstOrNull(out var map))
+ throw new Exception($"Failed to load dungeon template.");
+
+ comp = AddComp<DungeonAtlasTemplateComponent>(map.Value.Owner);
comp.Path = proto.AtlasPath;
- return mapId;
+ return map.Value.Comp.MapId;
}
/// <summary>
using System.Numerics;
using System.Threading.Tasks;
using Content.Server.Salvage.Magnet;
-using Content.Shared.Humanoid;
using Content.Shared.Mobs.Components;
using Content.Shared.Procedural;
using Content.Shared.Radio;
using Content.Shared.Salvage.Magnet;
-using Robust.Server.Maps;
using Robust.Shared.Map;
-using Robust.Shared.Map.Components;
namespace Content.Server.Salvage;
case SalvageOffering wreck:
var salvageProto = wreck.SalvageMap;
- var opts = new MapLoadOptions
- {
- Offset = new Vector2(0, 0)
- };
-
- if (!_map.TryLoad(salvMapXform.MapID, salvageProto.MapPath.ToString(), out _, opts))
+ if (!_loader.TryLoadGrid(salvMapXform.MapID, salvageProto.MapPath, out _))
{
Report(magnet, MagnetChannel, "salvage-system-announcement-spawn-debris-disintegrated");
- _mapManager.DeleteMap(salvMapXform.MapID);
+ _mapSystem.DeleteMap(salvMapXform.MapID);
return;
}
-using System.Linq;
-using System.Numerics;
-using Content.Server.Cargo.Systems;
-using Content.Server.Construction;
-using Content.Server.GameTicking;
using Content.Server.Radio.EntitySystems;
-using Content.Shared.Examine;
-using Content.Shared.Interaction;
-using Content.Shared.Popups;
using Content.Shared.Radio;
using Content.Shared.Salvage;
using Robust.Server.GameObjects;
using Robust.Shared.Configuration;
using Robust.Shared.Map;
-using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
-using Robust.Shared.Utility;
using Content.Server.Chat.Managers;
using Content.Server.Gravity;
using Content.Server.Parallax;
using Content.Server.Procedural;
using Content.Server.Shuttles.Systems;
using Content.Server.Station.Systems;
-using Content.Shared.CCVar;
using Content.Shared.Construction.EntitySystems;
-using Content.Shared.Random;
-using Content.Shared.Random.Helpers;
-using Content.Shared.Tools.Components;
-using Robust.Server.Maps;
-using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Map.Components;
using Robust.Shared.Timing;
using Content.Server.Labels;
+using Robust.Shared.EntitySerialization.Systems;
namespace Content.Server.Salvage
{
[Dependency] private readonly DungeonSystem _dungeon = default!;
[Dependency] private readonly GravitySystem _gravity = default!;
[Dependency] private readonly LabelSystem _labelSystem = default!;
- [Dependency] private readonly MapLoaderSystem _map = default!;
+ [Dependency] private readonly MapLoaderSystem _loader = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly RadioSystem _radioSystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
using Robust.Shared.Collections;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
+using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
+using Robust.Shared.Utility;
using TimedDespawnComponent = Robust.Shared.Spawners.TimedDespawnComponent;
namespace Content.Server.Shuttles.Systems;
private void SetupArrivalsStation()
{
- var mapUid = _mapSystem.CreateMap(out var mapId, false);
- _metaData.SetEntityName(mapUid, Loc.GetString("map-name-terminal"));
-
- if (!_loader.TryLoad(mapId, _cfgManager.GetCVar(CCVars.ArrivalsMap), out var uids))
- {
+ var path = new ResPath(_cfgManager.GetCVar(CCVars.ArrivalsMap));
+ if (!_loader.TryLoadMap(path, out var map, out var grids))
return;
- }
- foreach (var id in uids)
+ _metaData.SetEntityName(map.Value, Loc.GetString("map-name-terminal"));
+
+ foreach (var id in grids)
{
EnsureComp<ArrivalsSourceComponent>(id);
EnsureComp<ProtectedGridComponent>(id);
if (_cfgManager.GetCVar(CCVars.ArrivalsPlanet))
{
var template = _random.Pick(_arrivalsBiomeOptions);
- _biomes.EnsurePlanet(mapUid, _protoManager.Index(template));
+ _biomes.EnsurePlanet(map.Value, _protoManager.Index(template));
var restricted = new RestrictedRangeComponent
{
Range = 32f
};
- AddComp(mapUid, restricted);
+ AddComp(map.Value, restricted);
}
- _mapSystem.InitializeMap(mapId);
+ _mapSystem.InitializeMap(map.Value.Comp.MapId);
// Handle roundstart stations.
var query = AllEntityQuery<StationArrivalsComponent>();
var dummpMapEntity = _mapSystem.CreateMap(out var dummyMapId);
if (TryGetArrivals(out var arrivals) &&
- _loader.TryLoad(dummyMapId, component.ShuttlePath.ToString(), out var shuttleUids))
+ _loader.TryLoadGrid(dummyMapId, component.ShuttlePath, out var shuttle))
{
- component.Shuttle = shuttleUids[0];
+ component.Shuttle = shuttle.Value;
var shuttleComp = Comp<ShuttleComponent>(component.Shuttle);
var arrivalsComp = EnsureComp<ArrivalsShuttleComponent>(component.Shuttle);
arrivalsComp.Station = uid;
using Content.Shared.Tag;
using Content.Shared.Tiles;
using Robust.Server.GameObjects;
-using Robust.Server.Maps;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Configuration;
-using Robust.Shared.Map;
+using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.Map.Components;
using Robust.Shared.Player;
using Robust.Shared.Random;
[Dependency] private readonly DockingSystem _dock = default!;
[Dependency] private readonly IdCardSystem _idSystem = default!;
[Dependency] private readonly NavMapSystem _navMap = default!;
- [Dependency] private readonly MapLoaderSystem _map = default!;
+ [Dependency] private readonly MapLoaderSystem _loader = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly RoundEndSystem _roundEnd = default!;
}
var map = _mapSystem.CreateMap(out var mapId);
- var grid = _map.LoadGrid(mapId, component.Map.ToString(), new MapLoadOptions()
+ if (!_loader.TryLoadGrid(mapId, component.Map, out var grid))
{
- LoadMap = false,
- });
+ Log.Error($"Failed to set up centcomm grid!");
+ return;
+ }
if (!Exists(map))
{
// Load escape shuttle
var shuttlePath = ent.Comp1.EmergencyShuttlePath;
- var shuttle = _map.LoadGrid(map.MapId, shuttlePath.ToString(), new MapLoadOptions()
- {
+ if (!_loader.TryLoadGrid(map.MapId,
+ shuttlePath,
+ out var shuttle,
// Should be far enough... right? I'm too lazy to bounds check CentCom rn.
- Offset = new Vector2(500f + ent.Comp2.ShuttleIndex, 0f),
- // fun fact: if you just fucking yeet centcomm into nullspace anytime you try to spawn the shuttle, then any distance is far enough. so lets not do that
- LoadMap = false,
- });
-
- if (shuttle == null)
+ offset: new Vector2(500f + ent.Comp2.ShuttleIndex, 0f)))
{
Log.Error($"Unable to spawn emergency shuttle {shuttlePath} for {ToPrettyString(ent)}");
return;
_mapSystem.CreateMap(out var mapId);
- if (_loader.TryLoad(mapId, component.Path.ToString(), out var ent) && ent.Count > 0)
+ if (_loader.TryLoadGrid(mapId, component.Path, out var ent))
{
- if (HasComp<ShuttleComponent>(ent[0]))
- {
- TryFTLProximity(ent[0], targetGrid.Value);
- }
+ if (HasComp<ShuttleComponent>(ent))
+ TryFTLProximity(ent.Value, targetGrid.Value);
- _station.AddGridToStation(uid, ent[0]);
+ _station.AddGridToStation(uid, ent.Value);
}
- _mapManager.DeleteMap(mapId);
+ _mapSystem.DeleteMap(mapId);
}
private bool TryDungeonSpawn(Entity<MapGridComponent?> targetGrid, DungeonSpawnGroup group, out EntityUid spawned)
var path = paths[^1];
paths.RemoveAt(paths.Count - 1);
- if (_loader.TryLoad(mapId, path.ToString(), out var ent) && ent.Count == 1)
+ if (_loader.TryLoadGrid(mapId, path, out var grid))
{
- if (HasComp<ShuttleComponent>(ent[0]))
- {
- TryFTLProximity(ent[0], targetGrid);
- }
+ if (HasComp<ShuttleComponent>(grid))
+ TryFTLProximity(grid.Value, targetGrid);
if (group.NameGrid)
{
var name = path.FilenameWithoutExtension;
- _metadata.SetEntityName(ent[0], name);
+ _metadata.SetEntityName(grid.Value, name);
}
- spawned = ent[0];
+ spawned = grid.Value;
return true;
}
}
}
- _mapManager.DeleteMap(mapId);
+ _mapSystem.DeleteMap(mapId);
}
private void OnGridFillMapInit(EntityUid uid, GridFillComponent component, MapInitEvent args)
_mapSystem.CreateMap(out var mapId);
var valid = false;
- if (_loader.TryLoad(mapId, component.Path.ToString(), out var ent) &&
- ent.Count == 1 &&
- TryComp(ent[0], out TransformComponent? shuttleXform))
+ if (_loader.TryLoadGrid(mapId, component.Path, out var grid))
{
- var escape = GetSingleDock(ent[0]);
+ var escape = GetSingleDock(grid.Value);
if (escape != null)
{
- var config = _dockSystem.GetDockingConfig(ent[0], xform.GridUid.Value, escape.Value.Entity, escape.Value.Component, uid, dock);
+ var config = _dockSystem.GetDockingConfig(grid.Value, xform.GridUid.Value, escape.Value.Entity, escape.Value.Component, uid, dock);
if (config != null)
{
- FTLDock((ent[0], shuttleXform), config);
+ var shuttleXform = Transform(grid.Value);
+ FTLDock((grid.Value, shuttleXform), config);
if (TryComp<StationMemberComponent>(xform.GridUid, out var stationMember))
{
- _station.AddGridToStation(stationMember.Station, ent[0]);
+ _station.AddGridToStation(stationMember.Station, grid.Value);
}
valid = true;
{
var compType = compReg.Component.GetType();
- if (HasComp(ent[0], compType))
+ if (HasComp(grid.Value, compType))
continue;
var comp = _factory.GetComponent(compType);
- AddComp(ent[0], comp, true);
+ AddComp(grid.Value, comp, true);
}
}
Log.Error($"Error loading gridfill dock for {ToPrettyString(uid)} / {component.Path}");
}
- _mapManager.DeleteMap(mapId);
+ _mapSystem.DeleteMap(mapId);
}
private (EntityUid Entity, DockingComponent Component)? GetSingleDock(EntityUid uid)
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Configuration;
+using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics;
using Robust.Shared.GameStates;
using Robust.Shared.Input;
using Robust.Shared.Input.Binding;
+using Robust.Shared.Map.Components;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
}
// If we went from grid -> map we'll preserve our worldrotation
- if (relative != null && _mapManager.IsMap(relative.Value))
+ if (relative != null && HasComp<MapComponent>(relative.Value))
{
targetRotation = currentRotation.FlipPositive().Reduced();
}
duration: 1
- type: RuleGrids
- type: LoadMapRule
- mapPath: /Maps/Shuttles/ShuttleEvent/striker.yml
+ gridPath: /Maps/Shuttles/ShuttleEvent/striker.yml
- type: NukeopsRule
roundEndBehavior: Nothing
- type: AntagSelection
- type: gameMap
id: CentComm
+ isGrid: true # Did you know that centcomm is the only "game map" that isn't actually a map? Send help.
mapName: 'Central Command'
mapPath: /Maps/centcomm.yml
minPlayers: 10
-Subproject commit 5e97db435c05b4c188184ef90e5d77b0500403d0
+Subproject commit 3cccf5be028be75242ffc86877b4e78a72b8cafe