]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Fix MappingCommand grid loading (#35233)
authorLeon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Tue, 18 Feb 2025 12:25:14 +0000 (23:25 +1100)
committerGitHub <noreply@github.com>
Tue, 18 Feb 2025 12:25:14 +0000 (23:25 +1100)
Content.Server/Mapping/MappingCommand.cs
Content.Server/Mapping/MappingSystem.cs
Resources/Locale/en-US/mapping/mapping-command.ftl

index 85c561b9db073521df40355b2827a767a88bddb7..12a7af448465d9eee8cb68ecce8689085f4892ac 100644 (file)
@@ -9,6 +9,7 @@ using Robust.Shared.ContentPack;
 using Robust.Shared.EntitySerialization;
 using Robust.Shared.EntitySerialization.Systems;
 using Robust.Shared.Map;
+using Robust.Shared.Map.Components;
 using Robust.Shared.Utility;
 
 namespace Content.Server.Mapping
@@ -35,6 +36,8 @@ namespace Content.Server.Mapping
                     var opts = CompletionHelper.UserFilePath(args[1], res.UserData)
                         .Concat(CompletionHelper.ContentFilePath(args[1], res));
                     return CompletionResult.FromHintOptions(opts, Loc.GetString("cmd-hint-mapping-path"));
+                case 3:
+                    return CompletionResult.FromHintOptions(["false", "true"], Loc.GetString("cmd-mapping-hint-grid"));
             }
             return CompletionResult.Empty;
         }
@@ -47,7 +50,7 @@ namespace Content.Server.Mapping
                 return;
             }
 
-            if (args.Length > 2)
+            if (args.Length > 3)
             {
                 shell.WriteLine(Help);
                 return;
@@ -57,12 +60,20 @@ namespace Content.Server.Mapping
             shell.WriteLine(Loc.GetString("cmd-mapping-warning"));
 #endif
 
+            // For backwards compatibility, isGrid is optional and we allow mappers to try load grids without explicitly
+            // specifying that they are loading a grid. Currently content is not allowed to override a map's MapId, so
+            // without engine changes this needs to be done by brute force by just trying to load it as a map first.
+            // This can result in errors being logged if the file is actually a grid, but the command should still work.
+            // yipeeee
+            bool? isGrid = args.Length < 3 ? null : bool.Parse(args[2]);
+
             MapId mapId;
             string? toLoad = null;
             var mapSys = _entities.System<SharedMapSystem>();
+            Entity<MapGridComponent>? grid = null;
 
             // Get the map ID to use
-            if (args.Length is 1 or 2)
+            if (args.Length > 0)
             {
                 if (!int.TryParse(args[0], out var intMapId))
                 {
@@ -79,7 +90,7 @@ namespace Content.Server.Mapping
                     return;
                 }
 
-                if (_map.MapExists(mapId))
+                if (mapSys.MapExists(mapId))
                 {
                     shell.WriteError(Loc.GetString("cmd-mapping-exists", ("mapId", mapId)));
                     return;
@@ -93,12 +104,43 @@ namespace Content.Server.Mapping
                 else
                 {
                     var path = new ResPath(args[1]);
+                    toLoad = path.FilenameWithoutExtension;
                     var opts = new DeserializationOptions {StoreYamlUids = true};
-                    _entities.System<MapLoaderSystem>().TryLoadMapWithId(mapId, path, out _, out _, opts);
+                    var loader = _entities.System<MapLoaderSystem>();
+
+                    if (isGrid == true)
+                    {
+                        mapSys.CreateMap(mapId, runMapInit: false);
+                        if (!loader.TryLoadGrid(mapId, path, out grid, opts))
+                        {
+                            shell.WriteError(Loc.GetString("cmd-mapping-error"));
+                            mapSys.DeleteMap(mapId);
+                            return;
+                        }
+                    }
+                    else if (!loader.TryLoadMapWithId(mapId, path, out _, out _, opts))
+                    {
+                        if (isGrid == false)
+                        {
+                            shell.WriteError(Loc.GetString("cmd-mapping-error"));
+                            return;
+                        }
+
+                        // isGrid was not specified and loading it as a map failed, so we fall back to trying to load
+                        // the file as a grid
+                        shell.WriteLine(Loc.GetString("cmd-mapping-try-grid"));
+                        mapSys.CreateMap(mapId, runMapInit: false);
+                        if (!loader.TryLoadGrid(mapId, path, out grid, opts))
+                        {
+                            shell.WriteError(Loc.GetString("cmd-mapping-error"));
+                            mapSys.DeleteMap(mapId);
+                            return;
+                        }
+                    }
                 }
 
                 // was the map actually created or did it fail somehow?
-                if (!_map.MapExists(mapId))
+                if (!mapSys.MapExists(mapId))
                 {
                     shell.WriteError(Loc.GetString("cmd-mapping-error"));
                     return;
@@ -120,16 +162,22 @@ namespace Content.Server.Mapping
             shell.ExecuteCommand("changecvar events.enabled false");
             shell.ExecuteCommand("changecvar shuttle.auto_call_time 0");
 
-            if (_cfg.GetCVar(CCVars.AutosaveEnabled))
-                shell.ExecuteCommand($"toggleautosave {mapId} {toLoad ?? "NEWMAP"}");
+            var auto = _entities.System<MappingSystem>();
+            if (grid != null)
+                auto.ToggleAutosave(grid.Value.Owner, toLoad ?? "NEWGRID");
+            else
+                auto.ToggleAutosave(mapId, toLoad ?? "NEWMAP");
+
             shell.ExecuteCommand($"tp 0 0 {mapId}");
             shell.RemoteExecuteCommand("mappingclientsidesetup");
-            _map.SetMapPaused(mapId, true);
+            DebugTools.Assert(mapSys.IsPaused(mapId));
 
-            if (args.Length == 2)
-                shell.WriteLine(Loc.GetString("cmd-mapping-success-load",("mapId",mapId),("path", args[1])));
-            else
+            if (args.Length != 2)
                 shell.WriteLine(Loc.GetString("cmd-mapping-success", ("mapId", mapId)));
+            else if (grid == null)
+                shell.WriteLine(Loc.GetString("cmd-mapping-success-load", ("mapId", mapId), ("path", args[1])));
+            else
+                shell.WriteLine(Loc.GetString("cmd-mapping-success-load-grid", ("mapId", mapId), ("path", args[1])));
         }
     }
 }
index 1ef6944924ef309c7e942746f9ea716d0d0c3716..b79387b3e5a4ab52bdbadec75f0718912791df7f 100644 (file)
@@ -2,12 +2,12 @@ using System.IO;
 using Content.Server.Administration;
 using Content.Shared.Administration;
 using Content.Shared.CCVar;
-using Robust.Server.GameObjects;
 using Robust.Shared.Configuration;
 using Robust.Shared.Console;
 using Robust.Shared.ContentPack;
 using Robust.Shared.EntitySerialization.Systems;
 using Robust.Shared.Map;
+using Robust.Shared.Map.Components;
 using Robust.Shared.Timing;
 using Robust.Shared.Utility;
 
@@ -21,7 +21,7 @@ public sealed class MappingSystem : EntitySystem
     [Dependency] private readonly IConsoleHost _conHost = default!;
     [Dependency] private readonly IGameTiming _timing = default!;
     [Dependency] private readonly IConfigurationManager _cfg = default!;
-    [Dependency] private readonly IMapManager _mapManager = default!;
+    [Dependency] private readonly SharedMapSystem _map = default!;
     [Dependency] private readonly IResourceManager _resMan = default!;
     [Dependency] private readonly MapLoaderSystem _loader = default!;
 
@@ -30,7 +30,7 @@ public sealed class MappingSystem : EntitySystem
     ///     map id -> next autosave timespan & original filename.
     /// </summary>
     /// <returns></returns>
-    private Dictionary<MapId, (TimeSpan next, string fileName)> _currentlyAutosaving = new();
+    private Dictionary<EntityUid, (TimeSpan next, string fileName)> _currentlyAutosaving = new();
 
     private bool _autosaveEnabled;
 
@@ -60,25 +60,29 @@ public sealed class MappingSystem : EntitySystem
         if (!_autosaveEnabled)
             return;
 
-        foreach (var (map, (time, name))in _currentlyAutosaving.ToArray())
+        foreach (var (uid, (time, name))in _currentlyAutosaving)
         {
             if (_timing.RealTime <= time)
                 continue;
 
-            if (!_mapManager.MapExists(map) || _mapManager.IsMapInitialized(map))
+            if (LifeStage(uid) >= EntityLifeStage.MapInitialized)
             {
-                Log.Warning($"Can't autosave map {map}; it doesn't exist, or is initialized. Removing from autosave.");
-                _currentlyAutosaving.Remove(map);
-                return;
+                Log.Warning($"Can't autosave entity {uid}; it doesn't exist, or is initialized. Removing from autosave.");
+                _currentlyAutosaving.Remove(uid);
+                continue;
             }
 
+            _currentlyAutosaving[uid] = (CalculateNextTime(), name);
             var saveDir = Path.Combine(_cfg.GetCVar(CCVars.AutosaveDirectory), name);
             _resMan.UserData.CreateDir(new ResPath(saveDir).ToRootedPath());
 
-            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.");
-            _loader.TrySaveMap(map, new ResPath(path));
+            var path = new ResPath(Path.Combine(saveDir, $"{DateTime.Now:yyyy-M-dd_HH.mm.ss}-AUTO.yml"));
+            Log.Info($"Autosaving map {name} ({uid}) to {path}. Next save in {ReadableTimeLeft(uid)} seconds.");
+
+            if (HasComp<MapComponent>(uid))
+                _loader.TrySaveMap(uid, path);
+            else
+                _loader.TrySaveGrid(uid, path);
         }
     }
 
