/// <summary> /// Loads the music pack information from a json file. /// </summary> /// <param name="path"></param> /// <returns></returns> public static MusicPackMetaData readFromJson(string path) { string json = Path.Combine(path, "MusicPackInformation.json"); var meta = StardewSymphony.ModHelper.ReadJsonFile <MusicPackMetaData>(json); try { try { meta.Icon = new Texture2DExtended(StardewSymphony.ModHelper, StardewSymphony.getRelativeDirectory(Path.Combine(path, meta.pathToMusicPackIcon + ".png"))); } catch (Exception errr) { errr.ToString(); meta.Icon = new Texture2DExtended(StardewSymphony.ModHelper, StardewSymphony.getRelativeDirectory(Path.Combine(path, meta.pathToMusicPackIcon))); } } catch (Exception err) { err.ToString(); if (StardewSymphony.Config.EnableDebugLog) { StardewSymphony.ModMonitor.Log(err.ToString()); } } return(meta); }
/// <summary> /// Play a song. /// </summary> /// <param name="name">The name of the song to play.</param> public override void playSong(string name) { this.currentCue = this.getCue(name); if (this.currentCue == null) { return; //getCue will throw the error message. } Game1.waveBank = this.WaveBank; Game1.soundBank = this.SoundBank; this.currentCue.Play(); StardewSymphony.Reset(); }
/// <summary> /// Pause the currently playing song. /// </summary> /// <param name="name">Pause the current song that is playing.</param> public override void pauseSong() { if (this.currentCue == null) { return; } else { Game1.waveBank = this.WaveBank; Game1.soundBank = this.SoundBank; this.currentCue.Pause(); StardewSymphony.Reset(); } }
/// <summary>Get the name of the location of where I am at.</summary> public static string getLocationString() { try { string locName = Game1.currentLocation.Name; if (locName.StartsWith("UndergroundMine")) { StardewSymphony.DebugLog("LOC VALUE:" + locName); string splits = locName.Replace("UndergroundMine", ""); StardewSymphony.DebugLog("DEBUG VALUE:" + splits); int number = Convert.ToInt32(splits); if (number >= 1 && number <= 10) { return("UndergroundMine" + " Floors 1-10"); } if (number >= 11 && number <= 29) { return("UndergroundMine" + " Floors 11-29"); } if (number >= 31 && number <= 39) { return("UndergroundMine" + " Floors 31-39"); } if (number >= 40 && number <= 69) { return("UndergroundMine" + " Floors 40-69"); } if (number >= 70 && number <= 79) { return("UndergroundMine" + " Floors 70-79"); } if (number >= 80 && number <= 120) { return("UndergroundMine" + " Floors 80-120"); } } if (locName.Contains("Cabin") || Game1.currentLocation.isFarmBuildingInterior()) { locName = Game1.currentLocation.uniqueName.Value; } return(locName); } catch (Exception err) { StardewSymphony.ModMonitor.Log(err.ToString()); return(""); } }
/// <summary> /// Stops the currently playing song and nulls the current song. /// </summary> public override void stopSong() { if (this.currentCue == null) { return; } else { Game1.waveBank = this.WaveBank; Game1.soundBank = this.SoundBank; this.currentCue.Stop(AudioStopOptions.Immediate); StardewSymphony.Reset(); this.currentCue = null; } }
/// <summary>Load in the music files from the pack's respective Directory/Songs folder. Typically Content/Music/Wav/FolderName/Songs</summary> private void LoadMusicFiles() { DateTime startTime = DateTime.Now; DirectoryInfo songFolder = new DirectoryInfo(Path.Combine(this.ContentPack.DirectoryPath, this.MusicFolderName)); foreach (FileInfo file in songFolder.GetFiles()) { // get name string name = Path.GetFileNameWithoutExtension(file.Name); if (this.Sounds.ContainsKey(name)) { continue; } // load data SoundEffect effect = null; using (Stream waveFileStream = File.OpenRead(file.FullName)) { switch (file.Extension) { case ".wav": effect = SoundEffect.FromStream(waveFileStream); break; case ".mp3": using (Mp3FileReader reader = new Mp3FileReader(waveFileStream)) using (WaveStream pcmStream = WaveFormatConversionStream.CreatePcmStream(reader)) { string tempPath = Path.Combine(songFolder.FullName, $"{name}.wav"); StardewSymphony.ModMonitor.Log($"Converting: {tempPath}"); WaveFileWriter.CreateWaveFile(tempPath, pcmStream); using (Stream tempStream = File.OpenRead(tempPath)) effect = SoundEffect.FromStream(tempStream); File.Delete(tempPath); } break; case ".ogg": // Credits: https://social.msdn.microsoft.com/Forums/vstudio/en-US/100a97af-2a1c-4b28-b464-d43611b9b5d6/converting-multichannel-ogg-to-stereo-wav-file?forum=csharpgeneral using (VorbisWaveReader vorbisStream = new VorbisWaveReader(file.FullName)) { string tempPath = Path.Combine(songFolder.FullName, $"{name}.wav"); StardewSymphony.DebugLog($"Converting: {tempPath}"); WaveFileWriter.CreateWaveFile(tempPath, vorbisStream.ToWaveProvider16()); using (Stream tempStream = File.OpenRead(tempPath)) effect = SoundEffect.FromStream(tempStream); File.Delete(tempPath); } break; default: StardewSymphony.ModMonitor.Log($"Unsupported file extension {file.Extension}.", LogLevel.Warn); break; } } if (effect == null) { continue; } // add sound SoundEffectInstance instance = effect.CreateInstance(); this.Sounds.Add(name, instance); //this.SongInformation.listOfSongsWithoutTriggers.Add(name); this.SongInformation.songs.Add(name, new V2.SongInformation(name)); } // log loading time if (StardewSymphony.Config.EnableDebugLog) { StardewSymphony.ModMonitor.Log($"Time to load WAV music pack {this.Name}: {startTime.Subtract(DateTime.Now)}"); } }
/// <summary>Select the actual song to be played right now based on the selector key. The selector key should be called when the player's location changes.</summary> public void selectMusic(string songListKey, bool warpCheck = false) { StardewSymphony.DebugLog(SongSpecifics.GetKeySpecificity(songListKey).ToString()); StardewSymphony.DebugLog(songListKey); //Prevent generic song changes when running about. if (SongSpecifics.GetKeySpecificity(songListKey) == SongSpecifics.SongKeyType.None) { return; } if (SongSpecifics.IsKeyGeneric(songListKey)) { if (this.CurrentMusicPack != null) { if (this.CurrentMusicPack.IsPlaying()) { return; } } } //If I have warped and the key only is to be played when time changes prevent a new song from playing. //If the key is more specific (I.E has a location associated with it) then music will change. if (warpCheck == true && SongSpecifics.IsKeyTimeSpecific(songListKey)) { if (this.CurrentMusicPack != null) { if (this.CurrentMusicPack.IsPlaying()) { return; } } } // stop timer timer when music is selected this.Timer.Enabled = false; // get applicable music packs var listOfValidMusicPacks = this.GetApplicableMusicPacks(songListKey); string subKey = songListKey; //This chunk is to determine song specifics for location. while (listOfValidMusicPacks.Count == 0) { if (subKey.Length == 0) { break; } string[] subList = subKey.Split(SongSpecifics.seperator); if (subList.Length == 0) { break; //Because things would go bad otherwise. } subKey = ""; for (int i = 0; i < subList.Length - 1; i++) { subKey += subList[i]; if (i != subList.Length - 2) { subKey += SongSpecifics.seperator; } } if (subKey == "") { break; } if (StardewSymphony.Config.EnableDebugLog) { StardewSymphony.ModMonitor.Log(subKey, StardewModdingAPI.LogLevel.Alert); } listOfValidMusicPacks = this.GetApplicableMusicPacks(subKey); if (listOfValidMusicPacks.Count == 0) { //No valid songs to play at this time. if (StardewSymphony.Config.EnableDebugLog) { StardewSymphony.ModMonitor.Log("Error: There are no songs to play across any music pack for the song key: " + subKey + ". 1 Are you sure you did this properly?"); } //return; } } if (listOfValidMusicPacks.Count == 0) { //This chunk is used to determine more general seasonal specifics if song specifics couldn't be found. subKey = songListKey; string[] season = subKey.Split(SongSpecifics.seperator); subKey = ""; for (int i = 1; i < season.Length; i++) { subKey += season[i]; if (i != season.Length - 1) { subKey += SongSpecifics.seperator; } } if (string.IsNullOrEmpty(subKey)) { if (!this.checkGenericMusic(songListKey)) { if (StardewSymphony.Config.EnableDebugLog) { StardewSymphony.ModMonitor.Log("Error: There are no songs to play across any music pack for the song key: " + songListKey + ".2 Are you sure you did this properly?"); } StardewSymphony.menuChangedMusic = false; return; } } if (StardewSymphony.Config.EnableDebugLog) { StardewSymphony.ModMonitor.Log(subKey, StardewModdingAPI.LogLevel.Alert); } listOfValidMusicPacks = this.GetApplicableMusicPacks(subKey); if (listOfValidMusicPacks.Count == 0) { //No valid songs to play at this time. if (StardewSymphony.Config.EnableDebugLog) { StardewSymphony.ModMonitor.Log("Error: There are no songs to play across any music pack for the song key: " + subKey + ".3 Are you sure you did this properly?"); } //return; } //Try to get more specific. //????? What does this part even do anymore??? while (listOfValidMusicPacks.Count == 0) { if (subKey.Length == 0) { break; } string[] subList = subKey.Split(SongSpecifics.seperator); if (subList.Length == 0) { break; //Because things would go bad otherwise. } subKey = ""; for (int i = 0; i < subList.Length - 1; i++) { subKey += subList[i]; if (i != subList.Length - 2) { subKey += SongSpecifics.seperator; } } if (subKey == "") { break; } if (StardewSymphony.Config.EnableDebugLog) { StardewSymphony.ModMonitor.Log(subKey, StardewModdingAPI.LogLevel.Alert); } listOfValidMusicPacks = this.GetApplicableMusicPacks(subKey); if (listOfValidMusicPacks.Count == 0) { //No valid songs to play at this time. if (StardewSymphony.Config.EnableDebugLog) { StardewSymphony.ModMonitor.Log("Error: There are no songs to play across any music pack for the song key: " + subKey + ".4 Are you sure you did this properly?"); } //return; } } } //If the list of valid packs are 0, check if I'm currently at an event or festival or get some location specific music and try to play a generalized song from there. if (listOfValidMusicPacks.Count == 0) { if (!this.checkGenericMusic(songListKey)) { //No valid songs to play at this time. if (StardewSymphony.Config.EnableDebugLog) { StardewSymphony.ModMonitor.Log("Error: There are no songs to play across any music pack for the song key: " + songListKey + ".7 Are you sure you did this properly?"); } StardewSymphony.menuChangedMusic = false; return; } } string[] sizeList = subKey.Split(SongSpecifics.seperator); if (this.CurrentMusicPack != null) { //If I am trying to play a generic song and a generic song is playing don't change the music. //If I am trying to play a generic song and a non-generic song is playing, then play my generic song since I don't want to play the specific music anymore. if (sizeList.Length < 3 && (this.CurrentMusicPack.IsPlaying() && !this.lastSongWasLocationSpecific)) { if (StardewSymphony.Config.EnableDebugLog) { StardewSymphony.ModMonitor.Log("Non specific music change detected. Not going to change the music this time"); } return; } } this.lastSongWasLocationSpecific = sizeList.Length >= 3; //If there is a valid key for the place/time/event/festival I am at, play it! int randInt = this.Random.Next(0, listOfValidMusicPacks.Count - 1); var musicPackPair = listOfValidMusicPacks.ElementAt(randInt); //used to swap the music packs and stop the last playing song. this.SwapMusicPacks(musicPackPair.Key.Name); string songName = musicPackPair.Value.ElementAt(this.Random.Next(0, musicPackPair.Value.Count)); this.CurrentMusicPack.PlaySong(songName); }