Esempio n. 1
0
    IEnumerator getlevels(WWW w)
    {
        yield return(w);

        if (w.progress >= 1 && !stringsplit)
        {
            templist.AddRange(Regex.Split(w.text, "==>"));
            foreach (string temp in templist)
            {
                if (temp != "")
                {
                    tempstrings.Clear();
                    tempstrings.AddRange(Regex.Split(temp, "->"));
                    CustomLevel templevel = new CustomLevel();
                    //Debug.Log(tempstrings[0].ToString());
                    //Debug.Log(tempstrings[1].ToString());
                    templevel.Name            = tempstrings[0].ToString();
                    templevel.location        = tempstrings[1].ToString();
                    templevel.totalvotes      = Convert.ToInt32(tempstrings[2]);
                    templevel.totalvoters     = Convert.ToInt32(tempstrings[3]);
                    templevel.creator         = tempstrings[4].ToString();
                    templevel.uncompletevotes = Convert.ToInt32(tempstrings[5]);
                    CustomLevels.Add(templevel);
                }
            }
            templist.Clear();
            listdownloaded = true;
            loadCustom     = false;
            stringsplit    = true;
        }
        //Debug.Log (w.text.ToString());
        //Debug.Log (w.progress.ToString());
    }
Esempio n. 2
0
        public void GetCustomLevel_Successful() // this test is meant to succeed
        {
            CustomLevel result = new CustomLevel();

            result = testerObj.GetCustomLevel(valid_customLevelId);
            Assert.That(result, Is.TypeOf(typeof(CustomLevel)));
        }
Esempio n. 3
0
            internal static bool Prefix(string levelPath, CustomLevel __instance)
            {
                void Invoke(MethodBase methodBase, params object[] parameters)
                {
                    methodBase.Invoke(__instance, parameters);
                }

                Invoke(_printesp, (object)"");
                int num = __instance.LoadLevel(levelPath) ? 1 : 0;

                if (num == 0)
                {
                    return(num != 0);
                }
                __instance.editor.filenameText.text      = Path.GetFileName(levelPath);
                __instance.editor.filenameText.fontStyle = FontStyle.Bold;
                Invoke(_setupConductorWithLevelData);
                __instance.RemakePath();
                __instance.ReloadAssets();
                DiscordController.instance?.UpdatePresence();
                scnEditor.instance.settingsPanel.ShowPanel(LevelEventType.SongSettings);

                if (shouldSkipPlay)
                {
                    shouldSkipPlay = false;
                    return(false);
                }

                return(true);
            }
Esempio n. 4
0
 public Song(CustomLevel _data)
 {
     songName         = _data.songName;
     songSubName      = _data.songSubName;
     authorName       = _data.songAuthorName;
     difficultyLevels = ConvertDifficultyLevels(_data.difficultyBeatmaps);
 }
    /// <summary>
    /// Load all information on the CustomLevel from database
    /// </summary>
    /// <returns>Return the acquired information in a CustomLevel object</returns>
    public CustomLevel GetLevelInfo()
    {
        string query = String.Format("SELECT CustomLevelId, CustomLevelName, TimeLimit, StudentId, MonsterId, QuestionId, Option1, Option2, Option3, " +
                                     "CorrectOption, QuestionTitle FROM CustomLevel NATURAL JOIN StudentCustomQuestion " +
                                     "NATURAL JOIN Question WHERE CustomLevelId = {0};", Global.CustomLevelId);

        Dictionary <int, CustomLevel> clDict;

        using (MySqlConnection conn = new MySqlConnection(Global.csb.ConnectionString))
        {
            clDict = new Dictionary <int, CustomLevel>();
            var list = conn.Query <CustomLevel, Student, Monster, Question, CustomLevel>(
                query,
                (cl, s, m, q) =>
            {
                CustomLevel customLevel;
                if (!clDict.TryGetValue(cl.CustomLevelId, out customLevel))
                {
                    customLevel          = cl;
                    customLevel.Question = new List <Question>();
                    clDict.Add(customLevel.CustomLevelId, customLevel);
                }
                customLevel.Question.Add(q);
                customLevel.Monster = m;
                customLevel.Student = s;
                return(customLevel);
            }, splitOn: "CustomLevelId, StudentId, MonsterId, QuestionId").Distinct().ToList();
        }

        levelInfo = clDict[Global.CustomLevelId];
        return(levelInfo);
    }