@@ -87,34 +91,41 @@ public sealed class MappingSystem : EntitySystem
         return _timing.RealTime + TimeSpan.FromSeconds(_cfg.GetCVar(CCVars.AutosaveInterval));
     }
 
-    private double ReadableTimeLeft(MapId map)
+    private double ReadableTimeLeft(EntityUid uid)
     {
-        return Math.Round(_currentlyAutosaving[map].next.TotalSeconds - _timing.RealTime.TotalSeconds);
+        return Math.Round(_currentlyAutosaving[uid].next.TotalSeconds - _timing.RealTime.TotalSeconds);
     }
 
     #region Public API
 
-    public void ToggleAutosave(MapId map, string? path=null)
+    public void ToggleAutosave(MapId map, string? path = null)
+    {
+        if (_map.TryGetMap(map, out var uid))
+            ToggleAutosave(uid.Value, path);
+    }
+
+    public void ToggleAutosave(EntityUid uid, string? path=null)
     {
         if (!_autosaveEnabled)
             return;
 
-        if (path != null && _currentlyAutosaving.TryAdd(map, (CalculateNextTime(), Path.GetFileName(path))))
-        {
-            if (!_mapManager.MapExists(map) || _mapManager.IsMapInitialized(map))
-            {
-                Log.Warning("Tried to enable autosaving on non-existant or already initialized map!");
-                _currentlyAutosaving.Remove(map);
-                return;
-            }
+        if (_currentlyAutosaving.Remove(uid) || path == null)
+            return;
 
-            Log.Info($"Started autosaving map {path} ({map}). Next save in {ReadableTimeLeft(map)} seconds.");
+        if (LifeStage(uid) >= EntityLifeStage.MapInitialized)
+        {
+            Log.Error("Tried to enable autosaving on a post map-init entity.");
+            return;
         }
-        else
+
+        if (!HasComp<MapComponent>(uid) && !HasComp<MapGridComponent>(uid))
         {
-            _currentlyAutosaving.Remove(map);
-            Log.Info($"Stopped autosaving on map {map}");
+            Log.Error($"{ToPrettyString(uid)} is neither a grid or map");
+            return;
         }
+
+        _currentlyAutosaving[uid] = (CalculateNextTime(), Path.GetFileName(path));
+        Log.Info($"Started autosaving map {path} ({uid}). Next save in {ReadableTimeLeft(uid)} seconds.");
     }
 
     #endregion
index e6d4f0e393524d37d4edf8e15e4842f44410a3c5..12ab144e253f9739f412ac4e681c5bf4f13f2c55 100644 (file)
@@ -1,8 +1,10 @@
 cmd-mapping-desc = Create or load a map and teleports you to it.
-cmd-mapping-help = Usage: mapping [MapID] [Path]
+cmd-mapping-help = Usage: mapping [MapID] [Path] [Grid]
 cmd-mapping-server = Only players can use this command.
 cmd-mapping-error = An error occurred when creating the new map.
+cmd-mapping-try-grid = Failed to load the file as a map. Attempting to load the file as a grid...
 cmd-mapping-success-load = Created uninitialized map from file {$path} with id {$mapId}.
+cmd-mapping-success-load-grid = Loaded uninitialized grid from file {$path} onto a new map with id {$mapId}.
 cmd-mapping-success = Created uninitialized map with id {$mapId}.
 cmd-mapping-warning = WARNING: The server is using a debug build. You are risking losing your changes.
 
@@ -14,5 +16,6 @@ cmd-mapping-failure-float = {$arg} is not a valid float.
 cmd-mapping-failure-bool = {$arg} is not a valid bool.
 cmd-mapping-nullspace = You cannot load into map 0.
 cmd-hint-mapping-id = [MapID]
+cmd-mapping-hint-grid = [Grid]
 cmd-hint-mapping-path = [Path]
 cmd-mapping-exists = Map {$mapId} already exists.