diff --git a/Content.Client/Entry/EntryPoint.cs b/Content.Client/Entry/EntryPoint.cs index 49383d97797..1c9df27d33a 100644 --- a/Content.Client/Entry/EntryPoint.cs +++ b/Content.Client/Entry/EntryPoint.cs @@ -27,12 +27,16 @@ using Robust.Client; using Robust.Client.Graphics; using Robust.Client.Input; +using Robust.Client.Replays.Loading; +using Robust.Client.Replays.Playback; using Robust.Client.State; using Robust.Client.UserInterface; +using Robust.Shared; using Robust.Shared.Configuration; using Robust.Shared.ContentPack; using Robust.Shared.Map; using Robust.Shared.Prototypes; +using Robust.Shared.Replays; namespace Content.Client.Entry { @@ -64,6 +68,9 @@ public sealed class EntryPoint : GameClient [Dependency] private readonly JobRequirementsManager _jobRequirements = default!; [Dependency] private readonly ContentLocalizationManager _contentLoc = default!; [Dependency] private readonly ContentReplayPlaybackManager _playbackMan = default!; + [Dependency] private readonly IResourceManager _resourceManager = default!; + [Dependency] private readonly IReplayLoadManager _replayLoad = default!; + [Dependency] private readonly ILogManager _logManager = default!; public override void Init() { @@ -183,7 +190,20 @@ private void SwitchToDefaultState(bool disconnected = false) { // Fire off into state dependent on launcher or not. - if (_gameController.LaunchState.FromLauncher) + // Check if we're loading a replay via content bundle! + if (_configManager.GetCVar(CVars.LaunchContentBundle) + && _resourceManager.ContentFileExists( + ReplayConstants.ReplayZipFolder.ToRootedPath() / ReplayConstants.FileMeta)) + { + _logManager.GetSawmill("entry").Info("Loading content bundle replay from VFS!"); + + var reader = new ReplayFileReaderResources( + _resourceManager, + ReplayConstants.ReplayZipFolder.ToRootedPath()); + + _replayLoad.LoadAndStartReplay(reader); + } + else if (_gameController.LaunchState.FromLauncher) { _stateManager.RequestStateChange(); var state = (LauncherConnecting) _stateManager.CurrentState; diff --git a/Content.Client/Replay/ContentReplayPlaybackManager.cs b/Content.Client/Replay/ContentReplayPlaybackManager.cs index e400958bca5..843fcdfbd14 100644 --- a/Content.Client/Replay/ContentReplayPlaybackManager.cs +++ b/Content.Client/Replay/ContentReplayPlaybackManager.cs @@ -59,10 +59,10 @@ public void Initialize() _loadMan.LoadOverride += LoadOverride; } - private void LoadOverride(IWritableDirProvider dir, ResPath resPath) + private void LoadOverride(IReplayFileReader fileReader) { var screen = _stateMan.RequestStateChange>(); - screen.Job = new ContentLoadReplayJob(1/60f, dir, resPath, _loadMan, screen); + screen.Job = new ContentLoadReplayJob(1/60f, fileReader, _loadMan, screen); screen.OnJobFinished += (_, e) => OnFinishedLoading(e); } diff --git a/Content.Client/Replay/LoadReplayJob.cs b/Content.Client/Replay/LoadReplayJob.cs index 1064008609a..50615212783 100644 --- a/Content.Client/Replay/LoadReplayJob.cs +++ b/Content.Client/Replay/LoadReplayJob.cs @@ -12,11 +12,10 @@ public sealed class ContentLoadReplayJob : LoadReplayJob public ContentLoadReplayJob( float maxTime, - IWritableDirProvider dir, - ResPath path, + IReplayFileReader fileReader, IReplayLoadManager loadMan, LoadingScreen screen) - : base(maxTime, dir, path, loadMan) + : base(maxTime, fileReader, loadMan) { _screen = screen; } diff --git a/Content.Replay/Menu/ReplayMainMenu.cs b/Content.Replay/Menu/ReplayMainMenu.cs index 096abb69716..5792c1bc018 100644 --- a/Content.Replay/Menu/ReplayMainMenu.cs +++ b/Content.Replay/Menu/ReplayMainMenu.cs @@ -1,3 +1,4 @@ +using System.IO.Compression; using System.Linq; using Content.Client.Message; using Content.Client.UserInterface.Systems.EscapeMenu; @@ -13,7 +14,7 @@ using Robust.Shared.ContentPack; using Robust.Shared.Serialization.Markdown.Value; using Robust.Shared.Utility; -using static Robust.Shared.Replays.IReplayRecordingManager; +using static Robust.Shared.Replays.ReplayConstants; namespace Content.Replay.Menu; @@ -71,8 +72,10 @@ private void UpdateSelectedInfo() return; } + using var fileReader = new ReplayFileReaderZip( + new ZipArchive(_resMan.UserData.OpenRead(replay)), ReplayZipFolder); if (!_resMan.UserData.Exists(replay) - || _loadMan.LoadYamlMetadata(_resMan.UserData, replay) is not { } data) + || _loadMan.LoadYamlMetadata(fileReader) is not { } data) { info.SetMarkup(Loc.GetString("replay-info-invalid")); info.HorizontalAlignment = Control.HAlignment.Center; @@ -82,16 +85,16 @@ private void UpdateSelectedInfo() } var file = replay.ToRelativePath().ToString(); - data.TryGet(Time, out var timeNode); - data.TryGet(Duration, out var durationNode); + data.TryGet(MetaKeyTime, out var timeNode); + data.TryGet(MetaFinalKeyDuration, out var durationNode); data.TryGet("roundId", out var roundIdNode); - data.TryGet(Hash, out var hashNode); - data.TryGet(CompHash, out var compHashNode); + data.TryGet(MetaKeyTypeHash, out var hashNode); + data.TryGet(MetaKeyComponentHash, out var compHashNode); DateTime.TryParse(timeNode?.Value, out var time); TimeSpan.TryParse(durationNode?.Value, out var duration); var forkId = string.Empty; - if (data.TryGet(Fork, out var forkNode)) + if (data.TryGet(MetaKeyForkId, out var forkNode)) { // TODO Replay client build info. // When distributing the client we need to distribute a build.json or provide these cvars some other way? @@ -105,7 +108,7 @@ private void UpdateSelectedInfo() } var forkVersion = string.Empty; - if (data.TryGet(ForkVersion, out var versionNode)) + if (data.TryGet(MetaKeyForkVersion, out var versionNode)) { forkVersion = versionNode.Value; // Why does this not have a try-convert function? I just want to check if it looks like a hash code. @@ -162,7 +165,7 @@ private void UpdateSelectedInfo() } var engineVersion = string.Empty; - if (data.TryGet(Engine, out var engineNode)) + if (data.TryGet(MetaKeyEngineVersion, out var engineNode)) { var clientVer = _cfg.GetCVar(CVars.BuildEngineVersion); if (string.IsNullOrWhiteSpace(clientVer)) @@ -176,7 +179,7 @@ private void UpdateSelectedInfo() // Strip milliseconds. Apparently there is no general format string that suppresses milliseconds. duration = new((int)Math.Floor(duration.TotalDays), duration.Hours, duration.Minutes, duration.Seconds); - data.TryGet(Name, out var nameNode); + data.TryGet(MetaKeyName, out var nameNode); var name = nameNode?.Value ?? string.Empty; info.HorizontalAlignment = Control.HAlignment.Left; @@ -205,7 +208,11 @@ private void OnFolderPressed(BaseButton.ButtonEventArgs obj) private void OnLoadpressed(BaseButton.ButtonEventArgs obj) { if (_selected.HasValue) - _loadMan.LoadAndStartReplay(_resMan.UserData, _selected.Value); + { + var fileReader = new ReplayFileReaderZip( + new ZipArchive(_resMan.UserData.OpenRead(_selected.Value)), ReplayZipFolder); + _loadMan.LoadAndStartReplay(fileReader); + } } private void RefreshReplays() @@ -217,11 +224,14 @@ private void RefreshReplays() var file = _directory / entry; try { - var data = _loadMan.LoadYamlMetadata(_resMan.UserData, file); + using var fileReader = new ReplayFileReaderZip( + new ZipArchive(_resMan.UserData.OpenRead(file)), ReplayZipFolder); + + var data = _loadMan.LoadYamlMetadata(fileReader); if (data == null) continue; - var name = data.Get(Name).Value; + var name = data.Get(MetaKeyName).Value; _replays.Add((name, file)); } diff --git a/Resources/manifest.yml b/Resources/manifest.yml index 88c9243624a..67991181939 100644 --- a/Resources/manifest.yml +++ b/Resources/manifest.yml @@ -2,9 +2,4 @@ windowIconSet: /Textures/Logo/icon splashLogo: /Textures/Logo/logo.png -clientAssemblies: - - Content.Client - - Content.Shared - - Content.Shared.Database - # PJB PLEASE