Example #1
0
        private void submit_Click(object sender, EventArgs e)
        {
            if (int.TryParse(textBoxOctaveAdjust.Text, out int octaveAdjust))
            {
                button1.Enabled = false;
                button2.Enabled = false;
                // iterate every file in the mordhau Save folder matching format [A-Za-z0-9]*\[[0-9]*\]
                // skip any named PartitionIndex


                // First, move them to a backup folder

                // Then parse each set...
                // Parse out each command and convert it to MidiNote
                // Create a collection of MidiNotes for each set/song
                // For all notes of type 1, increase the second number (ex 1320-14-1;) by 12*octaveAdjust
                // Run the collection back through the partition save routine

                // This is all divison is used for:
                // partition.Tempo = note.Tone / division;
                // return new Note() { Tick = note.Tick, Tone = note.Tone / division, Type = note.Type };
                // So when I read the Tempo, NoteType 2, I can pass it straight back without sending through BuildNote
                // The rest I do need to send through BuildNote
                // But also be sure to set partition.Tempo



                // The save file requires: ([a-zA-Z0-9][a-zA-Z0-9 -]*[a-zA-Z0-9])
                Regex filenameReg = new Regex(@"^([a-zA-Z0-9][a-zA-Z0-9 -]*[a-zA-Z0-9])\[([0-9]+)\].sav$");
                // The first capture group is the song name, the second is the index

                Dictionary <string, string> fileContents = new Dictionary <string, string>();
                // Dictionary of filename:contents
                // We are also using a dictionary of index to string, because we can't guarantee what order we read these in (or, we could I guess, IDK)

                string backupDir = Path.Combine(SaveManager.SaveFilePath, "PartitionBackup " + DateTime.Now.ToString("MM-dd-yyyy"));
                Directory.CreateDirectory(backupDir);

                try
                {
                    foreach (var f in Directory.GetFiles(SaveManager.SaveFilePath))
                    {
                        var filename = Path.GetFileName(f);
                        var match    = filenameReg.Match(filename);
                        if (match.Success)
                        {
                            var songName = match.Groups[1].Value;
                            int index    = int.Parse(match.Groups[2].Value);

                            if (songName != "PartitionIndex")
                            {
                                if (!fileContents.ContainsKey(songName))
                                {
                                    fileContents[songName] = "";
                                }

                                // BOF: "SavedPartition    StrProperty Ž       Š  "
                                // EOF: "    None    "

                                var contents = File.ReadAllText(f);

                                int splitLocation = contents.IndexOf("SavedPartition\0\f\0\0\0StrProperty\0�\u0013\0\0\0\0\0\0\0�\u0013\0\0", StringComparison.InvariantCulture) + "SavedPartition    StrProperty Ž       Š  ".Length;

                                string songContent = contents.Substring(splitLocation);
                                songContent = songContent.Replace("\0\u0005\0\0\0None\0\0\0\0", "");

                                fileContents[songName] += songContent;

                                // Move it to a new backup folder
                                File.Move(f, Path.Combine(backupDir, filename));
                            }
                        }
                    }
                }
                catch
                {
                    MessageBox.Show("Failed to backup files.  If a backup folder already exists in the Save Folder that should now open, rename, move, or delete it");
                    button1.Enabled = true;
                    button2.Enabled = false;
                    Process.Start(SaveManager.SaveFilePath);
                    return;
                }

                // I think old lutemod saved the track name into the file or something, it's there on a few specific ones
                // This might be why dashes were disallowed, doing [^-;] would be great, but instead I'll put the naming thing and make it optional
                Regex tempoRegex = new Regex(@"^\|[a-zA-Z0-9]?[a-zA-Z0-9 -]*[a-zA-Z0-9]?;([0-9]+)\|");
                Regex noteRegex  = new Regex(@"([0-9]+)-([0-9]+)-([0-9]+);");

                int lowNote = ConfigManager.GetIntegerProperty(PropertyItem.LowestPlayedNote);

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

                foreach (var song in fileContents.Keys)
                {
                    try
                    {
                        // Parse out each command and convert it to MidiNote
                        // Create a collection of MidiNotes for each set/song
                        // For all notes of type 1, increase the second number (ex 1320-14-1;) by 12*octaveAdjust
                        // Run the collection back through the partition save routine
                        List <LuteMod.Sequencing.Note> notes = new List <LuteMod.Sequencing.Note>();

                        string content = fileContents[song];

                        var tempoMatch = tempoRegex.Match(content);


                        var converter = new LuteMod.Converter.MordhauConverter();
                        converter.Range               = ConfigManager.GetIntegerProperty(PropertyItem.AvaliableNoteCount);
                        converter.LowNote             = lowNote;
                        converter.IsConversionEnabled = true;
                        //converter.SetDivision(player.sequence.Division);
                        converter.AddTrack();

                        converter.SetPartitionTempo(int.Parse(tempoMatch.Groups[1].Value));
                        converter.SetDivision(1);

                        var noteMatches = noteRegex.Matches(content);
                        foreach (Match noteMatch in noteMatches)
                        {
                            int tone     = int.Parse(noteMatch.Groups[2].Value);
                            int noteType = int.Parse(noteMatch.Groups[3].Value);
                            if (noteType == 1)
                            {
                                tone = tone + octaveAdjust * 12 + lowNote;
                            }
                            notes.Add(new LuteMod.Sequencing.Note()
                            {
                                Tick = int.Parse(noteMatch.Groups[1].Value), Tone = tone, Type = (LuteMod.Sequencing.NoteType)noteType
                            });
                        }

                        // result.Add(new LuteMod.Sequencing.Note() { Tick = tempTick, Tone = tempMessage.Data1 + offset, Type = LuteMod.Sequencing.NoteType.On });


                        converter.FillTrack(0, notes); // We let it re-process them to fit new ranges, which is why we re-added lowNote above - it needs it, and will remove it again
                                                       // Interestingly, this also automatically moves things for our lute update, which is great
                        SaveManager.WriteSaveFile(Path.Combine(SaveManager.SaveFilePath, song), converter.GetPartitionToString());
                    }
                    catch
                    {
                        errorSongs.Add(song);
                    }
                }

                if (errorSongs.Count > 0)
                {
                    MessageBox.Show("Some songs caused exceptions while converting: " + string.Join("\n", errorSongs) + "\n\nYou can restore these from the backup folder that was opened");
                    Process.Start(backupDir);
                }
                else
                {
                    //index.SaveIndex();
                    //PopulateIndexList();
                    Close();
                    MessageBox.Show("Successfully converted all songs");
                }
            }
            else
            {
                MessageBox.Show("Please enter a value in the Octave Adjust field");
            }
        }
