diff --git a/Robust.Server/BaseServer.cs b/Robust.Server/BaseServer.cs
index bfa52bd2d..af75df85a 100644
--- a/Robust.Server/BaseServer.cs
+++ b/Robust.Server/BaseServer.cs
@@ -388,6 +388,11 @@ namespace Robust.Server
_protoLoadMan.Initialize();
_netResMan.Initialize();
+ // String serializer has to be locked before PostInit as content can depend on it (e.g., replays that start
+ // automatically recording on startup).
+ AddFinalStringsToSerializer();
+ _stringSerializer.LockStrings();
+
_modLoader.BroadcastRunLevel(ModRunLevel.PostInit);
_statusHost.Start();
@@ -397,9 +402,6 @@ namespace Robust.Server
_watchdogApi.Initialize();
- AddFinalStringsToSerializer();
- _stringSerializer.LockStrings();
-
if (OperatingSystem.IsWindows() && _config.GetCVar(CVars.SysWinTickPeriod) >= 0)
{
WindowsTickPeriod.TimeBeginPeriod((uint) _config.GetCVar(CVars.SysWinTickPeriod));
diff --git a/Robust.Shared/ContentPack/VirtualWritableDirProvider.cs b/Robust.Shared/ContentPack/VirtualWritableDirProvider.cs
index cddb3dfe3..534029786 100644
--- a/Robust.Shared/ContentPack/VirtualWritableDirProvider.cs
+++ b/Robust.Shared/ContentPack/VirtualWritableDirProvider.cs
@@ -43,7 +43,7 @@ namespace Robust.Shared.ContentPack
{
if (directory.Children.TryGetValue(segment, out var child))
{
- if (!(child is DirectoryNode childDir))
+ if (child is not DirectoryNode childDir)
{
throw new ArgumentException("A file already exists at that location.");
}
@@ -55,6 +55,7 @@ namespace Robust.Shared.ContentPack
var newDir = new DirectoryNode();
directory.Children.Add(segment, newDir);
+ directory = newDir;
}
}
@@ -205,7 +206,28 @@ namespace Robust.Shared.ContentPack
public void Rename(ResPath oldPath, ResPath newPath)
{
- throw new NotImplementedException();
+ if (!oldPath.IsRooted)
+ throw new ArgumentException("Path must be rooted", nameof(oldPath));
+
+ if (!newPath.IsRooted)
+ throw new ArgumentException("Path must be rooted", nameof(newPath));
+
+ if (!TryGetNodeAt(oldPath.Directory, out var parent) || parent is not DirectoryNode sourceDir)
+ throw new ArgumentException("Source directory does not exist.");
+
+ if (!TryGetNodeAt(newPath.Directory, out var target) || target is not DirectoryNode targetDir)
+ throw new ArgumentException("Target directory does not exist.");
+
+ var newFile = newPath.Filename;
+ if (targetDir.Children.ContainsKey(newFile))
+ throw new ArgumentException("Target node already exists");
+
+ var oldFile = oldPath.Filename;
+ if (!sourceDir.Children.TryGetValue(oldFile, out var node))
+ throw new ArgumentException("Node does not exist in original directory.");
+
+ sourceDir.Children.Remove(oldFile);
+ targetDir.Children.Add(newFile, node);
}
public void OpenOsWindow(ResPath path)
diff --git a/Robust.Shared/Replays/IReplayRecordingManager.cs b/Robust.Shared/Replays/IReplayRecordingManager.cs
index d4a717a6f..72f0b6b86 100644
--- a/Robust.Shared/Replays/IReplayRecordingManager.cs
+++ b/Robust.Shared/Replays/IReplayRecordingManager.cs
@@ -124,6 +124,11 @@ public interface IReplayRecordingManager
/// Thrown if we are currently recording ( true).
///
Task WaitWriteTasks();
+
+ ///
+ /// Returns true if there are any currently running write tasks.
+ ///
+ bool IsWriting();
}
///
diff --git a/Robust.Shared/Replays/SharedReplayRecordingManager.Write.cs b/Robust.Shared/Replays/SharedReplayRecordingManager.Write.cs
index f9223138f..cc3a12b0c 100644
--- a/Robust.Shared/Replays/SharedReplayRecordingManager.Write.cs
+++ b/Robust.Shared/Replays/SharedReplayRecordingManager.Write.cs
@@ -187,6 +187,12 @@ internal abstract partial class SharedReplayRecordingManager
}
}
+ public bool IsWriting()
+ {
+ UpdateWriteTasks();
+ return _finalizingWriteTasks.Count > 0;
+ }
+
public Task WaitWriteTasks()
{
if (IsRecording)
diff --git a/Robust.UnitTesting/IntegrationMappedStringSerializer.cs b/Robust.UnitTesting/IntegrationMappedStringSerializer.cs
index 3c876e696..efcc5d817 100644
--- a/Robust.UnitTesting/IntegrationMappedStringSerializer.cs
+++ b/Robust.UnitTesting/IntegrationMappedStringSerializer.cs
@@ -78,7 +78,7 @@ namespace Robust.UnitTesting
public (byte[] mapHash, byte[] package) GeneratePackage()
{
- throw new NotSupportedException();
+ return (Array.Empty(), Array.Empty());
}
public void SetPackage(byte[] hash, byte[] package)