using System; using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.Xna.Framework.Audio; using StardewValley; namespace Omegasis.StardewSymphony { //also known as the music_pack internal class MusicManager { /********* ** Properties *********/ /// The valid season values. private readonly Season[] Seasons = Enum.GetValues(typeof(Season)).Cast().ToArray(); /********* ** Accessors *********/ /// The directory path containing the music. public string Directory { get; } /// The name of the wavebank file. public string WavebankName { get; } /// The name of the soundbank file. public string SoundbankName { get; } /// The loaded wavebank (if any). public WaveBank Wavebank { get; } /// The loaded soundbank (if any). public SoundBank Soundbank { get; } /// The default music to play if there isn't a more specific option. public IDictionary> DefaultSongs = MusicManager.CreateSeasonalSongList(); /// The music to play at night. public IDictionary> NightSongs = MusicManager.CreateSeasonalSongList(); /// The music to play on rainy days. public IDictionary> RainySongs = MusicManager.CreateSeasonalSongList(); /// The music to play on rainy nights. public IDictionary> RainyNightSongs = MusicManager.CreateSeasonalSongList(); /// Songs that play in specific locations. public Dictionary> LocationSongs { get; } = new Dictionary>(); /// Songs that play in specific locations on rainy days. public Dictionary> LocationRainSongs { get; } = new Dictionary>(); /// Songs that play in specific locations at night. public Dictionary> LocationNightSongs { get; } = new Dictionary>(); /// Songs that play in specific locations on rainy nights. public Dictionary> LocationRainNightSongs { get; } = new Dictionary>(); /********* ** Public methods *********/ /// Construct an instance. /// The name of the wavebank file. /// The name of the soundbank file. /// The directory path containing the music. public MusicManager(string wavebank, string soundbank, string directory) { // init data this.Directory = directory; this.WavebankName = wavebank + ".xwb"; this.SoundbankName = soundbank + ".xsb"; // init banks string wavePath = Path.Combine(this.Directory, this.WavebankName); string soundPath = Path.Combine(this.Directory, this.SoundbankName); Console.WriteLine(wavePath); Console.WriteLine(soundPath); if (File.Exists(wavePath)) this.Wavebank = new WaveBank(Game1.audioEngine, wavePath); if (File.Exists(Path.Combine(this.Directory, this.SoundbankName))) this.Soundbank = new SoundBank(Game1.audioEngine, soundPath); // update audio Game1.audioEngine.Update(); } /// Read cue names from a text file and adds them to a specific list. Morphs with specific conditional name. Conditionals are hardcoded. /// The conditional file name to read. /// The music list to update. public void LoadSeasonalSongs(string conditionalName, IDictionary cues) { string path = Path.Combine(this.Directory, "Music_Files", "Seasons", conditionalName + ".txt"); if (!File.Exists(path)) { Console.WriteLine($"Stardew Symohony:The specified music file could not be found. That music file is {conditionalName} which should be located at {path} but don't worry I'll create it for you right now. It's going to be blank though"); string[] text = new string[3]; text[0] = conditionalName + " music file. This file holds all of the music that will play when there is no music for this game location, or simply put this is default music. Simply type the name of the song below the wall of equal signs."; text[1] = "========================================================================================"; File.WriteAllLines(path, text); } else { Console.WriteLine($"Stardew Symphony:The music pack located at: {this.Directory} is processing the song info for the game location: {conditionalName}"); string[] text = File.ReadAllLines(path); int i = 2; var lineCount = File.ReadLines(path).Count(); while (i < lineCount) //the ordering seems bad, but it works. { if (Convert.ToString(text[i]) == "") break; if (Convert.ToString(text[i]) == "\n") break; foreach (Season season in this.Seasons) { // default music if ($"{season}".Equals(conditionalName, StringComparison.InvariantCultureIgnoreCase)) { string cueName = Convert.ToString(text[i]); i++; this.DefaultSongs[season].Add(this.Soundbank.GetCue(cueName)); if (!cues.Keys.Contains(cueName)) cues.Add(cueName, this); } // night music if ($"{season}_night".Equals(conditionalName, StringComparison.InvariantCultureIgnoreCase)) { string cueName = Convert.ToString(text[i]); i++; this.NightSongs[season].Add(this.Soundbank.GetCue(cueName)); if (!cues.Keys.Contains(cueName)) cues.Add(cueName, this); } // rain music if ($"{season}_rain".Equals(conditionalName, StringComparison.InvariantCultureIgnoreCase)) { string cueName = Convert.ToString(text[i]); i++; this.RainySongs[season].Add(this.Soundbank.GetCue(cueName)); if (!cues.Keys.Contains(cueName)) cues.Add(cueName, this); } // rainy night if ($"{season}_rain_night".Equals(conditionalName, StringComparison.InvariantCultureIgnoreCase)) { string cueName = Convert.ToString(text[i]); i++; this.RainyNightSongs[season].Add(this.Soundbank.GetCue(cueName)); if (!cues.Keys.Contains(cueName)) cues.Add(cueName, this); } } } if (i == 2) { // Monitor.Log("Just thought that I'd let you know that there are no songs associated with the music file located at " + mylocation3 +" this may be intentional, but just incase you were wanted music, now you knew which ones were blank."); return; } Console.WriteLine($"Stardew Symohony:The music pack located at: {this.Directory} has successfully processed the song info for the game location {conditionalName}"); } } /// Read cue names from a text file and adds them to a specific list. Morphs with specific conditional name. Conditionals are hardcoded. /// The conditional file name to read. /// The music list to update. public void Music_Loader_Locations(string conditionalName, IDictionary cues) { List locationSongs = new List(); //loads the data to the variables upon loading the game. var musicPath = this.Directory; string mylocation = Path.Combine(musicPath, "Music_Files", "Locations", conditionalName); string mylocation2 = mylocation; string mylocation3 = mylocation2 + ".txt"; if (!File.Exists(mylocation3)) //check to make sure the file actually exists { Console.WriteLine("StardewSymohony:A music list for the location " + conditionalName + " does not exist for the music pack located at " + mylocation3 + " which isn't a problem, I just thought I'd let you know since this may have been intentional. Also I'm creating it for you just incase. Cheers."); //Console.WriteLine("Creating the Config file"); string[] mystring3 = new string[3];//seems legit. mystring3[0] = conditionalName + " music file. This file holds all of the music that will play when at this game location. Simply type the name of the song below the wall of equal signs."; mystring3[1] = "========================================================================================"; File.WriteAllLines(mylocation3, mystring3); } else { Console.WriteLine("Stardew Symphony:The music pack located at: " + this.Directory + " is processing the song info for the game location: " + conditionalName); string[] readtext = File.ReadAllLines(mylocation3); int i = 2; var lineCount = File.ReadLines(mylocation3).Count(); while (i < lineCount) //the ordering seems bad, but it works. { if (Convert.ToString(readtext[i]) == "") break; if (Convert.ToString(readtext[i]) == "\n") break; string cueName = Convert.ToString(readtext[i]); i++; if (!cues.Keys.Contains(cueName)) { locationSongs.Add(this.Soundbank.GetCue(cueName)); cues.Add(cueName, this); } else locationSongs.Add(this.Soundbank.GetCue(cueName)); } if (i == 2) { // Monitor.Log("Just thought that I'd let you know that there are no songs associated with the music file located at " + mylocation3 + " this may be intentional, but just incase you were wanted music, now you knew which ones were blank."); return; } if (locationSongs.Count > 0) { this.LocationSongs.Add(conditionalName, locationSongs); Console.WriteLine("StardewSymhony:The music pack located at: " + this.Directory + " has successfully processed the song info for the game location: " + conditionalName); } } } /// Read cue names from a text file and adds them to a specific list. Morphs with specific conditional name. Conditionals are hardcoded. /// The conditional file name to read. /// The music list to update. public void Music_Loader_Locations_Rain(string conditionalName, IDictionary cues) { List locationSongs = new List(); var musicPath = this.Directory; string mylocation = Path.Combine(musicPath, "Music_Files", "Locations", conditionalName); string mylocation2 = mylocation; string mylocation3 = mylocation2 + ".txt"; if (!File.Exists(mylocation3)) //check to make sure the file actually exists { Console.WriteLine("StardewSymphony:A music list for the location " + conditionalName + " does not exist for the music pack located at " + mylocation3 + " which isn't a problem, I just thought I'd let you know since this may have been intentional. Also I'm creating it for you just incase. Cheers."); string[] mystring3 = new string[3];//seems legit. mystring3[0] = conditionalName + " music file. This file holds all of the music that will play when at this game location. Simply type the name of the song below the wall of equal signs."; mystring3[1] = "========================================================================================"; File.WriteAllLines(mylocation3, mystring3); } else { // add in data here string[] readtext = File.ReadAllLines(mylocation3); int i = 2; var lineCount = File.ReadLines(mylocation3).Count(); while (i < lineCount) //the ordering seems bad, but it works. { if (Convert.ToString(readtext[i]) == "") break; if (Convert.ToString(readtext[i]) == "\n") break; string cueName = Convert.ToString(readtext[i]); i++; if (!cues.Keys.Contains(cueName)) { locationSongs.Add(this.Soundbank.GetCue(cueName)); cues.Add(cueName, this); } else locationSongs.Add(this.Soundbank.GetCue(cueName)); } if (i == 2) { // Monitor.Log("Just thought that I'd let you know that there are no songs associated with the music file located at " + mylocation3 + " this may be intentional, but just incase you were wanted music, now you knew which ones were blank."); return; } if (locationSongs.Count > 0) { this.LocationRainSongs.Add(conditionalName, locationSongs); Console.WriteLine("StardewSymohony:The music pack located at: " + this.Directory + " has successfully processed the song info for the game location: " + conditionalName); } } } /// Read cue names from a text file and adds them to a specific list. Morphs with specific conditional name. Conditionals are hardcoded. /// The conditional file name to read. /// The music list to update. public void Music_Loader_Locations_Night(string conditionalName, IDictionary cues) { List locationSongs = new List(); //loads the data to the variables upon loading the game. var musicPath = this.Directory; string mylocation = Path.Combine(musicPath, "Music_Files", "Locations", conditionalName); string mylocation2 = mylocation; string mylocation3 = mylocation2 + ".txt"; if (!File.Exists(mylocation3)) //check to make sure the file actually exists { Console.WriteLine("StardewSymphony:A music list for the location " + conditionalName + " does not exist for the music pack located at " + mylocation3 + " which isn't a problem, I just thought I'd let you know since this may have been intentional. Also I'm creating it for you just incase. Cheers."); string[] mystring3 = new string[3];//seems legit. mystring3[0] = conditionalName + " music file. This file holds all of the music that will play when at this game location. Simply type the name of the song below the wall of equal signs."; mystring3[1] = "========================================================================================"; File.WriteAllLines(mylocation3, mystring3); } else { // add in data here string[] readtext = File.ReadAllLines(mylocation3); int i = 2; var lineCount = File.ReadLines(mylocation3).Count(); while (i < lineCount) //the ordering seems bad, but it works. { if (Convert.ToString(readtext[i]) == "") break; if (Convert.ToString(readtext[i]) == "\n") break; string cueName = Convert.ToString(readtext[i]); i++; if (!cues.Keys.Contains(cueName)) { locationSongs.Add(this.Soundbank.GetCue(cueName)); cues.Add(cueName, this); } else locationSongs.Add(this.Soundbank.GetCue(cueName)); } if (i == 2) { // Monitor.Log("Just thought that I'd let you know that there are no songs associated with the music file located at " + mylocation3 + " this may be intentional, but just incase you were wanted music, now you knew which ones were blank."); return; } if (locationSongs.Count > 0) { this.LocationNightSongs.Add(conditionalName, locationSongs); Console.WriteLine("StardewSymphonyLThe music pack located at: " + this.Directory + " has successfully processed the song info for the game location: " + conditionalName); } } } /// Read cue names from a text file and adds them to a specific list. Morphs with specific conditional name. Conditionals are hardcoded. /// The conditional file name to read. /// The music list to update. public void Music_Loader_Locations_Rain_Night(string conditionalName, IDictionary cues) { List locationSongs = new List(); var musicPath = this.Directory; string path = Path.Combine(musicPath, "Music_Files", "Locations", conditionalName + ".txt"); if (!File.Exists(path)) //check to make sure the file actually exists { Console.WriteLine("StardewSymphony:A music list for the location " + conditionalName + " does not exist for the music pack located at " + path + " which isn't a problem, I just thought I'd let you know since this may have been intentional. Also I'm creating it for you just incase. Cheers."); string[] text = new string[3];//seems legit. text[0] = conditionalName + " music file. This file holds all of the music that will play when at this game location. Simply type the name of the song below the wall of equal signs."; text[1] = "========================================================================================"; File.WriteAllLines(path, text); } else { //load in music stuff from the text files using the code below. string[] text = File.ReadAllLines(path); int i = 2; var lineCount = File.ReadLines(path).Count(); while (i < lineCount) //the ordering seems bad, but it works. { if (Convert.ToString(text[i]) == "") //if there is ever an empty line, stop processing the music file break; if (Convert.ToString(text[i]) == "\n") break; string cueName = Convert.ToString(text[i]); i++; if (!cues.Keys.Contains(cueName)) { locationSongs.Add(this.Soundbank.GetCue(cueName)); cues.Add(cueName, this); } else locationSongs.Add(this.Soundbank.GetCue(cueName)); } if (i == 2) { // Monitor.Log("Just thought that I'd let you know that there are no songs associated with the music file located at " + mylocation3 + " this may be intentional, but just incase you were wanted music, now you knew which ones were blank."); return; } if (locationSongs.Count > 0) { this.LocationRainNightSongs.Add(conditionalName, locationSongs); Console.WriteLine("StardewSymohony:The music pack located at: " + this.Directory + " has successfully processed the song info for the game location: " + conditionalName); } } } /// Create a dictionary of seasonal songs. private static IDictionary> CreateSeasonalSongList() { IDictionary> dict = new Dictionary>(); foreach (Season season in Enum.GetValues(typeof(Season))) dict[season] = new List(); return dict; } } }