예제 #1
0
        protected override void OnThreadUnSafeEventFired(object source, CharacterSessionDataChangedEventArgs args)
        {
            if (Logger.IsInfoEnabled)
            {
                Logger.Info($"Starting process to download world.");
            }

            UnityAsyncHelper.UnityMainThreadContext.PostAsync(async() =>
            {
                long worldId = 0;
                try
                {
                    //TODO: Handle failure
                    ProjectVersionStage.AssertAlpha();

                    //TODO: Handle throwing/error
                    //We need to know the world the zone is it, so we can request a download URL for it.
                    var worldConfig = await ZoneDataService.GetZoneWorldConfigurationAsync(args.ZoneIdentifier)
                                      .ConfigureAwaitFalse();

                    if (!worldConfig.isSuccessful)
                    {
                        throw new InvalidOperationException($"Failed to query World Configuration for ZoneId: {args.ZoneIdentifier}");
                    }

                    worldId = worldConfig.Result.WorldId;

                    //With the worldid we can get the download URL.
                    ContentDownloadURLResponse urlDownloadResponse = await ContentService.RequestWorldDownloadUrl(worldId)
                                                                     .ConfigureAwaitFalse();

                    if (Logger.IsInfoEnabled)
                    {
                        Logger.Info($"World Download Url: {urlDownloadResponse.DownloadURL}");
                    }

                    //Can't do web request not on the main thread, sadly.
                    await new UnityYieldAwaitable();

                    WorldDownloader downloader = new WorldDownloader(Logger);

                    await downloader.DownloadAsync(urlDownloadResponse.DownloadURL, urlDownloadResponse.Version, o =>
                    {
                        OnWorldDownloadBegins?.Invoke(this, new WorldDownloadBeginEventArgs(o));
                    });
                }
                catch (Exception e)
                {
                    if (Logger.IsErrorEnabled)
                    {
                        Logger.Error($"Failed to query for Download URL for ZoneId: {args.ZoneIdentifier} WorldId: {worldId} (0 if never succeeded request). Error: {e.Message}");
                    }
                    throw;
                }
            });
        }
예제 #2
0
        public async Task OnGameInitialized()
        {
            //TODO: Handle throwing/error
            ContentDownloadURLResponse downloadUrlResponse = await ContentService.RequestWorldDownloadUrl(WorldConfig.WorldId)
                                                             .ConfigureAwaitFalse();

            if (Logger.IsInfoEnabled)
            {
                Logger.Info($"World Download Url: {downloadUrlResponse.DownloadURL}");
            }

            //Can't do web request not on the main thread, sadly.
            await new UnityYieldAwaitable();

            //TODO: Handle failure.
            WorldDownloader downloader = new WorldDownloader(Logger);

            //At this point after this finishes the world shoud be downloaded.
            await downloader.DownloadAsync(downloadUrlResponse.DownloadURL, downloadUrlResponse.Version, null, true);             //important that the world loads ontop of the existing scene.
        }
예제 #3
0
        /// <inheritdoc />
        public async Task <IPrefabContentResourceHandle> LoadContentPrefabAsync(long contentId)
        {
            //If it's already available, we can just return immediately
            if (IsContentResourceAvailable(contentId))
            {
                return(TryLoadContentPrefab(contentId));
            }

            ContentDownloadURLResponse downloadUrlResponse = await RequestDownloadURL(contentId);

            //TODO: Handle failure
            TaskCompletionSource <IPrefabContentResourceHandle> completionSource = new TaskCompletionSource <IPrefabContentResourceHandle>();

            //Asset bundle requests can sadly only happen on the main thread, so we must join the main thread.
            await new UnityYieldAwaitable();

            //TODO: We should handle caching, versioning and etc here.
            UnityWebRequestAsyncOperation asyncOperation = UnityWebRequestAssetBundle.GetAssetBundle(downloadUrlResponse.DownloadURL, (uint)downloadUrlResponse.Version, 0).SendWebRequest();

            //TODO: We should render these operations to the loading screen UI.
            asyncOperation.completed += operation =>
            {
                //When we first get back on the main thread, the main concern
                //is that this resource manager may be from the last scene
                //and that the client may have moved on
                //to avoid this issues we check disposal state
                //and do nothing, otherwise if we check AFTER then we just have to release the assetbundle immediately anyway.
                if (isDisposed)
                {
                    //Just tell anyone awaiting this that it is canceled. They should handle that case, not us.
                    completionSource.SetCanceled();
                    return;
                }


                //GetContent will throw if the assetbundle has already been loaded.
                //So to prevent this from occuring due to multiple requests for the
                //content async we will check, on this main thread, via a write lock.
                lock (SyncObj)
                {
                    //We're on the main thread again. So, we should check if another
                    //request already got the bundle
                    if (IsContentResourceAvailable(contentId))
                    {
                        completionSource.SetResult(TryLoadContentPrefab(contentId));
                        return;
                    }

                    try
                    {
                        //otherwise, we still don't have it so we should initialize it.
                        this.ResourceHandleCache[contentId] = new ReferenceCountedPrefabContentResourceHandle(DownloadHandlerAssetBundle.GetContent(asyncOperation.webRequest));
                        completionSource.SetResult(TryLoadContentPrefab(contentId));                         //we assume this will work now.
                    }
                    catch (Exception e)
                    {
                        if (Logger.IsErrorEnabled)
                        {
                            Logger.Error($"Failed to load AssetBundle for Content: {contentId}. Reason: {e.ToString()}");
                        }

                        //Don't rethrow, causing build breaking.
                    }
                }
            };

            return(await completionSource.Task
                   .ConfigureAwaitFalse());
        }