Esempio n. 6
0
 public string GetSongKey()
 {
     if (levelId.Length >= 32)
     {
         CustomLevel level = SongLoader.CustomLevels.FirstOrDefault(x => x.levelID.Contains(levelId));
         if (level != null)
         {
             Regex  expression = new Regex(@"\d{1,}-\d{1,}");
             string match      = expression.Match(level.customSongInfo.path).Value;
             if (string.IsNullOrEmpty(match))
             {
                 Plugin.log.Warn("Unable to retrieve BeatSaver ID of the song from the path! Are you sure you are using the correct folder structure?");
                 return("0-0");
             }
             else
             {
                 return(match);
             }
         }
         else
         {
             Plugin.log.Warn("Song with ID " + levelId + " not found!");
             return("0-0");
         }
     }
     else
     {
         return("0-0");
     }
 }
Esempio n. 7
0
    IEnumerator LoadGameLevel(CustomLevel level)
    {
        yield return(StartCoroutine(LoadLoadingScreen()));

        LoadingScreenController lsc = LoadingScreenController.GetInstance();

        lsc?.SetLevelName(level.name);

        AsyncOperation targetLevel = SceneManager.LoadSceneAsync(level.sceneBuiltInId, LoadSceneMode.Additive);

        while (!targetLevel.isDone)
        {
            targetLevel.allowSceneActivation = false;
            int percentage = Convert.ToInt32(targetLevel.progress * 100);
            lsc?.SetLoadingProgress(percentage);

            if (targetLevel.progress >= 0.9f)
            {
                break;
            }

            yield return(null);
        }

        lsc?.SetLoaded(true);
        yield return(new WaitUntil(() => Input.GetKeyDown(KeyCode.Space)));

        targetLevel.allowSceneActivation = true;
    }
Esempio n. 8
0
    /// <summary>
    /// Change scene to EditLevelInit when Edit button is pressed
    /// </summary>
    /// <param name="btn"></param>
    private void EditLevel(Button btn)
    {
        CustomLevel cl = customLevelList.Find(item => item.CustomLevelName == btn.Name.Trim());

        Global.CustomLevelId = cl.CustomLevelId;
        GetTree().ChangeScene("res://Presentation/EditLevel/EditLevelInit.tscn");
    }
        public List <BeatmapLevelSO> SortLevelsByCreationTime(List <BeatmapLevelSO> levels)
        {
            DirectoryInfo customSongsFolder = new DirectoryInfo(Environment.CurrentDirectory.Replace('\\', '/') + "/CustomSongs/");

            List <string> sortedFolders = customSongsFolder.GetDirectories().OrderByDescending(x => x.CreationTime.Ticks).Select(x => x.FullName.Replace('\\', '/')).ToList();

            List <string> sortedLevelIDs = new List <string>();

            foreach (string path in sortedFolders)
            {
                CustomLevel song = SongLoader.CustomLevels.FirstOrDefault(x => x.customSongInfo.path.StartsWith(path));
                if (song != null)
                {
                    sortedLevelIDs.Add(song.levelID);
                }
            }

            List <BeatmapLevelSO> notSorted = new List <BeatmapLevelSO>(levels);

            List <BeatmapLevelSO> sortedLevels = new List <BeatmapLevelSO>();

            foreach (string levelId in sortedLevelIDs)
            {
                BeatmapLevelSO data = notSorted.FirstOrDefault(x => x.levelID == levelId);
                if (data != null)
                {
                    sortedLevels.Add(data);
                }
            }

            sortedLevels.AddRange(notSorted.Except(sortedLevels));

            return(sortedLevels);
        }
        void UpdateSelectedSong(ServerCommand command)
        {
            if (string.IsNullOrEmpty(command.selectedLevelID))
            {
                return;
            }
            if (_selectedSong != null && _selectedSong.levelID.Substring(0, 32) == command.selectedLevelID.Substring(0, 32))
            {
                return;
            }
            Console.WriteLine("Set selected song " + command.selectedLevelID);

            _loading = false;

            try
            {
                _selectedSong = SongLoader.CustomLevels.First(x => x.levelID.Substring(0, 32) == command.selectedLevelID.Substring(0, 32));

                SongLoader.Instance.LoadAudioClipForLevel(_selectedSong, PlayPreview);

                _selectText.gameObject.SetActive(true);
                _selectText.text = "Next song:";

                _selectedSongCell.gameObject.SetActive(true);
                (_selectedSongCell.transform as RectTransform).anchoredPosition = new Vector2(-25f, 0);
                _selectedSongCell.songName = _selectedSong.songName + "\n<size=80%>" + _selectedSong.songSubName + "</size>";
                _selectedSongCell.author   = _selectedSong.songAuthorName;

                _selectedSongCell.coverImage = _selectedSong.coverImage;
            }
            catch (Exception e)
            {
                Console.WriteLine("EXCEPTION: " + e);
            }
        }
 private void _votingSongList_selectedSong(CustomLevel selectedSong)
 {
     BSMultiplayerClient._instance.SendString(JsonUtility.ToJson(
                                                  new ClientCommand(ClientCommandType.VoteForSong,
                                                                    _voteForLevelId: selectedSong.levelID.Substring(0, 32))));
     PlayPreview(selectedSong);
 }