Example #2
0
        private void savePartitionsButton_Click(object sender, EventArgs e)
        {
            if (tsm.MidiTracks.Values.Where(t => t.Active).Count() > 0)
            {
                var namingForm = new TrackNamingForm(Path.GetFileNameWithoutExtension(tsm.FileName));
                namingForm.ShowDialog(this);
                if (namingForm.DialogResult == DialogResult.OK)
                {
                    if (namingForm.textBoxPartName.Text == "Partition Name" || namingForm.textBoxPartName.Text.Trim() == "")
                    {
                        MessageBox.Show("Please name your partition");
                    }
                    else
                    {
                        if (index.PartitionNames.Contains(namingForm.textBoxPartName.Text))
                        {
                            MessageBox.Show("That name already exists");
                        }
                        else
                        {
                            if (!Regex.IsMatch(namingForm.textBoxPartName.Text, "^([a-zA-Z0-9][a-zA-Z0-9 -]*[a-zA-Z0-9])$"))
                            {
                                MessageBox.Show("That name contains invalid characters");
                            }
                            else
                            {
                                index.PartitionNames.Add(namingForm.textBoxPartName.Text);

                                //if (trackConverter == null)
                                //{
                                var converter       = new LuteMod.Converter.MordhauConverter();
                                int firstInstrument = ConfigManager.GetIntegerProperty(PropertyItem.Instrument);
                                // Step 1, load solo lute into track 0 - this profile should always exist
                                // Actually, all of the first 4 instruments get loaded in, under the same ID we use in lutebot.  Convenient.
                                for (int i = 0; i < 4; i++)
                                {
                                    int oldInstrument = ConfigManager.GetIntegerProperty(PropertyItem.Instrument);

                                    if (tsm.DataDictionary.ContainsKey(i))
                                    {
                                        if (oldInstrument != i)
                                        {
                                            ConfigManager.SetProperty(PropertyItem.Instrument, i.ToString());
                                            Instrument target = Instrument.Prefabs[i];

                                            bool soundEffects = !target.Name.StartsWith("Mordhau", true, System.Globalization.CultureInfo.InvariantCulture);
                                            ConfigManager.SetProperty(PropertyItem.SoundEffects, soundEffects.ToString());
                                            ConfigManager.SetProperty(PropertyItem.LowestNoteId, target.LowestSentNote.ToString());
                                            ConfigManager.SetProperty(PropertyItem.AvaliableNoteCount, target.NoteCount.ToString());
                                            ConfigManager.SetProperty(PropertyItem.NoteCooldown, target.NoteCooldown.ToString());
                                            ConfigManager.SetProperty(PropertyItem.LowestPlayedNote, target.LowestPlayedNote.ToString());
                                            ConfigManager.SetProperty(PropertyItem.ForbidsChords, target.ForbidsChords.ToString());
                                            tsm.UpdateTrackSelectionForInstrument(oldInstrument);
                                            player.mordhauOutDevice.UpdateNoteIdBounds();
                                        }

                                        converter.Range               = ConfigManager.GetIntegerProperty(PropertyItem.AvaliableNoteCount);
                                        converter.LowNote             = ConfigManager.GetIntegerProperty(PropertyItem.LowestPlayedNote);
                                        converter.IsConversionEnabled = true;
                                        converter.SetDivision(player.sequence.Division);
                                        converter.SetPartitionTempo(player.sequence.FirstTempo);
                                        converter.AddTrack();
                                        converter.SetEnabledTracksInTrack(i, tsm.MidiTracks.Values.ToList());
                                        converter.SetEnabledMidiChannelsInTrack(i, tsm.MidiChannels.Values.ToList());

                                        converter.FillTrack(i, player.ExtractMidiContent());
                                    }
                                }

                                SaveManager.WriteSaveFile(Path.Combine(SaveManager.SaveFilePath, namingForm.textBoxPartName.Text), converter.GetPartitionToString());
                                index.SaveIndex();
                                PopulateIndexList();
                                // And put the instrument back
                                if (ConfigManager.GetIntegerProperty(PropertyItem.Instrument) != firstInstrument)
                                {
                                    int oldInstrument = ConfigManager.GetIntegerProperty(PropertyItem.Instrument);
                                    ConfigManager.SetProperty(PropertyItem.Instrument, firstInstrument.ToString());
                                    Instrument target = Instrument.Prefabs[firstInstrument];

                                    bool soundEffects = !target.Name.StartsWith("Mordhau", true, System.Globalization.CultureInfo.InvariantCulture);
                                    ConfigManager.SetProperty(PropertyItem.SoundEffects, soundEffects.ToString());
                                    ConfigManager.SetProperty(PropertyItem.LowestNoteId, target.LowestSentNote.ToString());
                                    ConfigManager.SetProperty(PropertyItem.AvaliableNoteCount, target.NoteCount.ToString());
                                    ConfigManager.SetProperty(PropertyItem.NoteCooldown, target.NoteCooldown.ToString());
                                    ConfigManager.SetProperty(PropertyItem.LowestPlayedNote, target.LowestPlayedNote.ToString());
                                    ConfigManager.SetProperty(PropertyItem.ForbidsChords, target.ForbidsChords.ToString());
                                    tsm.UpdateTrackSelectionForInstrument(oldInstrument);
                                    player.mordhauOutDevice.UpdateNoteIdBounds();
                                }
                                //}
                                //else
                                //{
                                //    SaveManager.WriteSaveFile(SaveManager.SaveFilePath + namingForm.textBoxPartName.Text, trackConverter.GetPartitionToString());
                                //    index.SaveIndex();
                                //    PopulateIndexList();
                                //    trackConverter = null;
                                //}

                                // Lastly, save the settings in a midi file with the same name, in the same folder, for ease of sharing...
                                // TODO: Consider storing these in appdata, and providing a button to access them.  Both might get complicated if I make partition playlists
                                // Actually... I think I will store them in appdata.
                                var midFileName = Path.Combine(partitionMidiPath, namingForm.textBoxPartName.Text + ".mid");
                                if (File.Exists(midFileName))
                                {
                                    File.Delete(midFileName);
                                }
                                Directory.CreateDirectory(partitionMidiPath);
                                Task.Run(() => tsm.SaveTrackManager(midFileName)); // Lutebot doesn't need this anytime soon - and shouldn't offer the option to load it until it exists anyway
                            }
                        }
                    }
                }
                else if (namingForm.DialogResult == DialogResult.Yes)
                {
                    // They wanted to just add it as a track
                    if (trackConverter == null)
                    {
                        trackConverter = new LuteMod.Converter.MordhauConverter();
                    }
                    // These ranges and settings only matter for FillTrack.  So re-setting them each time isn't a problem
                    trackConverter.Range               = ConfigManager.GetIntegerProperty(PropertyItem.AvaliableNoteCount);
                    trackConverter.LowNote             = ConfigManager.GetIntegerProperty(PropertyItem.LowestPlayedNote);
                    trackConverter.IsConversionEnabled = true;
                    trackConverter.SetDivision(player.sequence.Division); // This one could be weird
                    trackConverter.AddTrack();
                    trackConverter.SetEnabledTracksInTrack(trackConverter.GetTrackCount() - 1, tsm.MidiTracks.Values.ToList());
                    trackConverter.SetEnabledMidiChannelsInTrack(trackConverter.GetTrackCount() - 1, tsm.MidiChannels.Values.ToList());

                    trackConverter.FillTrack(trackConverter.GetTrackCount() - 1, player.ExtractMidiContent());
                }
            }
            else
            {
                MessageBox.Show("The partition is empty");
            }
        }