public static async Task <FetchResult> LoadTask(MonoBehaviour runner, Uri uri)
        {
            FetchResult result = new FetchResult()
            {
                Asset          = null,
                FailureMessage = null
            };
            var ifNoneMatch = MREAPI.AppsAPI.AssetCache.SupportsSync ?
                              MREAPI.AppsAPI.AssetCache.GetVersionSync(uri) :
                              await MREAPI.AppsAPI.AssetCache.GetVersion(uri);

            runner.StartCoroutine(LoadCoroutine());

            // Spin asynchronously until the request completes.
            while (!result.IsPopulated)
            {
                await Task.Delay(10);
            }

            // handle caching
            if (ifNoneMatch != null && result.ReturnCode == 304)
            {
                var assets = MREAPI.AppsAPI.AssetCache.SupportsSync ?
                             MREAPI.AppsAPI.AssetCache.LeaseAssetsSync(uri) :
                             await MREAPI.AppsAPI.AssetCache.LeaseAssets(uri);

                result.Asset = assets.FirstOrDefault() as T;
            }
            else if (result.Asset != null)
            {
                MREAPI.AppsAPI.AssetCache.StoreAssets(
                    uri,
                    new UnityEngine.Object[] { result.Asset as UnityEngine.Object },
                    result.ETag);
            }

            return(result);

            IEnumerator LoadCoroutine()
            {
                DownloadHandler handler;

                if (typeof(T) == typeof(UnityEngine.AudioClip))
                {
                    handler = new DownloadHandlerAudioClip(uri, AudioType.UNKNOWN);
                }
                else if (typeof(T) == typeof(UnityEngine.Texture))
                {
                    handler = new DownloadHandlerTexture(false);
                }
                else
                {
                    result.FailureMessage = $"Unknown download type: {typeof(T)}";
                    yield break;
                }

                // Spin asynchronously until the load throttler would allow us through.
                while (AssetLoadThrottling.WouldThrottle())
                {
                    yield return(null);
                }

                using (var scope = new AssetLoadThrottling.AssetLoadScope())
                    using (var www = new UnityWebRequest(uri, "GET", handler, null))
                    {
                        if (ifNoneMatch != null)
                        {
                            www.SetRequestHeader("If-None-Match", ifNoneMatch);
                        }

                        yield return(www.SendWebRequest());

                        if (www.isNetworkError)
                        {
                            result.ReturnCode     = -1;
                            result.FailureMessage = www.error;
                        }
                        else
                        {
                            result.ReturnCode = www.responseCode;
                            result.ETag       = www.GetResponseHeader("ETag") ?? "unversioned";

                            if (www.isHttpError)
                            {
                                result.FailureMessage = $"[{www.responseCode}] {uri}";
                            }
                            else if (www.responseCode >= 200 && www.responseCode <= 299)
                            {
                                if (typeof(T).IsAssignableFrom(typeof(UnityEngine.AudioClip)))
                                {
                                    result.Asset = ((DownloadHandlerAudioClip)handler).audioClip as T;
                                }
                                else if (typeof(T).IsAssignableFrom(typeof(UnityEngine.Texture)))
                                {
                                    result.Asset = ((DownloadHandlerTexture)handler).texture as T;
                                }
                            }
                        }
                    }
            }
        }
Beispiel #2
0
        public static async Task <FetchResult> LoadTask(MonoBehaviour runner, Uri uri)
        {
            FetchResult result = new FetchResult()
            {
                Asset          = null,
                FailureMessage = null
            };

            runner.StartCoroutine(LoadCoroutine());

            // Spin asynchronously until the request completes.
            while (!result.IsPopulated)
            {
                await Task.Delay(10);
            }

            return(result);

            IEnumerator LoadCoroutine()
            {
                DownloadHandler handler;

                if (typeof(T) == typeof(UnityEngine.AudioClip))
                {
                    handler = new DownloadHandlerAudioClip(uri, AudioType.UNKNOWN);
                }
                else if (typeof(T) == typeof(UnityEngine.Texture))
                {
                    handler = new DownloadHandlerTexture(false);
                }
                else
                {
                    result.FailureMessage = $"Unknown download type: {typeof(T)}";
                    yield break;
                }

                // Spin asynchronously until the load throttler would allow us through.
                while (AssetLoadThrottling.WouldThrottle())
                {
                    yield return(null);
                }

                using (var scope = new AssetLoadThrottling.AssetLoadScope())
                    using (var www = new UnityWebRequest(uri, "GET", handler, null))
                    {
                        yield return(www.SendWebRequest());

                        if (www.isNetworkError)
                        {
                            result.FailureMessage = www.error;
                        }
                        else if (www.isHttpError)
                        {
                            result.FailureMessage = $"[{www.responseCode}] {uri}";
                        }
                        else
                        {
                            if (typeof(T) == typeof(UnityEngine.AudioClip))
                            {
                                result.Asset = ((DownloadHandlerAudioClip)handler).audioClip as T;
                            }
                            else if (typeof(T) == typeof(UnityEngine.Texture))
                            {
                                result.Asset = ((DownloadHandlerTexture)handler).texture as T;
                            }
                        }
                    }
            }
        }
