// Copyright (c) 2020 Sergey Ivonchik // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE // OR OTHER DEALINGS IN THE SOFTWARE. using System; using System.Linq; using Httx.Requests.Awaiters.Async; using Httx.Requests.Extensions; using Httx.Utils; using UnityEngine; using UnityEngine.Networking; namespace Httx.Requests.Awaiters { public class UnityWebRequestAssetBundleAwaiter : BaseUnityAwaiter { private const string ManifestAsset = "assetbundlemanifest"; private string currentBundleUrl; public UnityWebRequestAssetBundleAwaiter(IRequest request) : base(request) { } public override IAsyncOperation Awake(IRequest request) { var verb = request.ResolveVerb(); var url = request.ResolveUrl(); var headers = request.ResolveHeaders()?.ToList(); currentBundleUrl = url; var crc = headers.FetchHeader(InternalHeaders.AssetBundleCrc); var version = headers.FetchHeader(InternalHeaders.AssetBundleVersion); var hash = headers.FetchHeader(InternalHeaders.AssetBundleHash); var isCacheEnabled = headers.FetchHeader(InternalHeaders.NativeCacheEnabled); var cache = Context.NativeCache; var cacheVersion = 0 != version ? version : cache.Version; var handler = new DownloadHandlerAssetBundle(url, crc); if (0 != cacheVersion && isCacheEnabled) { handler = new DownloadHandlerAssetBundle(url, cacheVersion, crc); } if (default != hash) { handler = new DownloadHandlerAssetBundle(url, hash, crc); } var requestImpl = new UnityWebRequest(url, verb) { downloadHandler = handler }; var isManifestRequest = headers.FetchHeader(InternalHeaders.AssetBundleLoadManifest); var requestOperation = new Func(_ => { AssetBundlePool.Instance.Release(url, false, Context); return new UnityAsyncOperation(() => Send(requestImpl, headers)); }); if (!isManifestRequest) { return requestOperation(null); } var manifestOperation = new Func(previous => { var bundle = MapAssetBundle(url, previous); return new UnityAsyncOperation(() => bundle.LoadAssetAsync(ManifestAsset)); }); return new AsyncOperationQueue(requestOperation, manifestOperation); } public override TResult Map(IRequest request, IAsyncOperation completeOperation) { if (typeof(TResult) == typeof(AssetBundle)) { return (TResult)(object)MapAssetBundle(currentBundleUrl, completeOperation); } if (typeof(TResult) == typeof(AssetBundleManifest)) { return (TResult)(object)MapAssetBundleManifest(completeOperation); } return default; } private AssetBundle MapAssetBundle(string url, IAsyncOperation operation) { var webRequest = (UnityWebRequest)operation.Result; var handler = (DownloadHandlerAssetBundle)webRequest.downloadHandler; var bundle = handler.assetBundle; if (null == bundle) { return bundle; } var pool = AssetBundlePool.Instance; pool.Retain(url, bundle.name, Context); return bundle; } private AssetBundleManifest MapAssetBundleManifest(IAsyncOperation operation) { return operation.Result as AssetBundleManifest; } } }