diff --git a/Robust.Shared/CVars.cs b/Robust.Shared/CVars.cs index c781d1eab..6404bd1bf 100644 --- a/Robust.Shared/CVars.cs +++ b/Robust.Shared/CVars.cs @@ -1636,6 +1636,16 @@ namespace Robust.Shared public static readonly CVarDef ReplayMaxUncompressedSize = CVarDef.Create("replay.max_uncompressed_size", 1024L * 1024, CVar.ARCHIVE); + /// + /// Size of the replay (in kilobytes) at which point the replay is considered "large", + /// and replay clients should enable server GC (if possible) to improve performance. + /// + /// + /// Set to -1 to never make replays use server GC. + /// + public static readonly CVarDef ReplayServerGCSizeThreshold = + CVarDef.Create("replay.server_gc_size_threshold", 50L * 1024); + /// /// Uncompressed size of individual files created by the replay (in kilobytes), where each file contains data /// for one or more ticks. Actual files may be slightly larger, this is just a threshold for the file to get diff --git a/Robust.Shared/Replays/SharedReplayRecordingManager.cs b/Robust.Shared/Replays/SharedReplayRecordingManager.cs index b5d842d53..656e9ff83 100644 --- a/Robust.Shared/Replays/SharedReplayRecordingManager.cs +++ b/Robust.Shared/Replays/SharedReplayRecordingManager.cs @@ -58,6 +58,7 @@ internal abstract partial class SharedReplayRecordingManager : IReplayRecordingM // Config variables. private long _maxCompressedSize; private long _maxUncompressedSize; + private long _serverGCSizeThreshold; private int _tickBatchSize; private bool _enabled; @@ -71,6 +72,7 @@ internal abstract partial class SharedReplayRecordingManager : IReplayRecordingM NetConf.OnValueChanged(CVars.ReplayMaxCompressedSize, (v) => _maxCompressedSize = SaturatingMultiplyKb(v), true); NetConf.OnValueChanged(CVars.ReplayMaxUncompressedSize, (v) => _maxUncompressedSize = SaturatingMultiplyKb(v), true); + NetConf.OnValueChanged(CVars.ReplayServerGCSizeThreshold, (v) => _serverGCSizeThreshold = SaturatingMultiplyKb(v), true); NetConf.OnValueChanged(CVars.ReplayTickBatchSize, (v) => _tickBatchSize = Math.Min(v, MaxTickBatchSize) * 1024, true); NetConf.OnValueChanged(CVars.NetPvsCompressLevel, OnCompressionChanged); } @@ -238,7 +240,6 @@ internal abstract partial class SharedReplayRecordingManager : IReplayRecordingM try { - WriteContentBundleInfo(_recState); WriteInitialMetadata(name, _recState); } catch @@ -391,6 +392,7 @@ internal abstract partial class SharedReplayRecordingManager : IReplayRecordingM // this just overwrites the previous yml with additional data. var document = new YamlDocument(yamlMetadata.ToYaml()); WriteYaml(recState, ReplayZipFolder / FileMetaFinal, document); + WriteContentBundleInfo(recState); UpdateWriteTasks(); Reset(); @@ -412,6 +414,7 @@ internal abstract partial class SharedReplayRecordingManager : IReplayRecordingM var document = new JsonObject { + ["server_gc"] = ShouldEnableServerGC(recState), ["engine_version"] = info.EngineVersion, ["base_build"] = new JsonObject { @@ -429,6 +432,14 @@ internal abstract partial class SharedReplayRecordingManager : IReplayRecordingM WriteBytes(recState, new ResPath("rt_content_bundle.json"), bytes); } + private bool ShouldEnableServerGC(RecordingState recState) + { + if (_serverGCSizeThreshold < 0) + return false; + + return recState.CompressedSize >= _serverGCSizeThreshold; + } + /// /// Get information describing the server build. /// This will be embedded in replay content bundles to allow the launcher to directly load them.