Beispiel #3
0
        public static async Task <FetchResult> LoadTask(MonoBehaviour runner, Uri uri)
        {
            // acquire the exclusive right to load this asset
            if (!await MREAPI.AppsAPI.AssetCache.AcquireLoadingLock(uri))
            {
                throw new TimeoutException("Failed to acquire exclusive loading rights for " + uri);
            }

            FetchResult result = new FetchResult()
            {
                Asset          = null,
                FailureMessage = null
            };
            var ifNoneMatch = MREAPI.AppsAPI.AssetCache.SupportsSync
                                ? MREAPI.AppsAPI.AssetCache.TryGetVersionSync(uri)
                                : await MREAPI.AppsAPI.AssetCache.TryGetVersion(uri);

            // if the cached version is unversioned, i.e. the server doesn't support ETags, don't bother making request
            if (ifNoneMatch == Constants.UnversionedAssetVersion)
            {
                var assets = MREAPI.AppsAPI.AssetCache.SupportsSync
                                        ? MREAPI.AppsAPI.AssetCache.LeaseAssetsSync(uri)
                                        : await MREAPI.AppsAPI.AssetCache.LeaseAssets(uri);

                result.Asset = assets.FirstOrDefault() as T;

                MREAPI.AppsAPI.AssetCache.ReleaseLoadingLock(uri);
                return(result);
            }

            runner.StartCoroutine(LoadCoroutine());

            // Spin asynchronously until the request completes.
            while (!result.IsPopulated)
            {
                await Task.Delay(10);
            }

            // handle caching
            if (!string.IsNullOrEmpty(ifNoneMatch) && result.ReturnCode == 304)
            {
                var assets = MREAPI.AppsAPI.AssetCache.SupportsSync
                                        ? MREAPI.AppsAPI.AssetCache.LeaseAssetsSync(uri)
                                        : await MREAPI.AppsAPI.AssetCache.LeaseAssets(uri);

                result.Asset = assets.FirstOrDefault() as T;
            }
            else if (result.Asset != null)
            {
                MREAPI.AppsAPI.AssetCache.StoreAssets(
                    uri,
                    new UnityEngine.Object[] { result.Asset },
                    result.ETag);
            }

            MREAPI.AppsAPI.AssetCache.ReleaseLoadingLock(uri);
            return(result);

            IEnumerator LoadCoroutine()
            {
                DownloadHandler handler;

                if (typeof(T) == typeof(UnityEngine.AudioClip))
                {
                    handler = new DownloadHandlerAudioClip(uri, AudioType.UNKNOWN);
                }
                else if (typeof(T) == typeof(UnityEngine.Texture))
                {
                    handler = new DownloadHandlerTexture(false);
                }
                else
                {
                    result.FailureMessage = $"Unknown download type: {typeof(T)}";
                    yield break;
                }

                // Spin asynchronously until the load throttler would allow us through.
                while (AssetLoadThrottling.WouldThrottle())
                {
                    yield return(null);
                }

                using (var scope = new AssetLoadThrottling.AssetLoadScope())
                    using (var www = new UnityWebRequest(uri, "GET", handler, null))
                    {
                        if (!string.IsNullOrEmpty(ifNoneMatch))
                        {
                            www.SetRequestHeader("If-None-Match", ifNoneMatch);
                        }

                        yield return(www.SendWebRequest());

                        if (www.isNetworkError)
                        {
                            result.ReturnCode     = -1;
                            result.FailureMessage = www.error;
                        }
                        else
                        {
                            result.ReturnCode = www.responseCode;
                            result.ETag       = www.GetResponseHeader("ETag") ?? Constants.UnversionedAssetVersion;

                            if (www.isHttpError)
                            {
                                result.FailureMessage = $"[{www.responseCode}] {uri}";
                            }
                            else if (www.responseCode >= 200 && www.responseCode <= 299)
                            {
                                if (typeof(T).IsAssignableFrom(typeof(UnityEngine.AudioClip)))
                                {
                                    result.Asset = ((DownloadHandlerAudioClip)handler).audioClip as T;
                                }
                                else if (typeof(T).IsAssignableFrom(typeof(UnityEngine.Texture)))
                                {
                                    result.Asset = ((DownloadHandlerTexture)handler).texture as T;
                                }
                            }
                        }
                    }
            }
        }
