コード例 #1
0
    private IEnumerator GetBeatmapFromLocation(Uri uri)
    {
        // We will extract the contents of the zip to the temp directory, so we will save the zip in memory.
        DownloadHandlerBuffer downloadHandler = new DownloadHandlerBuffer();

        // Create our web request, and set our handler.
        UnityWebRequest request = UnityWebRequest.Get(uri);

        request.downloadHandler = downloadHandler;
        // Change our User-Agent so BeatSaver can download our map
        request.SetRequestHeader("User-Agent", $"{Application.productName}/{Application.version}");

        // Set progress bar state.
        PersistentUI.Instance.LevelLoadSlider.gameObject.SetActive(true);
        PersistentUI.Instance.LevelLoadSlider.value     = 0;
        PersistentUI.Instance.LevelLoadSliderLabel.text = $"Downloading file... Starting download...";

        var operation = request.SendWebRequest();

        while (!request.isDone)
        {
            // Grab Content-Length, which is the length of the downloading file, to use for progress bar.
            if (int.TryParse(request.GetResponseHeader("Content-Length"), out int length))
            {
                float progress = downloadHandler.data.Length / (float)length;
                PersistentUI.Instance.LevelLoadSlider.value = progress;
                float percent = progress * 100;
                PersistentUI.Instance.LevelLoadSliderLabel.text = $"Downloading file... {percent:F2}% complete.";
            }
            else
            {
                // Just gives the bar something to do until we get the content length.
                PersistentUI.Instance.LevelLoadSlider.value = (Mathf.Sin(Time.time) / 2) + 0.5f;
            }

            // Cancel loading if an error has occurred.
            if (request.isHttpError || request.isNetworkError)
            {
                CancelTempLoader(request.error);
                yield break;
            }
            yield return(new WaitForEndOfFrame());
        }
        // Check one more time to be safe.
        if (request.isHttpError || request.isNetworkError)
        {
            CancelTempLoader(request.error);
            yield break;
        }

        // Wahoo! We are done. Let's grab our downloaded data.
        byte[] downloaded = downloadHandler.data;

        // If the request failed, our downloaded bytes will be null. Let's check that.
        if (downloaded != null)
        {
            PersistentUI.Instance.LevelLoadSlider.value     = 1;
            PersistentUI.Instance.LevelLoadSliderLabel.text = "Extracting contents...";

            yield return(new WaitForEndOfFrame());

            try
            {
                // Slap our downloaded bytes into a memory stream and slap that into a ZipArchive.
                MemoryStream stream  = new MemoryStream(downloaded);
                ZipArchive   archive = new ZipArchive(stream, ZipArchiveMode.Read);

                // Create the directory for our song to go to.
                // Path.GetTempPath() should be compatible with Windows and UNIX.
                // See Microsoft docs on it.
                string directory = $"{Path.GetTempPath()}ChroMapper Temp Loader\\{request.GetHashCode()}";
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                // Extract our zipped file into this directory.
                archive.ExtractToDirectory(directory);

                // Dispose our downloaded bytes, we don't need them.
                downloadHandler.Dispose();

                // Try and get a BeatSaberSong out of what we've downloaded.
                BeatSaberSong song = BeatSaberSong.GetSongFromFolder(directory);
                if (song != null)
                {
                    PersistentUI.Instance.LevelLoadSliderLabel.text = "Loading song...";
                    BeatSaberSongContainer.Instance.song            = song;
                }
                else
                {
                    CancelTempLoader("Could not obtain a valid Beatmap from the downloaded content.");
                }
            }
            catch (Exception e)
            {
                // Uh oh, an error occurred.
                // Let's see if it is due to user error, or a genuine error on ChroMapper's part.
                switch (e.GetType().Name)
                {
                // InvalidDataException means that the ZipArchive cannot be created.
                // ChroMapper tried to download something that is not a zip.
                case nameof(InvalidDataException):
                    CancelTempLoader($"Downloaded content was not a valid zip.");
                    break;

                // Default case is a genuine error, let's print what it has to say.
                default:
                    CancelTempLoader($"An unknown error ({e.GetType().Name}) has occurred:\n\n{e.Message}");
                    break;
                }
            }
        }
        else
        {
            CancelTempLoader("Downloaded bytes is somehow null, yet the request was successfully completed. WTF!?");
        }
    }