0
0
mirror of https://github.com/sp-tarkov/modules.git synced 2025-02-13 09:50:43 -05:00

Revert "Improve async bundles (!123)"

This reverts commit 9e65e68c81f47b05b29244f08d3cb2b9edc8616d.
This commit is contained in:
Dev 2024-05-12 23:03:30 +01:00
parent 9e65e68c81
commit 64296e3e62
3 changed files with 75 additions and 63 deletions

View File

@ -1,19 +1,21 @@
using System; using Aki.Reflection.Patching;
using System.Collections.Generic; using Diz.Jobs;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Diz.Resources; using Diz.Resources;
using JetBrains.Annotations; using JetBrains.Annotations;
using Newtonsoft.Json; using Newtonsoft.Json;
using UnityEngine; using UnityEngine;
using UnityEngine.Build.Pipeline; using UnityEngine.Build.Pipeline;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Aki.Common.Utils; using Aki.Common.Utils;
using Aki.Custom.Models; using Aki.Custom.Models;
using Aki.Custom.Utils; using Aki.Custom.Utils;
using Aki.Reflection.Patching;
using Aki.Reflection.Utils;
using DependencyGraph = DependencyGraph<IEasyBundle>; using DependencyGraph = DependencyGraph<IEasyBundle>;
using Aki.Reflection.Utils;
namespace Aki.Custom.Patches namespace Aki.Custom.Patches
{ {
@ -36,33 +38,40 @@ namespace Aki.Custom.Patches
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
return typeof(EasyAssets).GetMethod(nameof(EasyAssets.Create)); return typeof(EasyAssets).GetMethods(PatchConstants.PublicDeclaredFlags).SingleCustom(IsTargetMethod);
}
private static bool IsTargetMethod(MethodInfo mi)
{
var parameters = mi.GetParameters();
return (parameters.Length == 6
&& parameters[0].Name == "bundleLock"
&& parameters[1].Name == "defaultKey"
&& parameters[4].Name == "shouldExclude");
} }
[PatchPrefix] [PatchPrefix]
private static bool PatchPrefix(ref Task<EasyAssets> __result, GameObject gameObject, [CanBeNull] IBundleLock bundleLock, string defaultKey, string rootPath, private static bool PatchPrefix(ref Task __result, EasyAssets __instance, [CanBeNull] IBundleLock bundleLock, string defaultKey, string rootPath,
string platformName, [CanBeNull] Func<string, bool> shouldExclude, [CanBeNull] Func<string, Task> bundleCheck) string platformName, [CanBeNull] Func<string, bool> shouldExclude, [CanBeNull] Func<string, Task> bundleCheck)
{ {
var easyAsset = gameObject.AddComponent<EasyAssets>(); __result = Init(__instance, bundleLock, defaultKey, rootPath, platformName, shouldExclude, bundleCheck);
__result = Init(easyAsset, bundleLock, defaultKey, rootPath, platformName, shouldExclude, bundleCheck);
return false; return false;
} }
private static async Task<EasyAssets> Init(EasyAssets instance, [CanBeNull] IBundleLock bundleLock, string defaultKey, string rootPath, string platformName, [CanBeNull] Func<string, bool> shouldExclude, Func<string, Task> bundleCheck) private static async Task Init(EasyAssets instance, [CanBeNull] IBundleLock bundleLock, string defaultKey, string rootPath, string platformName, [CanBeNull] Func<string, bool> shouldExclude, Func<string, Task> bundleCheck)
{ {
// platform manifest // platform manifest
var eftBundlesPath = $"{rootPath.Replace("file:///", string.Empty).Replace("file://", string.Empty)}/{platformName}/"; var path = $"{rootPath.Replace("file:///", string.Empty).Replace("file://", string.Empty)}/{platformName}/";
var filepath = eftBundlesPath + platformName; var filepath = path + platformName;
var jsonfile = filepath + ".json"; var jsonfile = filepath + ".json";
var manifest = VFS.Exists(jsonfile) var manifest = File.Exists(jsonfile)
? await GetManifestJson(jsonfile) ? await GetManifestJson(jsonfile)
: await GetManifestBundle(filepath); : await GetManifestBundle(filepath);
// lazy-initialize aki bundles // lazy-initialize aki bundles
if (BundleManager.Bundles.Keys.Count == 0) if (BundleManager.Bundles.Keys.Count == 0)
{ {
await BundleManager.DownloadManifest(); await BundleManager.GetBundles();
} }
// create bundles array from obfuscated type // create bundles array from obfuscated type
@ -76,43 +85,27 @@ namespace Aki.Custom.Patches
bundleLock = new BundleLock(int.MaxValue); bundleLock = new BundleLock(int.MaxValue);
} }
// create bundle of obfuscated type
var bundles = (IEasyBundle[])Array.CreateInstance(EasyBundleHelper.Type, bundleNames.Length); var bundles = (IEasyBundle[])Array.CreateInstance(EasyBundleHelper.Type, bundleNames.Length);
for (var i = 0; i < bundleNames.Length; i++) for (var i = 0; i < bundleNames.Length; i++)
{ {
var key = bundleNames[i];
var path = eftBundlesPath;
// acquire external bundle
if (BundleManager.Bundles.TryGetValue(key, out var bundleInfo))
{
// we need base path without file extension
path = BundleManager.GetBundlePath(bundleInfo);
// only download when connected externally
if (await BundleManager.ShouldReaquire(bundleInfo))
{
await BundleManager.DownloadBundle(bundleInfo);
}
}
// create bundle of obfuscated type
bundles[i] = (IEasyBundle)Activator.CreateInstance(EasyBundleHelper.Type, new object[] bundles[i] = (IEasyBundle)Activator.CreateInstance(EasyBundleHelper.Type, new object[]
{ {
key, bundleNames[i],
path, path,
manifest, manifest,
bundleLock, bundleLock,
bundleCheck bundleCheck
}); });
await JobScheduler.Yield(EJobPriority.Immediate);
} }
// create dependency graph // create dependency graph
instance.Manifest = manifest; instance.Manifest = manifest;
_bundlesField.SetValue(instance, bundles); _bundlesField.SetValue(instance, bundles);
instance.System = new DependencyGraph(bundles, defaultKey, shouldExclude); instance.System = new DependencyGraph(bundles, defaultKey, shouldExclude);
return instance;
} }
// NOTE: used by: // NOTE: used by:

View File

@ -1,12 +1,12 @@
using System; using System;
using Aki.Reflection.Patching;
using Diz.DependencyManager;
using UnityEngine.Build.Pipeline;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Diz.DependencyManager;
using UnityEngine.Build.Pipeline;
using Aki.Custom.Models; using Aki.Custom.Models;
using Aki.Custom.Utils; using Aki.Custom.Utils;
using Aki.Reflection.Patching;
namespace Aki.Custom.Patches namespace Aki.Custom.Patches
{ {
@ -38,7 +38,7 @@ namespace Aki.Custom.Patches
: bundle.Dependencies; : bundle.Dependencies;
// set path to either cache (HTTP) or mod (local) // set path to either cache (HTTP) or mod (local)
filepath = BundleManager.GetBundleFilePath(bundle); filepath = BundleManager.GetBundlePath(bundle);
} }
_ = new EasyBundleHelper(__instance) _ = new EasyBundleHelper(__instance)

View File

@ -10,51 +10,74 @@ namespace Aki.Custom.Utils
{ {
public static class BundleManager public static class BundleManager
{ {
private const string CachePath = "user/cache/bundles/";
private static readonly ManualLogSource _logger; private static readonly ManualLogSource _logger;
public static readonly ConcurrentDictionary<string, BundleItem> Bundles; public static readonly ConcurrentDictionary<string, BundleItem> Bundles;
public static string CachePath;
static BundleManager() static BundleManager()
{ {
_logger = Logger.CreateLogSource(nameof(BundleManager)); _logger = Logger.CreateLogSource(nameof(BundleManager));
Bundles = new ConcurrentDictionary<string, BundleItem>(); Bundles = new ConcurrentDictionary<string, BundleItem>();
CachePath = "user/cache/bundles/";
} }
public static string GetBundlePath(BundleItem bundle) public static string GetBundlePath(BundleItem bundle)
{ {
return RequestHandler.IsLocal return RequestHandler.IsLocal
? $"{bundle.ModPath}/bundles/{bundle.FileName}" ? $"{bundle.ModPath}/bundles/{bundle.FileName}"
: CachePath; : CachePath + bundle.FileName;
} }
public static string GetBundleFilePath(BundleItem bundle) public static async Task GetBundles()
{
return GetBundlePath(bundle) + bundle.FileName;
}
public static async Task DownloadManifest()
{ {
// get bundles // get bundles
var json = await RequestHandler.GetJsonAsync("/singleplayer/bundles"); var json = RequestHandler.GetJson("/singleplayer/bundles");
var bundles = JsonConvert.DeserializeObject<BundleItem[]>(json); var bundles = JsonConvert.DeserializeObject<BundleItem[]>(json);
// register bundles
var toDownload = new ConcurrentBag<BundleItem>();
foreach (var bundle in bundles) foreach (var bundle in bundles)
{ {
Bundles.TryAdd(bundle.FileName, bundle); Bundles.TryAdd(bundle.FileName, bundle);
if (await ShouldReaquire(bundle))
{
// mark for download
toDownload.Add(bundle);
}
}
if (RequestHandler.IsLocal)
{
// loading from local mods
_logger.LogInfo("CACHE: Loading all bundles from mods on disk.");
return;
}
else
{
// download bundles
// NOTE: assumes bundle keys to be unique
foreach (var bundle in toDownload)
{
// download bundle
var filepath = GetBundlePath(bundle);
var data = await RequestHandler.GetDataAsync($"/files/bundle/{bundle.FileName}");
await VFS.WriteFileAsync(filepath, data);
}
} }
} }
public static async Task DownloadBundle(BundleItem bundle) private static async Task<bool> ShouldReaquire(BundleItem bundle)
{ {
var filepath = GetBundleFilePath(bundle); if (RequestHandler.IsLocal)
var data = await RequestHandler.GetDataAsync($"/files/bundle/{bundle.FileName}"); {
await VFS.WriteFileAsync(filepath, data); // only handle remote bundles
} return false;
}
public static async Task<bool> ShouldReaquire(BundleItem bundle)
{
// read cache // read cache
var filepath = GetBundleFilePath(bundle); var filepath = CachePath + bundle.FileName;
if (VFS.Exists(filepath)) if (VFS.Exists(filepath))
{ {
@ -65,11 +88,7 @@ namespace Aki.Custom.Utils
if (crc == bundle.Crc) if (crc == bundle.Crc)
{ {
// file is up-to-date // file is up-to-date
var location = RequestHandler.IsLocal _logger.LogInfo($"CACHE: Loading locally {bundle.FileName}");
? "MOD"
: "CACHE";
_logger.LogInfo($"{location}: Loading locally {bundle.FileName}");
return false; return false;
} }
else else