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)