Esempio n. 12
0
            internal static bool Prefix(string levelPath, CustomLevel __instance)
            {
                void Invoke(MethodBase methodBase, params object[] parameters)
                {
                    methodBase.Invoke(__instance, parameters);
                }

                Invoke(_printesp, (object)"");
                int num = __instance.LoadLevel(levelPath) ? 1 : 0;

                if (num == 0)
                {
                    return(false);
                }
                __instance.editor.filenameText.text      = Path.GetFileName(levelPath);
                __instance.editor.filenameText.fontStyle = FontStyle.Bold;
                __instance.conductor.SetupConductorWithLevelData(__instance.levelData);
                __instance.RemakePath();
                __instance.ReloadAssets();
                DiscordController.instance.UpdatePresence();
                if (editor)
                {
                    editor = false;
                    __instance.editor.Run(SelectFirstFloor);
                    return(false);
                }
                else
                {
                    __instance.Play();
                }

                return(false);
            }
Esempio n. 13
0
    public void SelectLevel()
    {
        int selection = levelDropdown.value;

        AllLevels.currentLevel = selection;

        if (selection < AllLevels.BuiltInLevels.Count)
        {
            BuiltInLevel selectedLevel = AllLevels.BuiltInLevels[selection];

            preview.preserveAspect = true;

            name.text        = selectedLevel.Name;
            description.text = selectedLevel.Description;
            AllLevels.currentLevelPositions = selectedLevel.PiecePositions;
            AllLevels.currentLevelPrefabs   = selectedLevel.Prefabs;
        }
        else
        {
            CustomLevel selectedLevel = AllLevels.CustomLevels[selection - AllLevels.BuiltInLevels.Count];

            preview.preserveAspect = true;

            name.text        = selectedLevel.Name;
            description.text = selectedLevel.Description;
            AllLevels.currentLevelPositions = selectedLevel.PiecePositions;
            AllLevels.currentLevelPrefabs   = selectedLevel.Prefabs;
        }

        ChangeLevel();
    }
    void InitCards()
    {
        LevelsController levels = LevelsController.GetInstance();

        if (levels == null)
        {
            return;
        }

        for (int i = 0; i < levels.levels.Count; i++)
        {
            int         id    = i;
            CustomLevel level = levels.levels[id];

            GameObject instance = Instantiate(selectorCardTemplate, parent);
            LevelCard  card     = instance.GetComponent <LevelCard>();
            card.SetCardData(level);

            CustomButton cb = instance.GetComponent <CustomButton>();

            cb.onPointerEnter.AddListener(() =>
            {
                levelCardHovered?.Invoke(level);
            });

            cb.onClick.AddListener(() =>
            {
                levels.SelectLevelById(id);
                pages.OpenPage(1);
            });

            selectorCards.Add(instance);
        }
    }
Esempio n. 15
0
        private void LoadSprite(string spritePath, CustomLevel customLevel)
        {
            Sprite sprite;

            if (!LoadedSprites.ContainsKey(spritePath))
            {
                if (!File.Exists(spritePath))
                {
                    //Cover image doesn't exist, ignore it.
                    return;
                }

                var bytes = File.ReadAllBytes(spritePath);
                var tex   = new Texture2D(256, 256);
                if (!tex.LoadImage(bytes, true))
                {
                    Log("Failed to load cover image: " + spritePath);
                    return;
                }

                sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), Vector2.one * 0.5f, 100, 1);
                LoadedSprites.Add(spritePath, sprite);
            }
            else
            {
                sprite = LoadedSprites[spritePath];
            }

            customLevel.SetCoverImage(sprite);
        }
Esempio n. 16
0
        private IEnumerator LoadSprite(string spritePath, CustomLevel customLevel)
        {
            Sprite sprite;

            if (!LoadedSprites.ContainsKey(spritePath))
            {
                using (var web = UnityWebRequestTexture.GetTexture(EncodePath(spritePath), true))
                {
                    yield return(web.SendWebRequest());

                    if (web.isNetworkError || web.isHttpError)
                    {
                        Log("Error loading: " + spritePath + ": " + web.error, LogSeverity.Warn);
                        sprite = null;
                    }
                    else
                    {
                        var tex = DownloadHandlerTexture.GetContent(web);
                        sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), Vector2.one * 0.5f, 100, 1);
                        LoadedSprites.Add(spritePath, sprite);
                    }
                }
            }
            else
            {
                sprite = LoadedSprites[spritePath];
            }

            customLevel.SetCoverImage(sprite);
        }
        public override TableCell CellForRow(int row)
        {
            LevelListTableCell _tableCell = Instantiate(_songListTableCellInstance);

            RequestBot.SongRequest request = SongInfoForRow(row);
            JSONObject             song    = request.song;

            BeatSaberUI.AddHintText(_tableCell.transform as RectTransform, $"Requested by {request.requestor.displayName}");
            _tableCell.songName = song["songName"];
            _tableCell.author   = song["authorName"];
            if (SongLoader.AreSongsLoaded)
            {
                CustomLevel level = CustomLevelForRow(row);
                if (level)
                {
                    _tableCell.coverImage = level.coverImage;
                }
            }
            if (_tableCell.coverImage == null)
            {
                string url = song["coverUrl"];
                _tableCell.coverImage = GetSongCoverArt(url, (sprite) => { _cachedSprites[url] = sprite; _customListTableView.ReloadData(); });
            }

            _tableCell.reuseIdentifier = "CustomListCell";
            return(_tableCell);
        }
Esempio n. 18
0
 private int customEnvironment(CustomLevel song)
 {
     if (!CustomPlatformsPresent)
     {
         return(-1);
     }
     return(findCustomEnvironment(song.customSongInfo.customEnvironment));
 }
Esempio n. 19
0
        public void LoadAudioClipForLevel(CustomLevel customLevel, Action <CustomLevel> clipReadyCallback)
        {
            Action callback = delegate { clipReadyCallback(customLevel); };

            customLevel.FixBPMAndGetNoteJumpMovementSpeed();
            StartCoroutine(LoadAudio(
                               "file:///" + customLevel.customSongInfo.path + "/" + customLevel.customSongInfo.GetAudioPath(), customLevel,
                               callback));
        }
Esempio n. 20
0
 public static bool Prefix(CustomLevel __instance, int seqID)
 {
     if (seqID == 0 || !RandomTweaks.settings.DisableRestartAtCheckpoint)
     {
         return(true);
     }
     __instance.Play(0);
     return(false);
 }
 public Song(CustomLevel _data)
 {
     songName         = _data.songName;
     songSubName      = _data.songSubName;
     authorName       = _data.songAuthorName;
     difficultyLevels = ConvertDifficultyLevels(_data.difficultyBeatmapSets.SelectMany(x => x.difficultyBeatmaps).ToArray());
     path             = _data.customSongInfo.path;
     hash             = _data.levelID.Substring(0, 32);
 }