Beispiel #4
0
        public static async Task <FetchResult> LoadTask(Node runner, Uri uri)
        {
            // acquire the exclusive right to load this asset
            if (!await MREAPI.AppsAPI.AssetCache.AcquireLoadingLock(uri))
            {
                throw new TimeoutException("Failed to acquire exclusive loading rights for " + uri);
            }

            FetchResult result = new FetchResult()
            {
                Asset          = null,
                FailureMessage = null
            };
            var ifNoneMatch = MREAPI.AppsAPI.AssetCache.SupportsSync
                                ? MREAPI.AppsAPI.AssetCache.TryGetVersionSync(uri)
                                : await MREAPI.AppsAPI.AssetCache.TryGetVersion(uri);

            // if the cached version is unversioned, i.e. the server doesn't support ETags, don't bother making request
            if (ifNoneMatch == Constants.UnversionedAssetVersion)
            {
                var assets = MREAPI.AppsAPI.AssetCache.SupportsSync
                                        ? MREAPI.AppsAPI.AssetCache.LeaseAssetsSync(uri)
                                        : await MREAPI.AppsAPI.AssetCache.LeaseAssets(uri);

                result.Asset = assets.FirstOrDefault() as T;

                MREAPI.AppsAPI.AssetCache.ReleaseLoadingLock(uri);
                return(result);
            }

            await LoadCoroutine(runner);

            // handle caching
            if (!string.IsNullOrEmpty(ifNoneMatch) && result.ReturnCode == 304)
            {
                var assets = MREAPI.AppsAPI.AssetCache.SupportsSync
                                        ? MREAPI.AppsAPI.AssetCache.LeaseAssetsSync(uri)
                                        : await MREAPI.AppsAPI.AssetCache.LeaseAssets(uri);

                result.Asset = assets.FirstOrDefault() as T;
            }
            else if (result.Asset != null)
            {
                MREAPI.AppsAPI.AssetCache.StoreAssets(
                    uri,
                    new Godot.Object[] { result.Asset },
                    result.ETag);
            }

            MREAPI.AppsAPI.AssetCache.ReleaseLoadingLock(uri);
            return(result);

            async Task LoadCoroutine(Node runner)
            {
                DownloadHandler handler;

                if (typeof(T) == typeof(Godot.AudioStream))
                {
                    handler = new DownloadHandlerAudioStream(uri, AudioType.Unknown);
                }
                else if (typeof(T) == typeof(Godot.Texture))
                {
                    handler = new DownloadHandlerTexture(uri);
                }
                else
                {
                    result.FailureMessage = $"Unknown download type: {typeof(T)}";
                    return;
                }

                // Spin asynchronously until the load throttler would allow us through.
                while (AssetLoadThrottling.WouldThrottle())
                {
                    await runner.ToSignal(Engine.GetMainLoop(), "idle_frame");
                }

                using (var scope = new AssetLoadThrottling.AssetLoadScope())
                    using (var www = new GodotWebRequest(uri, HTTPClient.Method.Get, handler))
                    {
                        if (!string.IsNullOrEmpty(ifNoneMatch))
                        {
                            www.SetRequestHeader("If-None-Match", ifNoneMatch);
                        }

                        Error error = www.SendWebRequest();
                        if (error != 0)
                        {
                            result.ReturnCode     = -1;
                            result.FailureMessage = error.ToString();
                        }
                        else
                        {
                            result.ReturnCode = www.GetResponseCode();
                            result.ETag       = www.GetResponseHeader("ETag") ?? Constants.UnversionedAssetVersion;

                            if (result.ReturnCode >= 200 && result.ReturnCode <= 299)
                            {
                                if (typeof(T).IsAssignableFrom(typeof(AudioStream)))
                                {
                                    result.Asset = ((DownloadHandlerAudioStream)handler).AudioStream as T;
                                }
                                else if (typeof(T).IsAssignableFrom(typeof(Godot.Texture)))
                                {
                                    result.Asset = ((DownloadHandlerTexture)handler).Texture as T;
                                }
                            }
                            else
                            {
                                result.FailureMessage = $"[{result.ReturnCode}] {uri}";
                            }
                        }
                    }
            }
        }