示例#1
0
        /// <summary>
        /// Replace any keys within a file from a dictionary
        /// </summary>
        /// <param name="filePath">path of file to replace keys in</param>
        /// <param name="keyVars">dictionary of words to replace within files</param>
        public static bool UpdateFileWithKeys(string filePath, Dictionary <string, string> keyVars)
        {
            string textInfo = SafeFileManagement.GetFileContents(filePath);

            if (textInfo == null)
            {
                return(false);
            }
            foreach (string key in keyVars.Keys)
            {
                textInfo = textInfo.Replace(key, keyVars[key]);
            }
            return(SafeFileManagement.SetFileContents(filePath, textInfo));
        }
        /// <summary>
        /// Generate obstacles commands given a song and difficulty
        /// </summary>
        /// <param name="song">Beatmap data for a song and difficulty</param>
        /// <param name="difficultyName">Minecraft safe difficulty name</param>
        /// <param name="commandBasePath">Base folder path to generate new mcfunctions</param>
        /// <param name="packInfo">Beat Saber Parsed info</param>
        /// <param name="dpd">Data used for datapack generation</param>
        public static void GenerateObstacles(MapData song, string difficultyName, string commandBasePath, Info packInfo, DataPackData dpd)
        {
            Obstacle[] obstacles               = song.Obstacles;
            int        obstacleIndex           = 0;
            int        currentLevel            = 1;
            int        currentTick             = 0;
            int        maxTick                 = 0;
            int        minTick                 = -1;
            int        currentNumberOfCommands = 0;
            int        currentCommandLimit     = Globals.COMMAND_LIMIT;

            // Main note generation
            while (obstacleIndex < obstacles.Length)
            {
                string        commandLevelName     = difficultyName + Globals.LEVEL_OBSTACLE_NAME + currentLevel;
                string        commandLevelFileName = commandLevelName + Globals.MCFUNCTION;
                string        commandLevelFilePath = Path.Combine(dpd.folder_uuidFunctionsPath, commandLevelFileName);
                StringBuilder currentCommands      = new StringBuilder();
                int           maxNewTick           = 0;
                int           minNewTick           = 0;
                minTick = -1;

                // Continue to generate commands until all nodes and obstacles have been iterated though
                while (obstacleIndex < obstacles.Length && currentNumberOfCommands < currentCommandLimit)
                {
                    ObstacleDataToCommands(obstacles[obstacleIndex], packInfo.BeatsPerMinute, dpd.metersPerTick, ref currentCommands, ref currentNumberOfCommands, ref minNewTick, ref maxNewTick);
                    if (minTick == -1)
                    {
                        minTick = minNewTick;
                    }
                    maxTick = Mathf.Max(maxTick, maxNewTick);
                    obstacleIndex++;
                }

                if (obstacleIndex >= obstacles.Length)
                {
                    maxTick += (int)(dpd.ticksStartOffset + 1);
                    currentCommands.AppendFormat(Globals.templateStrings._finishedObstacles, maxTick);
                    if (minTick == -1)
                    {
                        minTick = maxTick - 1;
                    }
                }

                SafeFileManagement.SetFileContents(commandLevelFilePath, currentCommands.ToString());
                string baseCommand = string.Format(Globals.templateStrings._baseCommand, minTick, maxTick, dpd.folder_uuid, commandLevelName);
                SafeFileManagement.AppendFile(commandBasePath, baseCommand);
                currentCommandLimit = currentNumberOfCommands + Globals.COMMAND_LIMIT;
                minTick             = 0;
                maxTick             = 0;
                currentLevel++;
            }

            if (obstacles.Length == 0)
            {
                string        commandLevelName     = difficultyName + Globals.LEVEL_OBSTACLE_NAME + currentLevel;
                string        commandLevelFileName = commandLevelName + Globals.MCFUNCTION;
                string        commandLevelFilePath = Path.Combine(dpd.folder_uuidFunctionsPath, commandLevelFileName);
                StringBuilder currentCommands      = new StringBuilder();
                currentTick++;
                currentCommands.AppendFormat(Globals.templateStrings._finishedObstacles, currentTick);
                SafeFileManagement.SetFileContents(commandLevelFilePath, currentCommands.ToString());
                string baseCommand = string.Format(Globals.templateStrings._baseCommand,
                                                   minTick,
                                                   maxTick + (int)(dpd.ticksStartOffset + 1),
                                                   dpd.folder_uuid,
                                                   commandLevelName);
                SafeFileManagement.AppendFile(commandBasePath, baseCommand);
            }
        }
        public static void GenerateEvents(MapData song, string difficultyName, string commandBasePath, Info packInfo, DataPackData dpd)
        {
            int currentLevel            = 1;
            int currentTick             = 0;
            int prevCurrentTick         = 0;
            int currentNumberOfCommands = 0;
            int noteIndex           = 0;
            int currentCommandLimit = Globals.COMMAND_LIMIT;

            var bEvents = song.Events.Where(x => x.Value >= 0 && x.Value <= 11).ToArray();

            List <EventFadeSave> autoOffTick = new List <EventFadeSave>();

            for (int i = 0; i < 10; i++)
            {
                autoOffTick.Add(new EventFadeSave());
            }
            // Main note generation
            while (noteIndex < bEvents.Length)
            {
                string        commandLevelName     = difficultyName + Globals.LEVEL_EVENT_NAME + currentLevel;
                string        commandLevelFileName = commandLevelName + Globals.MCFUNCTION;
                string        commandLevelFilePath = Path.Combine(dpd.folder_uuidFunctionsPath, commandLevelFileName);
                StringBuilder currentCommands      = new StringBuilder();

                // Continue to generate commands until all events
                while (noteIndex < bEvents.Length && currentNumberOfCommands < currentCommandLimit)
                {
                    currentNumberOfCommands += EventDataToCommands(bEvents[noteIndex], packInfo.BeatsPerMinute, dpd, ref currentCommands, ref currentTick, ref autoOffTick);
                    noteIndex++;
                }

                if (noteIndex >= bEvents.Length)
                {
                    currentTick += (int)(dpd.ticksStartOffset + 1);;
                    currentCommands.AppendFormat(Globals.templateStrings._finishedEvents, currentTick);
                }

                SafeFileManagement.SetFileContents(commandLevelFilePath, currentCommands.ToString());
                string baseCommand = string.Format(Globals.templateStrings._baseCommand,
                                                   prevCurrentTick,
                                                   currentTick,
                                                   dpd.folder_uuid,
                                                   commandLevelName);
                SafeFileManagement.AppendFile(commandBasePath, baseCommand);
                prevCurrentTick     = currentTick + 1;
                currentCommandLimit = currentNumberOfCommands + Globals.COMMAND_LIMIT;
                currentLevel++;
            }


            // Note pretty buy create a command if no obstacles are present in a map
            if (bEvents.Length == 0)
            {
                currentTick += (int)(dpd.ticksStartOffset + 1);;
                string        commandLevelName     = difficultyName + Globals.LEVEL_EVENT_NAME + currentLevel;
                string        commandLevelFileName = commandLevelName + Globals.MCFUNCTION;
                string        commandLevelFilePath = Path.Combine(dpd.folder_uuidFunctionsPath, commandLevelFileName);
                StringBuilder currentCommands      = new StringBuilder();
                SafeFileManagement.SetFileContents(commandLevelFilePath, currentCommands.ToString());
                string baseCommand = string.Format(Globals.templateStrings._baseCommand,
                                                   prevCurrentTick,
                                                   currentTick,
                                                   dpd.folder_uuid,
                                                   commandLevelName);
                SafeFileManagement.AppendFile(commandBasePath, baseCommand);
                currentCommands.AppendFormat(Globals.templateStrings._finishedNotes, currentTick);
            }
        }
        /// <summary>
        /// Generate note commands given a song and difficulty
        /// </summary>
        /// <param name="song">Beatmap data for a song and difficulty</param>
        /// <param name="difficultyName">Minecraft safe difficulty name</param>
        /// <param name="commandBasePath">Base folder path to generate new mcfunctions</param>
        /// <param name="packInfo">Beat Saber Parsed info</param>
        /// <param name="dpd">Data used for datapack generation</param>
        public static void GenerateNotes(MapData song, string difficultyName, string commandBasePath, Info packInfo, DataPackData dpd)
        {
            double prevNodeTime            = 0;
            int    nodeRowID               = 1;
            int    currentLevel            = 1;
            int    currentTick             = 0;
            int    prevCurrentTick         = 0;
            int    currentNumberOfCommands = 0;
            int    noteIndex               = 0;
            int    currentCommandLimit     = Globals.COMMAND_LIMIT;

            var notes = song.Notes;

            // Main note generation
            while (noteIndex < notes.Length)
            {
                string        commandLevelName     = difficultyName + Globals.LEVEL_NOTE_NAME + currentLevel;
                string        commandLevelFileName = commandLevelName + Globals.MCFUNCTION;
                string        commandLevelFilePath = Path.Combine(dpd.folder_uuidFunctionsPath, commandLevelFileName);
                StringBuilder currentCommands      = new StringBuilder();

                // Continue to generate commands until all nodes and obstacles have been iterated though
                while (noteIndex < notes.Length && currentNumberOfCommands < currentCommandLimit)
                {
                    if (prevNodeTime != notes[noteIndex].Time)
                    {
                        nodeRowID++;
                    }

                    NodeDataToCommands(notes[noteIndex], packInfo.BeatsPerMinute, dpd.metersPerTick, nodeRowID, ref currentCommands, ref currentTick);

                    prevNodeTime             = notes[noteIndex].Time;
                    currentNumberOfCommands += 3;
                    noteIndex++;
                }

                if (noteIndex >= notes.Length)
                {
                    currentTick += (int)(dpd.ticksStartOffset + 1);;
                    currentCommands.AppendFormat(Globals.templateStrings._finishedNotes, currentTick);
                }

                SafeFileManagement.SetFileContents(commandLevelFilePath, currentCommands.ToString());
                string baseCommand = string.Format(Globals.templateStrings._baseCommand,
                                                   prevCurrentTick,
                                                   currentTick,
                                                   dpd.folder_uuid,
                                                   commandLevelName);
                SafeFileManagement.AppendFile(commandBasePath, baseCommand);
                prevCurrentTick     = currentTick + 1;
                currentCommandLimit = currentNumberOfCommands + Globals.COMMAND_LIMIT;
                currentLevel++;
            }

            // Note pretty buy create a command if no obstacles are present in a map
            if (notes.Length == 0)
            {
                currentTick += (int)(dpd.ticksStartOffset + 1);;
                string        commandLevelName     = difficultyName + Globals.LEVEL_NOTE_NAME + currentLevel;
                string        commandLevelFileName = commandLevelName + Globals.MCFUNCTION;
                string        commandLevelFilePath = Path.Combine(dpd.folder_uuidFunctionsPath, commandLevelFileName);
                StringBuilder currentCommands      = new StringBuilder();
                SafeFileManagement.SetFileContents(commandLevelFilePath, currentCommands.ToString());
                string baseCommand = string.Format(Globals.templateStrings._baseCommand,
                                                   prevCurrentTick,
                                                   currentTick,
                                                   dpd.folder_uuid,
                                                   commandLevelName);
                SafeFileManagement.AppendFile(commandBasePath, baseCommand);
                currentCommands.AppendFormat(Globals.templateStrings._finishedNotes, currentTick);
            }
        }
        /// <summary>
        /// Main generation of minecraft commands for beat saber data
        /// </summary>
        /// <param name="beatMapSongList">List of Beat Saber song data</param>
        /// <param name="packInfo">Beat Saber Parsed info</param>
        /// <param name="dpd">Data used for datapack generation</param>
        /// <returns></returns>
        public static ConversionError GenerateMCBeatData(BeatSaberMap beatSaberMap, DataPackData dpd, IProgress <ConversionProgress> progress, CancellationToken cancellationToken)
        {
            StringBuilder difficultyDisplayCommands = new StringBuilder();
            StringBuilder scoreboardCommands        = new StringBuilder();
            StringBuilder spawnOriginCommands       = new StringBuilder();
            StringBuilder spawnNotesBaseCommands    = new StringBuilder();
            int           difficultyNumber          = 1;

            // Iterate though each song difficulty
            var mapDataInfos      = beatSaberMap.MapDataInfos;
            var progressPercent   = 0.4f;
            var mapDataInfosKeys  = mapDataInfos.Keys.ToArray();
            var progressIncrament = mapDataInfosKeys.Length * 0.5f;

            for (int i = 0; i < mapDataInfosKeys.Length; i++)
            {
                var mapDataInfo = mapDataInfos[mapDataInfosKeys[i]];
                if (mapDataInfo.MapData == null || mapDataInfo.MapData.Notes == null || mapDataInfo.MapData.Obstacles == null)
                {
                    return(ConversionError.NoMapData);
                }
                progress.Report(new ConversionProgress(progressPercent + progressIncrament, "Generating minecraft commands"));
                if (mapDataInfo.MapData.Notes.Length > 0 || mapDataInfo.MapData.Obstacles.Length > 0)
                {
                    string difficultyName = mapDataInfo.DifficultyBeatmapInfo.Difficulty.MakeMinecraftSafe();

                    // Append running command lists
                    string songDifficultyID = dpd.songGuid + difficultyNumber.ToString();
                    scoreboardCommands.AppendFormat(Globals.templateStrings._scoreboardCommand, songDifficultyID);
                    spawnOriginCommands.AppendFormat(Globals.templateStrings._spawnOriginCommands, -dpd.metersPerTick * dpd.ticksStartOffset, difficultyNumber);
                    spawnNotesBaseCommands.AppendFormat(Globals.templateStrings._spawnNotesBaseCommand, difficultyNumber, dpd.folder_uuid, difficultyName);

                    CreateDifficultyDisplay(songDifficultyID, difficultyName, dpd.folder_uuid, ref difficultyDisplayCommands);

                    // Write difficulty-specific-file commands
                    string playCommands = string.Format(Globals.templateStrings._playCommands, difficultyNumber, dpd.folder_uuid);
                    string playPath     = Path.Combine(dpd.folder_uuidFunctionsPath, difficultyName + "_play" + Globals.MCFUNCTION);
                    SafeFileManagement.SetFileContents(playPath, playCommands);

                    string playSongCommand = string.Format(Globals.templateStrings._playSongCommand, dpd.ticksStartOffset - 1, dpd.folder_uuid);
                    string commandBasePath = Path.Combine(dpd.folder_uuidFunctionsPath, difficultyName + Globals.MCFUNCTION);
                    SafeFileManagement.AppendFile(commandBasePath, playSongCommand);

                    string completedSongCommand = string.Format(Globals.templateStrings._completedSong, difficultyNumber, songDifficultyID);
                    string completedSongPath    = Path.Combine(dpd.folder_uuidFunctionsPath, Globals.MAP_DIFFICULTY_COMPLETED);
                    SafeFileManagement.AppendFile(completedSongPath, completedSongCommand);

                    // Generate main note/obstacle data/light data
                    GenerateNotes(mapDataInfo.MapData, difficultyName, commandBasePath, beatSaberMap.InfoData, dpd);
                    GenerateObstacles(mapDataInfo.MapData, difficultyName, commandBasePath, beatSaberMap.InfoData, dpd);
                    GenerateEvents(mapDataInfo.MapData, difficultyName, commandBasePath, beatSaberMap.InfoData, dpd);

                    difficultyNumber++;
                }
            }

            // Write collected commands to files
            string difficultiesFunctionPath  = Path.Combine(dpd.folder_uuidFunctionsPath, Globals.DIFFICULTIES);
            string initFunctionPath          = Path.Combine(dpd.folder_uuidFunctionsPath, Globals.INIT_FUNCTION);
            string setSpawnOrginFunctionPath = Path.Combine(dpd.folder_uuidFunctionsPath, Globals.SET_SPAWN_ORIGIN);

            SafeFileManagement.AppendFile(dpd.spawnNotesBasePath, spawnNotesBaseCommands.ToString());
            SafeFileManagement.AppendFile(setSpawnOrginFunctionPath, spawnOriginCommands.ToString());
            SafeFileManagement.AppendFile(initFunctionPath, scoreboardCommands.ToString());

            // Add back button in tellraw
            difficultyDisplayCommands.Append(Globals.templateStrings._mainMenuBack);
            SafeFileManagement.AppendFile(difficultiesFunctionPath, difficultyDisplayCommands.ToString());
            return(ConversionError.None);
        }