Esempio n. 22
0
    // Use this for initialization
    void Start()
    {
        AllLevels allLevels =
            GameObject.Find("Persistent Data").GetComponent <AllLevels>();

        BuildingBlockManager buildingBlockManager =
            GameObject.Find("Persistent Data").GetComponent <BuildingBlockManager>();

        int currentLevelIndex = allLevels.currentLevel;


        if (currentLevelIndex < allLevels.BuiltInLevels.Count)
        {
            BuiltInLevel currentLevel = allLevels.BuiltInLevels[currentLevelIndex];

            for (int i = 0; i < currentLevel.Prefabs.Count; i++)
            {
                Vector3 piecePosition = currentLevel.PiecePositions[i];

                Quaternion pieceRotation =
                    Quaternion.Euler(
                        0f,
                        0f,
                        currentLevel.PieceRotations[i]);

                string tag = currentLevel.Prefabs[i];

                Instantiate(
                    buildingBlockManager.searchBuiltInPrefabs(tag),
                    piecePosition,
                    pieceRotation);
            }
        }
        else if (currentLevelIndex >= allLevels.BuiltInLevels.Count)
        {
            CustomLevel currentLevel = allLevels.CustomLevels[currentLevelIndex];

            for (int i = 0; i < currentLevel.Prefabs.Count; i++)
            {
                Vector3 piecePosition = currentLevel.PiecePositions[i];

                Quaternion pieceRotation =
                    Quaternion.Euler(
                        0f,
                        0f,
                        currentLevel.PieceRotations[i]);

                string tag = currentLevel.Prefabs[i];

                Instantiate(
                    buildingBlockManager.searchBuiltInPrefabs(tag),
                    piecePosition,
                    pieceRotation);
            }
        }
    }
Esempio n. 23
0
        static void reserializer(string input, string output) //Should be: reserializer(path to .json, path to .bin)
        {
            IFormatter  formatter = new BinaryFormatter();
            string      text      = System.IO.File.ReadAllText(input);
            Stream      stream    = new FileStream(output, FileMode.Create, FileAccess.Write, FileShare.None);
            CustomLevel binOutput = JsonConvert.DeserializeObject <CustomLevel>(text);

            formatter.Serialize(stream, binOutput);
            stream.Close();
        }
Esempio n. 24
0
    private void customlevelRPC(string[] content, PhotonMessageInfo info = null)
    {
        if (info != null && !info.Sender.IsMasterClient)
        {
            Log.AddLine("RPCerror", MsgType.Error, info.Sender.ID.ToString(), nameof(customlevelRPC));
            AntisManager.Response(info.Sender.ID, true, string.Empty);
            return;
        }

        CustomLevel.RPC(content);
    }
Esempio n. 25
0
    /// <summary>
    /// Remove the popup prompt for deletion and handle the deletion through businesss logic when the No button is pressed
    /// </summary>
    private void _on_Yes_pressed()
    {
        CustomLevel cl = customLevelList.Find(item => item.CustomLevelName == levelName);

        customLevelBL.DeleteCustomLevel(cl.CustomLevelId);
        ClearGrid();
        DisplayHeader();
        DisplayLevels();
        popupMenu.Visible = false;
        NotificationPopup.DisplayPopup("Deleted Successfully!");
    }
Esempio n. 26
0
    /// <summary>
    /// Display original or updated level name, selected monster, selected time limit
    /// </summary>
    private void DisplayLevelInit()
    {
        if (updated == 0)
        {
            CustomLevel levelInfo = editLevelBL.LoadCustomLevelInfo();
            levelNameLine.Text = levelInfo.CustomLevelName;

            int i = 0;
            foreach (int a in timeLimitOptions)
            {
                if (a == levelInfo.TimeLimit)
                {
                    GD.Print("Found time: " + a);
                    break;
                }
                i++;
            }
            timeLimitBtn.Select(i);

            GD.Print("\nCustom Level Id: " + levelInfo.CustomLevelId + "\nCustom Level Name: " + levelInfo.CustomLevelName + "\nMonster Id: " + levelInfo.Monster.MonsterId +
                     "\nTimeLimit: " + levelInfo.TimeLimit);

            count = levelInfo.Monster.MonsterId - 1;
            UpdateArrowButtonStatuses();
            DisplayCharacter();

            oldName      = levelInfo.CustomLevelName;
            oldMonsterId = levelInfo.Monster.MonsterId;
            oldTimeLimit = levelInfo.TimeLimit;
        }
        else
        {
            levelNameLine.Text = Global.CustomLevelName;

            int i = 0;
            foreach (int a in timeLimitOptions)
            {
                if (a == Global.TimeLimit)
                {
                    GD.Print("Found time: " + a);
                    break;
                }
                i++;
            }
            timeLimitBtn.Select(i);

            GD.Print("\nCustom Level Id: " + Global.CustomLevelId + "\nCustom Level Name: " + Global.CustomLevelName + "\nMonster Id: " + Global.MonsterId +
                     "\nTimeLimit: " + Global.TimeLimit);

            count = Global.MonsterId - 1;
            UpdateArrowButtonStatuses();
            DisplayCharacter();
        }
    }
