update extension sample

抖音小游戏文件重命名
This commit is contained in:
何冠峰
2025-02-07 16:21:25 +08:00
parent a02b3fbf6e
commit 6e8cb0366d
25 changed files with 169 additions and 171 deletions
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8cba5e0b26df8ee40a93d697f889e33d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,101 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using UnityEngine;
using UnityEngine.Networking;
using YooAsset;
internal class TTFSDownloadFileOperation : DefaultDownloadFileOperation
{
private TiktokFileSystem _fileSystem;
private ESteps _steps = ESteps.None;
internal TTFSDownloadFileOperation(TiktokFileSystem fileSystem, PackageBundle bundle, DownloadParam param) : base(bundle, param)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
_steps = ESteps.CreateRequest;
}
internal override void InternalOnUpdate()
{
// 创建下载器
if (_steps == ESteps.CreateRequest)
{
// 获取请求地址
_requestURL = GetRequestURL();
// 重置变量
ResetRequestFiled();
// 创建下载器
CreateWebRequest();
_steps = ESteps.CheckRequest;
}
// 检测下载结果
if (_steps == ESteps.CheckRequest)
{
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = (long)_webRequest.downloadedBytes;
Progress = DownloadProgress;
if (_webRequest.isDone == false)
{
CheckRequestTimeout();
return;
}
// 检查网络错误
if (CheckRequestResult())
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.TryAgain;
}
// 注意:最终释放请求器
DisposeWebRequest();
}
// 重新尝试下载
if (_steps == ESteps.TryAgain)
{
if (FailedTryAgain <= 0)
{
Status = EOperationStatus.Failed;
_steps = ESteps.Done;
YooLogger.Error(Error);
return;
}
_tryAgainTimer += Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
FailedTryAgain--;
_steps = ESteps.CreateRequest;
YooLogger.Warning(Error);
}
}
}
private void CreateWebRequest()
{
//TODO : 抖音小游戏没有找到预下载方法
_webRequest = UnityWebRequestAssetBundle.GetAssetBundle(_requestURL);
_webRequest.disposeDownloadHandlerOnDispose = true;
_webRequest.SendWebRequest();
}
private void DisposeWebRequest()
{
if (_webRequest != null)
{
//注意:引擎底层会自动调用Abort方法
_webRequest.Dispose();
_webRequest = null;
}
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0bdf53359f9e17b41b08982a2be2098c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,55 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using YooAsset;
internal partial class TTFSInitializeOperation : FSInitializeFileSystemOperation
{
private enum ESteps
{
None,
RecordCacheFiles,
Done,
}
private readonly TiktokFileSystem _fileSystem;
private RecordTiktokCacheFilesOperation _recordTiktokCacheFilesOp;
private ESteps _steps = ESteps.None;
public TTFSInitializeOperation(TiktokFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
_steps = ESteps.RecordCacheFiles;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RecordCacheFiles)
{
if (_recordTiktokCacheFilesOp == null)
{
_recordTiktokCacheFilesOp = new RecordTiktokCacheFilesOperation(_fileSystem);
OperationSystem.StartOperation(_fileSystem.PackageName, _recordTiktokCacheFilesOp);
}
if (_recordTiktokCacheFilesOp.IsDone == false)
return;
if (_recordTiktokCacheFilesOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _recordTiktokCacheFilesOp.Error;
}
}
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 614227bf558da7149a7eb6de7dfa1a21
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,112 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using UnityEngine;
using UnityEngine.Networking;
using YooAsset;
using TTSDK;
internal class TTFSLoadBundleOperation : FSLoadBundleOperation
{
private enum ESteps
{
None,
LoadBundleFile,
Done,
}
private readonly TiktokFileSystem _fileSystem;
private readonly PackageBundle _bundle;
private UnityWebRequest _webRequest;
private ESteps _steps = ESteps.None;
internal TTFSLoadBundleOperation(TiktokFileSystem fileSystem, PackageBundle bundle)
{
_fileSystem = fileSystem;
_bundle = bundle;
}
internal override void InternalOnStart()
{
_steps = ESteps.LoadBundleFile;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadBundleFile)
{
if (_webRequest == null)
{
string mainURL = _fileSystem.RemoteServices.GetRemoteMainURL(_bundle.FileName);
_webRequest = TTAssetBundle.GetAssetBundle(mainURL);
_webRequest.SendWebRequest();
}
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = (long)_webRequest.downloadedBytes;
Progress = DownloadProgress;
if (_webRequest.isDone == false)
return;
if (CheckRequestResult())
{
var assetBundle = (_webRequest.downloadHandler as DownloadHandlerTTAssetBundle).assetBundle;
if (assetBundle == null)
{
_steps = ESteps.Done;
Error = $"{nameof(DownloadHandlerTTAssetBundle)} loaded asset bundle is null !";
Status = EOperationStatus.Failed;
}
else
{
_steps = ESteps.Done;
Result = new AssetBundleResult(_fileSystem, _bundle, assetBundle, null);
Status = EOperationStatus.Succeed;
}
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
}
}
}
internal override void InternalWaitForAsyncComplete()
{
if (_steps != ESteps.Done)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "WebGL platform not support sync load method !";
UnityEngine.Debug.LogError(Error);
}
}
public override void AbortDownloadOperation()
{
}
private bool CheckRequestResult()
{
#if UNITY_2020_3_OR_NEWER
if (_webRequest.result != UnityWebRequest.Result.Success)
{
Error = _webRequest.error;
return false;
}
else
{
return true;
}
#else
if (_webRequest.isNetworkError || _webRequest.isHttpError)
{
Error = _webRequest.error;
return false;
}
else
{
return true;
}
#endif
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 19997de7b89b54445961e8b973f43ab3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,88 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using YooAsset;
internal class TTFSLoadPackageManifestOperation : FSLoadPackageManifestOperation
{
private enum ESteps
{
None,
RequestPackageHash,
LoadPackageManifest,
Done,
}
private readonly TiktokFileSystem _fileSystem;
private readonly string _packageVersion;
private readonly int _timeout;
private RequestTiktokPackageHashOperation _requestPackageHashOp;
private LoadTiktokPackageManifestOperation _loadPackageManifestOp;
private ESteps _steps = ESteps.None;
public TTFSLoadPackageManifestOperation(TiktokFileSystem fileSystem, string packageVersion, int timeout)
{
_fileSystem = fileSystem;
_packageVersion = packageVersion;
_timeout = timeout;
}
internal override void InternalOnStart()
{
_steps = ESteps.RequestPackageHash;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestPackageHash)
{
if (_requestPackageHashOp == null)
{
_requestPackageHashOp = new RequestTiktokPackageHashOperation(_fileSystem, _packageVersion, _timeout);
OperationSystem.StartOperation(_fileSystem.PackageName, _requestPackageHashOp);
}
if (_requestPackageHashOp.IsDone == false)
return;
if (_requestPackageHashOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.LoadPackageManifest;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _requestPackageHashOp.Error;
}
}
if (_steps == ESteps.LoadPackageManifest)
{
if (_loadPackageManifestOp == null)
{
string packageHash = _requestPackageHashOp.PackageHash;
_loadPackageManifestOp = new LoadTiktokPackageManifestOperation(_fileSystem, _packageVersion, packageHash, _timeout);
OperationSystem.StartOperation(_fileSystem.PackageName, _loadPackageManifestOp);
}
Progress = _loadPackageManifestOp.Progress;
if (_loadPackageManifestOp.IsDone == false)
return;
if (_loadPackageManifestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Manifest = _loadPackageManifestOp.Manifest;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _loadPackageManifestOp.Error;
}
}
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2850c0b0e742f824f9d1f12b7d68b806
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,60 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using YooAsset;
internal class TTFSRequestPackageVersionOperation : FSRequestPackageVersionOperation
{
private enum ESteps
{
None,
RequestPackageVersion,
Done,
}
private readonly TiktokFileSystem _fileSystem;
private readonly int _timeout;
private RequestTiktokPackageVersionOperation _requestPackageVersionOp;
private ESteps _steps = ESteps.None;
internal TTFSRequestPackageVersionOperation(TiktokFileSystem fileSystem, int timeout)
{
_fileSystem = fileSystem;
_timeout = timeout;
}
internal override void InternalOnStart()
{
_steps = ESteps.RequestPackageVersion;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestPackageVersion)
{
if (_requestPackageVersionOp == null)
{
_requestPackageVersionOp = new RequestTiktokPackageVersionOperation(_fileSystem, _timeout);
OperationSystem.StartOperation(_fileSystem.PackageName, _requestPackageVersionOp);
}
Progress = _requestPackageVersionOp.Progress;
if (_requestPackageVersionOp.IsDone == false)
return;
if (_requestPackageVersionOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
PackageVersion = _requestPackageVersionOp.PackageVersion;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _requestPackageVersionOp.Error;
}
}
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8210185faba92a3479bf6713abab1f19
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 101c97835f86e9147993961f514caf2c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,125 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using YooAsset;
internal class LoadTiktokPackageManifestOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RequestFileData,
VerifyFileData,
LoadManifest,
Done,
}
private readonly TiktokFileSystem _fileSystem;
private readonly string _packageVersion;
private readonly string _packageHash;
private readonly int _timeout;
private UnityWebDataRequestOperation _webDataRequestOp;
private DeserializeManifestOperation _deserializer;
private int _requestCount = 0;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹清单
/// </summary>
public PackageManifest Manifest { private set; get; }
internal LoadTiktokPackageManifestOperation(TiktokFileSystem fileSystem, string packageVersion, string packageHash, int timeout)
{
_fileSystem = fileSystem;
_packageVersion = packageVersion;
_packageHash = packageHash;
_timeout = timeout;
}
internal override void InternalOnStart()
{
_requestCount = WebRequestCounter.GetRequestFailedCount(_fileSystem.PackageName, nameof(LoadTiktokPackageManifestOperation));
_steps = ESteps.RequestFileData;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestFileData)
{
if (_webDataRequestOp == null)
{
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_fileSystem.PackageName, _packageVersion);
string url = GetRequestURL(fileName);
_webDataRequestOp = new UnityWebDataRequestOperation(url, _timeout);
OperationSystem.StartOperation(_fileSystem.PackageName, _webDataRequestOp);
}
Progress = _webDataRequestOp.Progress;
if (_webDataRequestOp.IsDone == false)
return;
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.VerifyFileData;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webDataRequestOp.Error;
WebRequestCounter.RecordRequestFailed(_fileSystem.PackageName, nameof(LoadTiktokPackageManifestOperation));
}
}
if (_steps == ESteps.VerifyFileData)
{
string fileHash = HashUtility.BytesCRC32(_webDataRequestOp.Result);
if (fileHash == _packageHash)
{
_steps = ESteps.LoadManifest;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Failed to verify package manifest file!";
}
}
if (_steps == ESteps.LoadManifest)
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_webDataRequestOp.Result);
OperationSystem.StartOperation(_fileSystem.PackageName, _deserializer);
}
Progress = _deserializer.Progress;
if (_deserializer.IsDone == false)
return;
if (_deserializer.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Manifest = _deserializer.Manifest;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _deserializer.Error;
}
}
}
private string GetRequestURL(string fileName)
{
// 轮流返回请求地址
if (_requestCount % 2 == 0)
return _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
else
return _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b648d648fa0c4e44d811b42b80891543
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,57 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using YooAsset;
using TTSDK;
internal class RecordTiktokCacheFilesOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RecordCacheFiles,
WaitResponse,
Done,
}
private readonly TiktokFileSystem _fileSystem;
private ESteps _steps = ESteps.None;
public RecordTiktokCacheFilesOperation(TiktokFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
_steps = ESteps.RecordCacheFiles;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RecordCacheFiles)
{
_steps = ESteps.WaitResponse;
var fileSystemMgr = _fileSystem.GetFileSystemMgr();
var getSavedFileListParam = new GetSavedFileListParam();
getSavedFileListParam.success = (TTGetSavedFileListResponse response) =>
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
foreach (var fileInfo in response.fileList)
{
//TODO 需要确认存储文件为Bundle文件
_fileSystem.RecordBundleFile(fileInfo.filePath);
}
};
getSavedFileListParam.fail = (TTGetSavedFileListResponse response) =>
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = response.errMsg;
};
fileSystemMgr.GetSavedFileList(getSavedFileListParam);
}
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e4420bd73f37dec468a9b23425be68f2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,90 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using YooAsset;
internal class RequestTiktokPackageHashOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RequestPackageHash,
Done,
}
private readonly TiktokFileSystem _fileSystem;
private readonly string _packageVersion;
private readonly int _timeout;
private UnityWebTextRequestOperation _webTextRequestOp;
private int _requestCount = 0;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹哈希值
/// </summary>
public string PackageHash { private set; get; }
public RequestTiktokPackageHashOperation(TiktokFileSystem fileSystem, string packageVersion, int timeout)
{
_fileSystem = fileSystem;
_packageVersion = packageVersion;
_timeout = timeout;
}
internal override void InternalOnStart()
{
_requestCount = WebRequestCounter.GetRequestFailedCount(_fileSystem.PackageName, nameof(RequestTiktokPackageHashOperation));
_steps = ESteps.RequestPackageHash;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestPackageHash)
{
if (_webTextRequestOp == null)
{
string fileName = YooAssetSettingsData.GetPackageHashFileName(_fileSystem.PackageName, _packageVersion);
string url = GetRequestURL(fileName);
_webTextRequestOp = new UnityWebTextRequestOperation(url, _timeout);
OperationSystem.StartOperation(_fileSystem.PackageName, _webTextRequestOp);
}
Progress = _webTextRequestOp.Progress;
if (_webTextRequestOp.IsDone == false)
return;
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
{
PackageHash = _webTextRequestOp.Result;
if (string.IsNullOrEmpty(PackageHash))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Wechat package hash file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webTextRequestOp.Error;
WebRequestCounter.RecordRequestFailed(_fileSystem.PackageName, nameof(RequestTiktokPackageHashOperation));
}
}
}
private string GetRequestURL(string fileName)
{
// 轮流返回请求地址
if (_requestCount % 2 == 0)
return _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
else
return _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 51a0e40e248b49a4783b3dca33a23cf1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,88 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using YooAsset;
internal class RequestTiktokPackageVersionOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RequestPackageVersion,
Done,
}
private readonly TiktokFileSystem _fileSystem;
private readonly int _timeout;
private UnityWebTextRequestOperation _webTextRequestOp;
private int _requestCount = 0;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹版本
/// </summary>
public string PackageVersion { private set; get; }
public RequestTiktokPackageVersionOperation(TiktokFileSystem fileSystem, int timeout)
{
_fileSystem = fileSystem;
_timeout = timeout;
}
internal override void InternalOnStart()
{
_requestCount = WebRequestCounter.GetRequestFailedCount(_fileSystem.PackageName, nameof(RequestTiktokPackageVersionOperation));
_steps = ESteps.RequestPackageVersion;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestPackageVersion)
{
if (_webTextRequestOp == null)
{
string fileName = YooAssetSettingsData.GetPackageVersionFileName(_fileSystem.PackageName);
string url = GetRequestURL(fileName);
_webTextRequestOp = new UnityWebTextRequestOperation(url, _timeout);
OperationSystem.StartOperation(_fileSystem.PackageName, _webTextRequestOp);
}
Progress = _webTextRequestOp.Progress;
if (_webTextRequestOp.IsDone == false)
return;
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
{
PackageVersion = _webTextRequestOp.Result;
if (string.IsNullOrEmpty(PackageVersion))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Wechat package version file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webTextRequestOp.Error;
WebRequestCounter.RecordRequestFailed(_fileSystem.PackageName, nameof(RequestTiktokPackageVersionOperation));
}
}
}
private string GetRequestURL(string fileName)
{
// 轮流返回请求地址
if (_requestCount % 2 == 0)
return _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
else
return _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a04c463fb00f60f499541fbb98e4fdc4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,285 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
using TTSDK;
using System.Linq;
using System;
public static class TiktokFileSystemCreater
{
public static FileSystemParameters CreateByteGameFileSystemParameters(IRemoteServices remoteServices, string packageRoot)
{
string fileSystemClass = $"{nameof(TiktokFileSystem)},YooAsset.RuntimeExtension";
var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot);
fileSystemParams.AddParameter("REMOTE_SERVICES", remoteServices);
return fileSystemParams;
}
}
/// <summary>
/// 抖音小游戏文件系统
/// 参考:https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/guide/know
/// </summary>
internal class TiktokFileSystem : IFileSystem
{
private class WebRemoteServices : IRemoteServices
{
private readonly string _webPackageRoot;
protected readonly Dictionary<string, string> _mapping = new Dictionary<string, string>(10000);
public WebRemoteServices(string buildinPackRoot)
{
_webPackageRoot = buildinPackRoot;
}
string IRemoteServices.GetRemoteMainURL(string fileName)
{
return GetFileLoadURL(fileName);
}
string IRemoteServices.GetRemoteFallbackURL(string fileName)
{
return GetFileLoadURL(fileName);
}
private string GetFileLoadURL(string fileName)
{
if (_mapping.TryGetValue(fileName, out string url) == false)
{
string filePath = PathUtility.Combine(_webPackageRoot, fileName);
url = DownloadSystemHelper.ConvertToWWWPath(filePath);
_mapping.Add(fileName, url);
}
return url;
}
}
private readonly HashSet<string> _recorders = new HashSet<string>();
private readonly Dictionary<string, string> _cacheFilePaths = new Dictionary<string, string>(10000);
private TTFileSystemManager _fileSystemMgr;
private string _ttCacheRoot = string.Empty;
/// <summary>
/// 包裹名称
/// </summary>
public string PackageName { private set; get; }
/// <summary>
/// 文件根目录
/// </summary>
public string FileRoot
{
get
{
return _ttCacheRoot;
}
}
/// <summary>
/// 文件数量
/// </summary>
public int FileCount
{
get
{
return _recorders.Count;
}
}
#region 自定义参数
/// <summary>
/// 自定义参数:远程服务接口
/// </summary>
public IRemoteServices RemoteServices { private set; get; } = null;
#endregion
public TiktokFileSystem()
{
}
public virtual FSInitializeFileSystemOperation InitializeFileSystemAsync()
{
var operation = new TTFSInitializeOperation(this);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
public virtual FSLoadPackageManifestOperation LoadPackageManifestAsync(string packageVersion, int timeout)
{
var operation = new TTFSLoadPackageManifestOperation(this, packageVersion, timeout);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
public virtual FSRequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks, int timeout)
{
var operation = new TTFSRequestPackageVersionOperation(this, timeout);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
public virtual FSClearCacheFilesOperation ClearCacheFilesAsync(PackageManifest manifest, string clearMode, object clearParam)
{
var operation = new FSClearCacheFilesCompleteOperation();
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
public virtual FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadParam param)
{
param.MainURL = RemoteServices.GetRemoteMainURL(bundle.FileName);
param.FallbackURL = RemoteServices.GetRemoteFallbackURL(bundle.FileName);
var operation = new TTFSDownloadFileOperation(this, bundle, param);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle)
{
if (bundle.BundleType == (int)EBuildBundleType.AssetBundle)
{
var operation = new TTFSLoadBundleOperation(this, bundle);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
else
{
string error = $"{nameof(TiktokFileSystem)} not support load bundle type : {bundle.BundleType}";
var operation = new FSLoadBundleCompleteOperation(error);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
}
public virtual void SetParameter(string name, object value)
{
if (name == "REMOTE_SERVICES")
{
RemoteServices = (IRemoteServices)value;
}
else
{
YooLogger.Warning($"Invalid parameter : {name}");
}
}
public virtual void OnCreate(string packageName, string rootDirectory)
{
PackageName = packageName;
_ttCacheRoot = rootDirectory;
if (string.IsNullOrEmpty(_ttCacheRoot))
{
throw new System.Exception("请配置抖音小游戏的缓存根目录!");
}
// 注意:CDN服务未启用的情况下,使用抖音WEB服务器
if (RemoteServices == null)
{
string webRoot = PathUtility.Combine(Application.streamingAssetsPath, YooAssetSettingsData.Setting.DefaultYooFolderName, packageName);
RemoteServices = new WebRemoteServices(webRoot);
}
_fileSystemMgr = TT.GetFileSystemManager();
}
public virtual void OnUpdate()
{
}
public virtual bool Belong(PackageBundle bundle)
{
return true;
}
public virtual bool Exists(PackageBundle bundle)
{
string filePath = GetCacheFileLoadPath(bundle);
return _recorders.Contains(filePath);
}
public virtual bool NeedDownload(PackageBundle bundle)
{
if (Belong(bundle) == false)
return false;
return Exists(bundle) == false;
}
public virtual bool NeedUnpack(PackageBundle bundle)
{
return false;
}
public virtual bool NeedImport(PackageBundle bundle)
{
return false;
}
public virtual string GetBundleFilePath(PackageBundle bundle)
{
return GetCacheFileLoadPath(bundle);
}
public virtual byte[] ReadBundleFileData(PackageBundle bundle)
{
string filePath = GetCacheFileLoadPath(bundle);
if (CheckCacheFileExist(filePath))
return _fileSystemMgr.ReadFileSync(filePath);
else
return Array.Empty<byte>();
}
public virtual string ReadBundleFileText(PackageBundle bundle)
{
string filePath = GetCacheFileLoadPath(bundle);
if (CheckCacheFileExist(filePath))
return _fileSystemMgr.ReadFileSync(filePath, "utf8");
else
return string.Empty;
}
#region 内部方法
public TTFileSystemManager GetFileSystemMgr()
{
return _fileSystemMgr;
}
public bool CheckCacheFileExist(string filePath)
{
return _fileSystemMgr.AccessSync(filePath);
}
private string GetCacheFileLoadPath(PackageBundle bundle)
{
if (_cacheFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false)
{
filePath = _fileSystemMgr.GetLocalCachedPathForUrl(bundle.FileName);
_cacheFilePaths.Add(bundle.BundleGUID, filePath);
}
return filePath;
}
#endregion
#region 本地记录
public List<string> GetAllRecords()
{
return _recorders.ToList();
}
public bool RecordBundleFile(string filePath)
{
if (_recorders.Contains(filePath))
{
YooLogger.Error($"{nameof(TiktokFileSystem)} has element : {filePath}");
return false;
}
_recorders.Add(filePath);
return true;
}
public void TryRecordBundle(PackageBundle bundle)
{
string filePath = GetCacheFileLoadPath(bundle);
if (_recorders.Contains(filePath) == false)
{
_recorders.Add(filePath);
}
}
public void ClearAllRecords()
{
_recorders.Clear();
}
public void ClearRecord(string filePath)
{
if (_recorders.Contains(filePath))
{
_recorders.Remove(filePath);
}
}
#endregion
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e6b4324eddc60f045aa271bc5bb50cc9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: