Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions FModel/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ await Task.WhenAll(
await Task.WhenAll(
_applicationView.CUE4Parse.VerifyConsoleVariables(),
_applicationView.CUE4Parse.VerifyOnDemandArchives(),
_applicationView.CUE4Parse.VerifyCloudArchives(),
_applicationView.CUE4Parse.InitMappings(),
ApplicationViewModel.InitDetex(),
ApplicationViewModel.InitVgmStream(),
Expand Down
5 changes: 5 additions & 0 deletions FModel/ViewModels/ApiEndpoints/Models/FModelResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ public class ManifestInfoDilly
[J] public string DownloadUrl { get; private set; }
}

public class CloudContent
{
public string ManifestPath { get; private set; }
}

public class Donator
{
[J] public string Username { get; private set; }
Expand Down
58 changes: 58 additions & 0 deletions FModel/ViewModels/CUE4ParseViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
using FModel.Framework;
using FModel.Services;
using FModel.Settings;
using FModel.ViewModels.ApiEndpoints.Models;
using FModel.Views;
using FModel.Views.Resources.Controls;
using FModel.Views.Snooper;
Expand All @@ -88,6 +89,7 @@
using UE4Config.Parsing;
using Application = System.Windows.Application;
using FGuid = CUE4Parse.UE4.Objects.Core.Misc.FGuid;
using Version = System.Version;

namespace FModel.ViewModels;

Expand Down Expand Up @@ -372,6 +374,21 @@ private void RegisterFortniteLiveArchives(StreamedFileProvider provider, FBuildP
}
}

private void RegisterArchivesFromManifest(DefaultFileProvider provider, FBuildPatchAppManifest manifest)
{
var archiveFiles = manifest.Files.Where(x =>
_fnLiveRegex.IsMatch(x.FileName) &&
(x.FileName.EndsWith(".pak", StringComparison.OrdinalIgnoreCase) ||
x.FileName.EndsWith(".utoc", StringComparison.OrdinalIgnoreCase))).ToList();

Parallel.ForEach(archiveFiles, fileManifest =>
{
provider.RegisterVfs(fileManifest.FileName, [fileManifest.GetStream()],
it => new FRandomAccessStreamArchive(it, manifest.FindFile(it)!.GetStream(), provider.Versions));
});
}


/// <summary>
/// load virtual files system from GameDirectory
/// </summary>
Expand Down Expand Up @@ -551,6 +568,47 @@ public Task VerifyOnDemandArchives()
});
}

public Task VerifyCloudArchives()
{
if (Provider is not DefaultFileProvider p || !Provider.ProjectName.Equals("FortniteGame", StringComparison.OrdinalIgnoreCase))
return Task.CompletedTask;

var cloudContentPath = Path.Combine(UserSettings.Default.GameDirectory, "..\\..\\..\\Cloud\\cloudcontent.json");
if (!File.Exists(cloudContentPath))
return Task.CompletedTask;

return Task.Run(async () =>
{
var startTs = Stopwatch.GetTimestamp();

var cloudContent = JsonConvert.DeserializeObject<CloudContent>(await File.ReadAllTextAsync(cloudContentPath));
if (cloudContent is null || string.IsNullOrEmpty(cloudContent.ManifestPath))
return;

var manifestBytes = await _chunkClient.GetByteArrayAsync("https://egdownload.fastly-edge.com/" + cloudContent.ManifestPath);

var manifestOptions = new ManifestParseOptions
{
ChunkCacheDirectory = CacheManager.ChunksDirectory,
ManifestCacheDirectory = CacheManager.ManifestsDirectory,
ChunkBaseUrl = "https://egdownload.fastly-edge.com/Builds/Fortnite/CloudDir/",
Decompressor = Compression.Decompressor,
Client = _chunkClient,
CacheChunksAsIs = false
};

var contentManifest = FBuildPatchAppManifest.Deserialize(manifestBytes, manifestOptions);

RegisterArchivesFromManifest(p, contentManifest);

var cloudCount = await Provider.MountAsync();
var elapsedTime = Stopwatch.GetElapsedTime(startTs);

FLogger.Append(ELog.Information, () =>
FLogger.Text($"{cloudCount} cloud archive{(cloudCount > 1 ? "s" : "")} streamed via epicgames.com in {elapsedTime.TotalMilliseconds:F1}ms", Constants.WHITE, true));
});
}

public int LocalizedResourcesCount { get; set; }
public bool LocalResourcesDone { get; set; }
public bool HotfixedResourcesDone { get; set; }
Expand Down