BITKit/Src/Unity/Scripts/Assets/YooAssetModHelper.cs

166 lines
6.3 KiB
C#

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing.Printing;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using BITKit.Mod;
using Cysharp.Threading.Tasks;
using Microsoft.Extensions.Logging;
using UnityEditor;
using UnityEngine;
using YooAsset;
using ILogger = Microsoft.Extensions.Logging.ILogger;
using Object = UnityEngine.Object;
namespace BITKit.IO
{
public class YooAssetModHelper
{
public static string Url = "http://server.bitfall.icu:21982/com.project.b/Mods";
public static readonly ConcurrentDictionary<string, HashSet<string>> PackagesManifestDictionary = new();
public static async UniTask LoadMods(ILogger logger=null)
{
try
{
var modPath = Path.Combine(Environment.CurrentDirectory, "Mods");
if (Application.platform is RuntimePlatform.Android)
{
modPath = Path.Combine($"/storage/emulated/0/{Application.identifier}/Mods/");
}
foreach (var directoryInfo in new DirectoryInfo(modPath).GetDirectories())
{
var packageName = directoryInfo.Name;
logger?.LogInformation($"开始加载:{packageName}");
var package = YooAssets.CreatePackage(packageName);
var initPars = new HostPlayModeParameters()
{
BuildinQueryServices = new GameQueryServices(),
RemoteServices = new RemoteServices($"{Url}/{directoryInfo.Name}",$"file://{directoryInfo.FullName}")
};
await package.InitializeAsync(initPars);
var update = package.UpdatePackageVersionAsync();
await update.ToUniTask();
var manifest = package.UpdatePackageManifestAsync(update.PackageVersion);
await manifest.ToUniTask();
var downloader = package.CreateResourceDownloader(10, 3);
if (logger is not null)
{
downloader.OnDownloadProgressCallback = (totalDownloadCount, currentDownloadCount,
totalDownloadBytes, currentDownloadBytes) =>
{
//下载进度
var progress = (float)currentDownloadBytes / totalDownloadBytes;
logger.LogInformation($"已下载{(int)(progress*100)}%,资源数量{currentDownloadBytes}/{totalDownloadBytes}");
};
downloader.OnDownloadErrorCallback = (fileName, error) =>
{
logger.LogError($"资源[{fileName}]下载错误::{error}");
};
}
downloader.BeginDownload();
await downloader.ToUniTask();
var mod = new MyMod()
{
FolderPath = directoryInfo.FullName,
PackageName = packageName,
Name = packageName
};
await ModService.Install(mod);
await ModService.Load(mod);
YooAssetUtils.RegisterResourcePackage(package);
logger?.LogInformation($"已加载:{packageName},路径:{directoryInfo.FullName}");
}
return;
}
catch (Exception e)
{
if (logger is not null)
{
logger.LogCritical(e.Message,e);
}
else
{
BIT4Log.LogException(e);
}
}
logger?.LogInformation($"未找到Mod");
}
private static HashSet<string> BuildPackageCache(string obj)
{
var package = YooAssets.GetPackage(obj);
var playMode = package.GetType().GetField("_playModeImpl", ReflectionHelper.Flags)!.GetValue(package);
var manifest = playMode.GetType().GetProperty("ActiveManifest", ReflectionHelper.Flags)!.GetValue(playMode);
var dictionary = manifest.GetType().GetField("AssetDic", ReflectionHelper.Flags)!.GetValue(manifest) as IDictionary;
var hashset = new HashSet<string>();
foreach (var key in dictionary.Keys)
{
hashset.Add(key?.ToString());
}
var assetPathMapping1=manifest.GetType().GetField("AssetPathMapping1", ReflectionHelper.Flags)!.GetValue(manifest) as IDictionary<string,string>;
foreach (var key in assetPathMapping1.Keys)
{
hashset.Add(key);
}
return hashset;
}
public static async UniTask<IReadOnlyList<object>> LoadAssets( string[] arg)
{
var list = new List<object>();
foreach (var resourcePackage in YooAssetUtils.RegisteredResourcePackages)
{
foreach (var assetInfo in resourcePackage.GetAssetInfos(arg))
{
var asyncHandle = resourcePackage.LoadAssetAsync(assetInfo);
await asyncHandle;
list.Add(asyncHandle.AssetObject);
}
}
return list;
}
public static async UniTask<object> LoadAsset(string arg)
{
foreach (var resourcePackage in YooAssetUtils.RegisteredResourcePackages.Reverse())
{
if(PackagesManifestDictionary.GetOrAdd(resourcePackage.PackageName,BuildPackageCache).Contains(arg) is false)continue;
var assetInfo = resourcePackage.GetAssetInfo(arg);
if(string.IsNullOrEmpty(assetInfo.Error) is false)continue;
var handle = resourcePackage.LoadAssetAsync(arg);
await handle;
return handle.AssetObject;
}
return null;
}
}
}