Esempio n. 27
0
    void LoadNextLevel()
    {
        CustomLevel nextLevel = levelsController.SelectNext();
        CarData     car       = CarsController.GetInstance()?.CurrentCar;

        if (nextLevel == null || car == null)
        {
            return;
        }

        LevelManager.GetInstance()?.Load(nextLevel, car);
    }
Esempio n. 28
0
    void Replay()
    {
        CustomLevel currentLevel = levelsController.CurrentLevel;
        CarData     car          = CarsController.GetInstance()?.CurrentCar;

        if (currentLevel == null || car == null)
        {
            return;
        }

        LevelManager.GetInstance()?.Load(currentLevel, car);
    }
        private void _characteristicControl_didSelectCellEvent(int arg2)
        {
            try
            {
                selectedCharacteristic = _selectedSong.beatmapCharacteristics[arg2];

                Dictionary <IDifficultyBeatmap, string> difficulties = _selectedSong.difficultyBeatmapSets.First(x => x.beatmapCharacteristic == selectedCharacteristic).difficultyBeatmaps.ToDictionary(x => x, x => x.difficulty.ToString().Replace("Plus", "+"));

                if (_selectedSong is CustomLevel)
                {
                    CustomLevel customSelectedSong = _selectedSong as CustomLevel;
                    var         songData           = SongCore.Collections.RetrieveExtraSongData(customSelectedSong.levelID);
                    if (songData != null && songData.difficulties != null)
                    {
                        for (int i = 0; i < difficulties.Keys.Count; i++)
                        {
                            var diffKey = difficulties.Keys.ElementAt(i);

                            var difficultyLevel = songData.difficulties.FirstOrDefault(x => x.difficulty == diffKey.difficulty);
                            if (difficultyLevel != null && !string.IsNullOrEmpty(difficultyLevel.difficultyLabel))
                            {
                                difficulties[diffKey] = difficultyLevel.difficultyLabel;
                                Plugin.log.Info($"Found difficulty label \"{difficulties[diffKey]}\" for difficulty {diffKey.difficulty.ToString()}");
                            }
                        }
                    }
                    else
                    {
                        Plugin.log.Warn($"Unable to retrieve extra song data for song with LevelID \"{customSelectedSong.levelID}\"!");
                    }
                }

                _difficultyControl.SetTexts(difficulties.Values.ToArray());

                int closestDifficultyIndex = CustomExtensions.GetClosestDifficultyIndex(difficulties.Keys.ToArray(), selectedDifficulty);

                _difficultyControl.SelectCellWithNumber(closestDifficultyIndex);

                if (!difficulties.Any(x => x.Key.difficulty == selectedDifficulty))
                {
                    _difficultyControl_didSelectCellEvent(closestDifficultyIndex);
                }
                else
                {
                    levelOptionsChanged?.Invoke();
                }
            }catch (Exception e)
            {
                Plugin.log.Critical($"Exception in char control did select event: {e}");
            }
        }
Esempio n. 30
0
    public void LoadLevel()
    {
        if (ready)
        {
            CustomLevel level = LevelsController.GetInstance()?.CurrentLevel;
            CarData     car   = CarsController.GetInstance()?.CurrentCar;

            LevelManager.GetInstance()?.Load(level, car);
        }
        else
        {
            throw new NullReferenceException("Level or Car data is not set!");
        }
    }
    public void Save()
    {
        #if UNITY_WEBPLAYER
        Debug.Log(
            "Loading or saving levels is not supported on the web player.");
        #else
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Create(FullFileName());

        CustomLevel clone = new CustomLevel(Name,
            BrickRows, FileName, BackgroundIndex);

        bf.Serialize(file, clone);
        file.Close();
        #endif
    }
    public static CustomLevel[] AllCustomLevels()
    {
        CustomLevel[] result = null;
        #if UNITY_WEBPLAYER
        Debug.Log(
            "Loading or saving levels is not supported on the web player.");
        #else
        DirectoryInfo dir = new DirectoryInfo(Application.persistentDataPath);
        FileInfo[] info = dir.GetFiles("*.bbpp-level");

        result = new CustomLevel[info.Length];
        for(int i=0; i<info.Length; i++){
            CustomLevel cl = new CustomLevel();
            cl.LoadFromFile(info[i].Name);
            result[i] = cl;
        }
        #endif
        return result;
    }