Merge pull request #49 from Pathoschild/migrate-to-content-packs
Refactor Stardew Symphony to use content packs, add readme, drop XACT support
|
@ -3,22 +3,22 @@ namespace StardewSymphonyRemastered
|
|||
/// <summary>A class that handles all of the config files for this mod.</summary>
|
||||
public class Config
|
||||
{
|
||||
/// <summary>Whether or not to display debug log information on the SMAPI console for this mod.</summary>
|
||||
/// <summary>Whether to show debug logs in the SMAPI console.</summary>
|
||||
public bool EnableDebugLog { get; set; } = false;
|
||||
|
||||
/// <summary>The minimum delay between songs in terms of milliseconds.</summary>
|
||||
/// <summary>The minimum delay between songs in milliseconds.</summary>
|
||||
public int MinimumDelayBetweenSongsInMilliseconds { get; set; } = 5000;
|
||||
|
||||
/// <summary>The maximum delay between songs in terms of milliseconds.</summary>
|
||||
/// <summary>The maximum delay between songs in milliseconds.</summary>
|
||||
public int MaximumDelayBetweenSongsInMilliseconds { get; set; } = 60000;
|
||||
|
||||
/// <summary>The key binding to open up the menu music.</summary>
|
||||
/// <summary>The key binding to open the menu music.</summary>
|
||||
public string KeyBinding { get; set; } = "L";
|
||||
|
||||
/// <summary>Used to write a .json file for every possible option for a music pack. Use at your own risk!</summary>
|
||||
public bool writeAllConfigMusicOptions { get; set; } = false;
|
||||
/// <summary>Whether to write a JSON file for every possible option for a music pack. Use at your own risk!</summary>
|
||||
public bool WriteAllConfigMusicOptions { get; set; } = false;
|
||||
|
||||
/// <summary>Used to completely disable the Stardew Valley OST.</summary>
|
||||
public bool disableStardewMusic { get; set; } = false;
|
||||
/// <summary>Whether to completely disable the Stardew Valley OST.</summary>
|
||||
public bool DisableStardewMusic { get; set; } = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "Omegas's Music Data Example",
|
||||
"author": "Omegasis",
|
||||
"description": "Just a simple example of how metadata is formated for music packs. Feel free to copy and edit this one!",
|
||||
"versionInfo": "1.0.0 CoolExample",
|
||||
"pathToMusicPackIcon": "Icon",
|
||||
"Icon": null
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
Place the .wav song files in the Songs folder, modify the MusicPackInformation.json as desired, and then run!
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "Omegas's Music Data Example",
|
||||
"author": "Omegasis",
|
||||
"description": "Just a simple example of how metadata is formated for music packs. Feel free to copy and edit this one!",
|
||||
"versionInfo": "1.0.0 CoolExample",
|
||||
"pathToMusicPackIcon": "Icon.png",
|
||||
"Icon": null
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
Place the Wave Bank.xwb file and Sound Bank.xsb file you created in XACT in a similar directory in Content/Music/XACT/SoundPackName.
|
||||
Modify MusicPackInformation.json as desire!
|
||||
Run the mod!
|
|
@ -1,196 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using StardewValley;
|
||||
|
||||
namespace StardewSymphonyRemastered.Framework
|
||||
{
|
||||
public class MusicHexProcessor
|
||||
{
|
||||
/*********
|
||||
** Properties
|
||||
*********/
|
||||
/// <summary>All of the music/soundbanks and their locations.</summary>
|
||||
private readonly XACTMusicPack MasterList;
|
||||
|
||||
/// <summary>The registered soundbanks.</summary>
|
||||
private readonly List<string> SoundBanks = new List<string>();
|
||||
|
||||
/// <summary>The callback to reset the game audio.</summary>
|
||||
private readonly Action Reset;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="masterList">All of the music/soundbanks and their locations.</param>
|
||||
/// <param name="reset">The callback to reset the game audio.</param>
|
||||
public MusicHexProcessor(XACTMusicPack masterList, Action reset)
|
||||
{
|
||||
this.MasterList = masterList;
|
||||
this.Reset = reset;
|
||||
}
|
||||
|
||||
/// <summary>Add a file path to the list of soundbanks.</summary>
|
||||
/// <param name="path">The soundbank file path.</param>
|
||||
public void AddSoundBank(string path)
|
||||
{
|
||||
this.SoundBanks.Add(path);
|
||||
}
|
||||
|
||||
/// <summary>Process the soundbank.swb file's hex info and extract the song names from it.</summary>
|
||||
public static List<string> ProcessSongNamesFromHex(XACTMusicPack musicPack, Action reset, string FileName)
|
||||
{
|
||||
|
||||
List<string> cleanCueNames = new List<string>();
|
||||
byte[] array = File.ReadAllBytes(FileName);
|
||||
string rawName = FileName.Substring(0, FileName.Length - 4);
|
||||
string cueName = rawName + "CueList.txt";
|
||||
|
||||
//Not used as the music pack can change between loads
|
||||
/*
|
||||
if (File.Exists(cueName))
|
||||
{
|
||||
string[] arr = File.ReadAllLines(cueName);
|
||||
List<string> names = new List<string>();
|
||||
foreach(var v in arr)
|
||||
{
|
||||
names.Add(v);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
*/
|
||||
string hexDumpContents = HexDump(array);
|
||||
|
||||
string rawHexName = rawName + "HexDump.txt";
|
||||
File.WriteAllText(rawHexName, hexDumpContents);
|
||||
|
||||
string[] readText = File.ReadAllLines(rawHexName);
|
||||
string largeString = "";
|
||||
foreach (string line in readText)
|
||||
{
|
||||
try
|
||||
{
|
||||
string newString = "";
|
||||
for (int i = 62; i <= 77; i++)
|
||||
newString += line[i];
|
||||
largeString += newString;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
string[] splits = largeString.Split('ÿ');
|
||||
string fix = "";
|
||||
foreach (string s in splits)
|
||||
{
|
||||
if (s == "")
|
||||
continue;
|
||||
fix += s;
|
||||
}
|
||||
splits = fix.Split('.');
|
||||
|
||||
foreach (string split in splits)
|
||||
{
|
||||
if (split == "")
|
||||
continue;
|
||||
try
|
||||
{
|
||||
Game1.waveBank = musicPack.WaveBank;
|
||||
Game1.soundBank = musicPack.SoundBank;
|
||||
|
||||
if (Game1.soundBank.GetCue(split) != null)
|
||||
cleanCueNames.Add(split);
|
||||
|
||||
reset.Invoke();
|
||||
}
|
||||
catch
|
||||
{
|
||||
reset.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
return cleanCueNames;
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
private static string HexDump(byte[] bytes, int bytesPerLine = 16)
|
||||
{
|
||||
if (bytes == null)
|
||||
return "<null>";
|
||||
|
||||
int bytesLength = bytes.Length;
|
||||
|
||||
char[] hexChars = "0123456789ABCDEF".ToCharArray();
|
||||
|
||||
int firstHexColumn =
|
||||
8 // 8 characters for the address
|
||||
+ 3; // 3 spaces
|
||||
|
||||
int firstCharColumn = firstHexColumn
|
||||
+ bytesPerLine * 3 // - 2 digit for the hexadecimal value and 1 space
|
||||
+ (bytesPerLine - 1) / 8 // - 1 extra space every 8 characters from the 9th
|
||||
+ 2; // 2 spaces
|
||||
|
||||
int lineLength = firstCharColumn
|
||||
+ bytesPerLine // - characters to show the ascii value
|
||||
+ Environment.NewLine.Length; // Carriage return and line feed (should normally be 2)
|
||||
|
||||
char[] line = (new string(' ', lineLength - 2) + Environment.NewLine).ToCharArray();
|
||||
int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine;
|
||||
StringBuilder result = new StringBuilder(expectedLines * lineLength);
|
||||
|
||||
for (int i = 0; i < bytesLength; i += bytesPerLine)
|
||||
{
|
||||
line[0] = hexChars[(i >> 28) & 0xF];
|
||||
line[1] = hexChars[(i >> 24) & 0xF];
|
||||
line[2] = hexChars[(i >> 20) & 0xF];
|
||||
line[3] = hexChars[(i >> 16) & 0xF];
|
||||
line[4] = hexChars[(i >> 12) & 0xF];
|
||||
line[5] = hexChars[(i >> 8) & 0xF];
|
||||
line[6] = hexChars[(i >> 4) & 0xF];
|
||||
line[7] = hexChars[(i >> 0) & 0xF];
|
||||
|
||||
int hexColumn = firstHexColumn;
|
||||
int charColumn = firstCharColumn;
|
||||
|
||||
for (int j = 0; j < bytesPerLine; j++)
|
||||
{
|
||||
if (j > 0 && (j & 7) == 0) hexColumn++;
|
||||
if (i + j >= bytesLength)
|
||||
{
|
||||
line[hexColumn] = ' ';
|
||||
line[hexColumn + 1] = ' ';
|
||||
line[charColumn] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
byte b = bytes[i + j];
|
||||
line[hexColumn] = hexChars[(b >> 4) & 0xF];
|
||||
line[hexColumn + 1] = hexChars[b & 0xF];
|
||||
line[charColumn] = GetAsciiSymbol(b);
|
||||
}
|
||||
hexColumn += 3;
|
||||
charColumn++;
|
||||
}
|
||||
result.Append(line);
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
public static char GetAsciiSymbol(byte ch)
|
||||
{
|
||||
if (ch < 32) return '.'; // Non-printable ASCII
|
||||
if (ch < 127) return (char)ch; // Normal ASCII
|
||||
// Handle the hole in Latin-1
|
||||
if (ch == 127) return '.';
|
||||
if (ch < 0x90) return "€.‚ƒ„…†‡ˆ‰Š‹Œ.Ž."[ch & 0xF];
|
||||
if (ch < 0xA0) return ".‘’“”•–—˜™š›œ.žŸ"[ch & 0xF];
|
||||
if (ch == 0xAD) return '.'; // Soft hyphen: this symbol is zero-width even in monospace fonts
|
||||
return (char)ch; // Normal Latin-1
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,169 +9,103 @@ namespace StardewSymphonyRemastered.Framework
|
|||
/// <summary>Manages all music for the mod.</summary>
|
||||
public class MusicManager
|
||||
{
|
||||
/// <summary>A dictionary containing all of the music packs loaded in.</summary>
|
||||
public Dictionary<string, MusicPack> musicPacks;
|
||||
/*********
|
||||
** Fields
|
||||
*********/
|
||||
/// <summary>The RNG used to select music packs and songs.</summary>
|
||||
private readonly Random Random = new Random();
|
||||
|
||||
public MusicPack currentMusicPack;
|
||||
/// <summary>The delay timer between songs.</summary>
|
||||
private readonly Timer Timer = new Timer();
|
||||
|
||||
private readonly Random packSelector;
|
||||
private readonly Random songSelector;
|
||||
private bool lastSongWasLocationSpecific;
|
||||
|
||||
Timer timer;
|
||||
|
||||
bool lastSongWasLocationSpecific;
|
||||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The loaded music packs.</summary>
|
||||
public IDictionary<string, MusicPack> MusicPacks { get; } = new Dictionary<string, MusicPack>();
|
||||
|
||||
/// <summary>The current music pack playing music, if any.</summary>
|
||||
public MusicPack CurrentMusicPack { get; private set; }
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
public MusicManager()
|
||||
{
|
||||
this.musicPacks = new Dictionary<string, MusicPack>();
|
||||
this.currentMusicPack = null;
|
||||
this.packSelector = new Random(Game1.random.Next(1, 1000000));
|
||||
this.songSelector = new Random(Game1.player.deepestMineLevel + Game1.player.facingDirection + this.packSelector.Next(0, 10000));
|
||||
this.lastSongWasLocationSpecific = false;
|
||||
this.Timer.Elapsed += this.OnTimerFinished;
|
||||
}
|
||||
|
||||
/// <summary>Swaps between referenced music packs and stops the last playing song.</summary>
|
||||
/// <param name="nameOfNewMusicPack"></param>
|
||||
public void swapMusicPacks(string nameOfNewMusicPack)
|
||||
/// <summary>Swap between referenced music packs and stop the current song.</summary>
|
||||
/// <param name="nameOfNewMusicPack">The name of the new music pack to select.</param>
|
||||
public void SwapMusicPacks(string nameOfNewMusicPack)
|
||||
{
|
||||
if (this.isMusicPackValid(nameOfNewMusicPack))
|
||||
{
|
||||
this.currentMusicPack?.stopSong();
|
||||
this.currentMusicPack = this.getMusicPack(nameOfNewMusicPack);
|
||||
}
|
||||
else if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log("ERROR: Music Pack " + nameOfNewMusicPack + " isn't valid for some reason.", StardewModdingAPI.LogLevel.Alert);
|
||||
}
|
||||
|
||||
/// <summary>Updtes the timer every second to check if a song is playing or not.</summary>
|
||||
public void updateTimer()
|
||||
{
|
||||
|
||||
if (this.currentMusicPack == null) return;
|
||||
if (StardewSymphony.Config.disableStardewMusic)
|
||||
{
|
||||
if (this.currentMusicPack.isPlaying())
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
string songName = Game1.currentSong.Name.ToLower();
|
||||
|
||||
if (this.currentMusicPack.isPlaying() || (Game1.currentSong.IsPlaying && !songName.Contains("ambient")))
|
||||
return;
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (this.currentMusicPack.isPlaying())
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.timer == null)
|
||||
{
|
||||
Random r = new Random(Game1.random.Next());
|
||||
int val = r.Next(StardewSymphony.Config.MinimumDelayBetweenSongsInMilliseconds, StardewSymphony.Config.MaximumDelayBetweenSongsInMilliseconds + 1);
|
||||
//StardewSymphony.ModMonitor.Log("Music Pack is not playing! Generate a new timer! Delay: "+val.ToString());
|
||||
this.timer = new Timer(val);
|
||||
this.timer.Elapsed += this.onTimerFinished;
|
||||
this.timer.Enabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.timer.Enabled = true;
|
||||
this.timer.Elapsed += this.onTimerFinished;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Selects a new song when the timer delay runs out.</summary>
|
||||
public void onTimerFinished(object source, ElapsedEventArgs e)
|
||||
{
|
||||
if (this.currentMusicPack.isPlaying())
|
||||
{
|
||||
this.timer.Enabled = false;
|
||||
this.timer = null;
|
||||
return;
|
||||
}
|
||||
//StardewSymphony.ModMonitor.Log("AHH THE TIMER FINISHED!");
|
||||
this.timer.Enabled = false;
|
||||
this.timer.Elapsed -= this.onTimerFinished;
|
||||
|
||||
this.selectMusic(SongSpecifics.getCurrentConditionalString());
|
||||
this.timer = null;
|
||||
}
|
||||
|
||||
/// <summary>Plays the song from the currently loaded music pack.</summary>
|
||||
/// <param name="songName"></param>
|
||||
public void playSongFromCurrentPack(string songName)
|
||||
{
|
||||
this.currentMusicPack?.playSong(songName);
|
||||
}
|
||||
|
||||
/// <summary>Resumes the paused song from the current music pack.</summary>
|
||||
public void pauseSongFromCurrentPack()
|
||||
{
|
||||
this.currentMusicPack?.pauseSong();
|
||||
}
|
||||
|
||||
/// <summary>Stops the song from the current music pack.</summary>
|
||||
public void stopSongFromCurrentMusicPack()
|
||||
{
|
||||
this.currentMusicPack?.stopSong();
|
||||
}
|
||||
|
||||
/// <summary>Resumes the song from the current music pack.</summary>
|
||||
public void resumeSongFromCurrentMusicPack()
|
||||
{
|
||||
this.currentMusicPack?.resumeSong();
|
||||
}
|
||||
|
||||
/// <summary>Returns the name of the currently playing song.</summary>
|
||||
public string getNameOfCurrentlyPlayingSong()
|
||||
{
|
||||
return this.currentMusicPack?.getNameOfCurrentSong() ?? "";
|
||||
}
|
||||
|
||||
/// <summary>Get the information associated with the current music pack.</summary>
|
||||
public MusicPackMetaData getMusicPackInformation()
|
||||
{
|
||||
return this.currentMusicPack?.musicPackInformation;
|
||||
}
|
||||
|
||||
/// <summary>Checks to see if the music pack has been loaded into the Music Manager.</summary>
|
||||
public bool isMusicPackValid(string nameOfMusicPack)
|
||||
{
|
||||
return this.musicPacks.ContainsKey(nameOfMusicPack);
|
||||
}
|
||||
|
||||
/// <summary>Gets the music pack from the</summary>
|
||||
public MusicPack getMusicPack(string name)
|
||||
{
|
||||
if (!this.isMusicPackValid(name))
|
||||
if (!this.MusicPacks.TryGetValue(nameOfNewMusicPack, out MusicPack musicPack))
|
||||
{
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log("Error, the music pack: " + name + " is not found. Please make sure it is loaded in and try again.");
|
||||
return null;
|
||||
StardewSymphony.ModMonitor.Log($"ERROR: Music Pack '{nameOfNewMusicPack}' isn't valid for some reason.", StardewModdingAPI.LogLevel.Alert);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var pair in this.musicPacks)
|
||||
this.CurrentMusicPack?.StopSong();
|
||||
this.CurrentMusicPack = musicPack;
|
||||
}
|
||||
|
||||
/// <summary>Updates the timer every second to check whether a song is playing.</summary>
|
||||
public void UpdateTimer()
|
||||
{
|
||||
if (name == pair.Key)
|
||||
return pair.Value;
|
||||
}
|
||||
if (this.CurrentMusicPack == null)
|
||||
return;
|
||||
|
||||
return null; //Needed I suppose to ensure this function compiles.
|
||||
}
|
||||
|
||||
/// <summary>Iterates across all music packs and determines which music packs contain songs that can be played right now.</summary>
|
||||
public Dictionary<MusicPack, List<Song>> getListOfApplicableMusicPacks(string songListKey)
|
||||
if (StardewSymphony.Config.DisableStardewMusic)
|
||||
{
|
||||
Dictionary<MusicPack, List<Song>> listOfValidDictionaries = new Dictionary<MusicPack, List<Song>>();
|
||||
foreach (var v in this.musicPacks)
|
||||
if (this.CurrentMusicPack.IsPlaying())
|
||||
return;
|
||||
}
|
||||
else if (this.CurrentMusicPack.IsPlaying() || (Game1.currentSong?.IsPlaying == true && !Game1.currentSong.Name.ToLower().Contains("ambient")))
|
||||
return;
|
||||
|
||||
if (!this.Timer.Enabled)
|
||||
{
|
||||
this.Timer.Interval = this.Random.Next(StardewSymphony.Config.MinimumDelayBetweenSongsInMilliseconds, StardewSymphony.Config.MaximumDelayBetweenSongsInMilliseconds + 1);
|
||||
this.Timer.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Choose a new song when a delay runs out.</summary>
|
||||
private void OnTimerFinished(object source, ElapsedEventArgs e)
|
||||
{
|
||||
this.Timer.Enabled = false;
|
||||
if (!this.CurrentMusicPack.IsPlaying())
|
||||
this.selectMusic(SongSpecifics.getCurrentConditionalString());
|
||||
}
|
||||
|
||||
/// <summary>Play a song from the current music pack.</summary>
|
||||
/// <param name="songName">The song to play.</param>
|
||||
public void PlaySongFromCurrentPack(string songName)
|
||||
{
|
||||
this.CurrentMusicPack?.PlaySong(songName);
|
||||
}
|
||||
|
||||
/// <summary>Stop the current song being played.</summary>
|
||||
public void stopSongFromCurrentMusicPack()
|
||||
{
|
||||
this.CurrentMusicPack?.StopSong();
|
||||
}
|
||||
|
||||
/// <summary>Get all music packs which contain songs that can be played right now.</summary>
|
||||
public Dictionary<MusicPack, List<string>> GetApplicableMusicPacks(string songListKey)
|
||||
{
|
||||
Dictionary<MusicPack, List<string>> listOfValidDictionaries = new Dictionary<MusicPack, List<string>>();
|
||||
foreach (var v in this.MusicPacks)
|
||||
{
|
||||
try
|
||||
{
|
||||
var songList = v.Value.songInformation.getSongList(songListKey).Value;
|
||||
var songList = v.Value.SongInformation.getSongList(songListKey).Value;
|
||||
if (songList.Count > 0)
|
||||
listOfValidDictionaries.Add(v.Value, songList);
|
||||
}
|
||||
|
@ -180,14 +114,14 @@ namespace StardewSymphonyRemastered.Framework
|
|||
return listOfValidDictionaries;
|
||||
}
|
||||
|
||||
public Dictionary<MusicPack, List<Song>> getListOfApplicableMusicPacksForFestivals()
|
||||
public Dictionary<MusicPack, List<string>> GetListOfApplicableMusicPacksForFestivals()
|
||||
{
|
||||
Dictionary<MusicPack, List<Song>> listOfValidDictionaries = new Dictionary<MusicPack, List<Song>>();
|
||||
foreach (var v in this.musicPacks)
|
||||
Dictionary<MusicPack, List<string>> listOfValidDictionaries = new Dictionary<MusicPack, List<string>>();
|
||||
foreach (var v in this.MusicPacks)
|
||||
{
|
||||
try
|
||||
{
|
||||
var songList = v.Value.songInformation.getFestivalMusic();
|
||||
var songList = v.Value.SongInformation.getFestivalMusic();
|
||||
if (songList.Count > 0)
|
||||
listOfValidDictionaries.Add(v.Value, songList);
|
||||
}
|
||||
|
@ -196,14 +130,14 @@ namespace StardewSymphonyRemastered.Framework
|
|||
return listOfValidDictionaries;
|
||||
}
|
||||
|
||||
public Dictionary<MusicPack, List<Song>> getListOfApplicableMusicPacksForEvents()
|
||||
public Dictionary<MusicPack, List<string>> GetListOfApplicableMusicPacksForEvents()
|
||||
{
|
||||
Dictionary<MusicPack, List<Song>> listOfValidDictionaries = new Dictionary<MusicPack, List<Song>>();
|
||||
foreach (var v in this.musicPacks)
|
||||
Dictionary<MusicPack, List<string>> listOfValidDictionaries = new Dictionary<MusicPack, List<string>>();
|
||||
foreach (var v in this.MusicPacks)
|
||||
{
|
||||
try
|
||||
{
|
||||
var songList = v.Value.songInformation.getEventMusic();
|
||||
var songList = v.Value.SongInformation.getEventMusic();
|
||||
if (songList.Count > 0)
|
||||
listOfValidDictionaries.Add(v.Value, songList);
|
||||
}
|
||||
|
@ -212,47 +146,34 @@ namespace StardewSymphonyRemastered.Framework
|
|||
return listOfValidDictionaries;
|
||||
}
|
||||
|
||||
public void selectMenuMusic(string songListKey)
|
||||
public void SelectMenuMusic(string songListKey)
|
||||
{
|
||||
//Nullify the timer when new music is selected.
|
||||
this.timer = null;
|
||||
// stop timer when new music is selected
|
||||
this.Timer.Enabled = false;
|
||||
|
||||
var listOfValidMusicPacks = this.getListOfApplicableMusicPacks(songListKey);
|
||||
// get applicable music packs
|
||||
var listOfValidMusicPacks = this.GetApplicableMusicPacks(songListKey);
|
||||
if (listOfValidMusicPacks.Count == 0)
|
||||
return;
|
||||
|
||||
if (listOfValidMusicPacks.Count == 0) return;
|
||||
|
||||
|
||||
int randInt = this.packSelector.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.musicPackInformation.name);
|
||||
|
||||
int randInt2 = this.songSelector.Next(0, musicPackPair.Value.Count);
|
||||
|
||||
|
||||
var songName = musicPackPair.Value.ElementAt(randInt2);
|
||||
|
||||
this.currentMusicPack.playSong(songName.name);
|
||||
// swap to new music pack
|
||||
var pair = listOfValidMusicPacks.ElementAt(this.Random.Next(0, listOfValidMusicPacks.Count - 1));
|
||||
this.SwapMusicPacks(pair.Key.Name);
|
||||
string songName = pair.Value.ElementAt(this.Random.Next(0, pair.Value.Count));
|
||||
this.CurrentMusicPack.PlaySong(songName);
|
||||
|
||||
StardewSymphony.menuChangedMusic = true;
|
||||
|
||||
}
|
||||
/// <summary>Selects the actual song to be played right now based off of the selector key. The selector key should be called when the player's location changes.</summary>
|
||||
/// <param name="songListKey"></param>
|
||||
/// <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)
|
||||
{
|
||||
//Nullify the timer when new music is selected.
|
||||
this.timer = null;
|
||||
|
||||
var listOfValidMusicPacks = this.getListOfApplicableMusicPacks(songListKey);
|
||||
// stop timer timer when music is selected
|
||||
this.Timer.Enabled = false;
|
||||
|
||||
// get applicable music packs
|
||||
var listOfValidMusicPacks = this.GetApplicableMusicPacks(songListKey);
|
||||
string subKey = songListKey;
|
||||
//Try to get more specific.
|
||||
|
||||
|
||||
|
||||
//This chunk is to determine song specifics for location.
|
||||
while (listOfValidMusicPacks.Count == 0)
|
||||
|
@ -276,7 +197,7 @@ namespace StardewSymphonyRemastered.Framework
|
|||
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log(subKey, StardewModdingAPI.LogLevel.Alert);
|
||||
listOfValidMusicPacks = this.getListOfApplicableMusicPacks(subKey);
|
||||
listOfValidMusicPacks = this.GetApplicableMusicPacks(subKey);
|
||||
if (listOfValidMusicPacks.Count == 0)
|
||||
{
|
||||
//No valid songs to play at this time.
|
||||
|
@ -310,7 +231,7 @@ namespace StardewSymphonyRemastered.Framework
|
|||
}
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log(subKey, StardewModdingAPI.LogLevel.Alert);
|
||||
listOfValidMusicPacks = this.getListOfApplicableMusicPacks(subKey);
|
||||
listOfValidMusicPacks = this.GetApplicableMusicPacks(subKey);
|
||||
if (listOfValidMusicPacks.Count == 0)
|
||||
{
|
||||
//No valid songs to play at this time.
|
||||
|
@ -339,7 +260,7 @@ namespace StardewSymphonyRemastered.Framework
|
|||
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log(subKey, StardewModdingAPI.LogLevel.Alert);
|
||||
listOfValidMusicPacks = this.getListOfApplicableMusicPacks(subKey);
|
||||
listOfValidMusicPacks = this.GetApplicableMusicPacks(subKey);
|
||||
if (listOfValidMusicPacks.Count == 0)
|
||||
{
|
||||
//No valid songs to play at this time.
|
||||
|
@ -365,11 +286,11 @@ namespace StardewSymphonyRemastered.Framework
|
|||
|
||||
string[] sizeList = subKey.Split(SongSpecifics.seperator);
|
||||
|
||||
if (this.currentMusicPack != null)
|
||||
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 (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");
|
||||
|
@ -381,33 +302,28 @@ namespace StardewSymphonyRemastered.Framework
|
|||
|
||||
//If there is a valid key for the place/time/event/festival I am at, play it!
|
||||
|
||||
int randInt = this.packSelector.Next(0, listOfValidMusicPacks.Count - 1);
|
||||
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.musicPackInformation.name);
|
||||
|
||||
int randInt2 = this.songSelector.Next(0, musicPackPair.Value.Count);
|
||||
|
||||
|
||||
var songName = musicPackPair.Value.ElementAt(randInt2);
|
||||
|
||||
this.currentMusicPack.playSong(songName.name);
|
||||
this.SwapMusicPacks(musicPackPair.Key.Name);
|
||||
string songName = musicPackPair.Value.ElementAt(this.Random.Next(0, musicPackPair.Value.Count));
|
||||
this.CurrentMusicPack.PlaySong(songName);
|
||||
}
|
||||
|
||||
|
||||
public Dictionary<MusicPack, List<Song>> getLocationSpecificMusic()
|
||||
public Dictionary<MusicPack, List<string>> getLocationSpecificMusic()
|
||||
{
|
||||
Dictionary<MusicPack, List<Song>> listOfValidDictionaries = new Dictionary<MusicPack, List<Song>>();
|
||||
Dictionary<MusicPack, List<string>> listOfValidDictionaries = new Dictionary<MusicPack, List<string>>();
|
||||
//StardewSymphony.ModMonitor.Log(SongSpecifics.getCurrentConditionalString(true));
|
||||
|
||||
foreach (var v in this.musicPacks)
|
||||
foreach (var v in this.MusicPacks)
|
||||
{
|
||||
try
|
||||
{
|
||||
var songList = v.Value.songInformation.getSongList(SongSpecifics.getCurrentConditionalString(true)).Value;
|
||||
var songList = v.Value.SongInformation.getSongList(SongSpecifics.getCurrentConditionalString(true)).Value;
|
||||
if (songList == null) return null;
|
||||
if (songList.Count > 0)
|
||||
{
|
||||
|
@ -426,21 +342,17 @@ namespace StardewSymphonyRemastered.Framework
|
|||
if (Game1.CurrentEvent.isFestival)
|
||||
{
|
||||
//Try to play a generalized festival song.
|
||||
var listOfFestivalPacks = this.getListOfApplicableMusicPacksForFestivals();
|
||||
var listOfFestivalPacks = this.GetListOfApplicableMusicPacksForFestivals();
|
||||
if (listOfFestivalPacks.Count > 0)
|
||||
{
|
||||
int randFestivalPack = this.packSelector.Next(0, listOfFestivalPacks.Count - 1);
|
||||
int randFestivalPack = this.Random.Next(0, listOfFestivalPacks.Count - 1);
|
||||
|
||||
var festivalMusicPackPair = listOfFestivalPacks.ElementAt(randFestivalPack);
|
||||
|
||||
//used to swap the music packs and stop the last playing song.
|
||||
this.swapMusicPacks(festivalMusicPackPair.Key.musicPackInformation.name);
|
||||
|
||||
int randFestivalPack2 = this.songSelector.Next(0, festivalMusicPackPair.Value.Count);
|
||||
|
||||
var festivalSongName = festivalMusicPackPair.Value.ElementAt(randFestivalPack2);
|
||||
|
||||
this.currentMusicPack.playSong(festivalSongName.name);
|
||||
this.SwapMusicPacks(festivalMusicPackPair.Key.Name);
|
||||
string festivalSongName = festivalMusicPackPair.Value.ElementAt(this.Random.Next(0, festivalMusicPackPair.Value.Count));
|
||||
this.CurrentMusicPack.PlaySong(festivalSongName);
|
||||
StardewSymphony.menuChangedMusic = false;
|
||||
return true;
|
||||
}
|
||||
|
@ -458,21 +370,17 @@ namespace StardewSymphonyRemastered.Framework
|
|||
else
|
||||
{
|
||||
//Try to play a generalized event song.
|
||||
var listOfEventPacks = this.getListOfApplicableMusicPacksForEvents();
|
||||
var listOfEventPacks = this.GetListOfApplicableMusicPacksForEvents();
|
||||
if (listOfEventPacks.Count > 0)
|
||||
{
|
||||
int randEventPack = this.packSelector.Next(0, listOfEventPacks.Count - 1);
|
||||
int randEventPack = this.Random.Next(0, listOfEventPacks.Count - 1);
|
||||
|
||||
var eventMusicPackPair = listOfEventPacks.ElementAt(randEventPack);
|
||||
|
||||
//used to swap the music packs and stop the last playing song.
|
||||
this.swapMusicPacks(eventMusicPackPair.Key.musicPackInformation.name);
|
||||
|
||||
int randEventPack2 = this.songSelector.Next(0, eventMusicPackPair.Value.Count);
|
||||
|
||||
var eventSongName = eventMusicPackPair.Value.ElementAt(randEventPack2);
|
||||
|
||||
this.currentMusicPack.playSong(eventSongName.name);
|
||||
this.SwapMusicPacks(eventMusicPackPair.Key.Name);
|
||||
string eventSongName = eventMusicPackPair.Value.ElementAt(this.Random.Next(0, eventMusicPackPair.Value.Count));
|
||||
this.CurrentMusicPack.PlaySong(eventSongName);
|
||||
StardewSymphony.menuChangedMusic = false;
|
||||
return true;
|
||||
}
|
||||
|
@ -494,18 +402,14 @@ namespace StardewSymphonyRemastered.Framework
|
|||
var listOfLocationPacks = this.getLocationSpecificMusic();
|
||||
if (listOfLocationPacks.Count > 0)
|
||||
{
|
||||
int randFestivalPack = this.packSelector.Next(0, listOfLocationPacks.Count - 1);
|
||||
int randFestivalPack = this.Random.Next(0, listOfLocationPacks.Count - 1);
|
||||
|
||||
var locationMusicPackPair = listOfLocationPacks.ElementAt(randFestivalPack);
|
||||
|
||||
//used to swap the music packs and stop the last playing song.
|
||||
this.swapMusicPacks(locationMusicPackPair.Key.musicPackInformation.name);
|
||||
|
||||
int randLocPack2 = this.songSelector.Next(0, locationMusicPackPair.Value.Count);
|
||||
|
||||
var songName = locationMusicPackPair.Value.ElementAt(randLocPack2);
|
||||
|
||||
this.currentMusicPack.playSong(songName.name);
|
||||
this.SwapMusicPacks(locationMusicPackPair.Key.Name);
|
||||
string songName = locationMusicPackPair.Value.ElementAt(this.Random.Next(0, locationMusicPackPair.Value.Count));
|
||||
this.CurrentMusicPack.PlaySong(songName);
|
||||
StardewSymphony.menuChangedMusic = false;
|
||||
return true;
|
||||
}
|
||||
|
@ -531,65 +435,49 @@ namespace StardewSymphonyRemastered.Framework
|
|||
{
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
{
|
||||
StardewSymphony.ModMonitor.Log("Adding a new music pack!");
|
||||
|
||||
|
||||
//StardewSymphony.ModMonitor.Log(" Location:" + musicPack.shortenedDirectory);
|
||||
StardewSymphony.ModMonitor.Log(" Name:" + musicPack.musicPackInformation.name);
|
||||
StardewSymphony.ModMonitor.Log(" Author:" + musicPack.musicPackInformation.author);
|
||||
StardewSymphony.ModMonitor.Log(" Description:" + musicPack.musicPackInformation.description);
|
||||
StardewSymphony.ModMonitor.Log(" Version Info:" + musicPack.musicPackInformation.versionInfo);
|
||||
StardewSymphony.ModMonitor.Log("Adding music pack:");
|
||||
StardewSymphony.ModMonitor.Log($" Name: {musicPack.Name}");
|
||||
StardewSymphony.ModMonitor.Log($" Author: {musicPack.Manifest.Author}");
|
||||
StardewSymphony.ModMonitor.Log($" Description: {musicPack.Manifest.Description}");
|
||||
StardewSymphony.ModMonitor.Log($" Version Info: {musicPack.Manifest.Version}");
|
||||
}
|
||||
if (displaySongs && StardewSymphony.Config.EnableDebugLog)
|
||||
{
|
||||
StardewSymphony.ModMonitor.Log(" Song List:");
|
||||
}
|
||||
|
||||
if (displaySongs)
|
||||
{
|
||||
foreach (var song in musicPack.songInformation.listOfSongsWithoutTriggers)
|
||||
{
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log(" " + song.name);
|
||||
}
|
||||
foreach (string song in musicPack.SongInformation.listOfSongsWithoutTriggers)
|
||||
StardewSymphony.ModMonitor.Log($" {song}");
|
||||
}
|
||||
}
|
||||
|
||||
this.musicPacks.Add(musicPack.musicPackInformation.name, musicPack);
|
||||
this.MusicPacks.Add(musicPack.Name, musicPack);
|
||||
}
|
||||
|
||||
/// <summary>Initializes all of the potential key triggers for playing songs.</summary>
|
||||
public void initializeSeasonalMusic()
|
||||
{
|
||||
foreach (var pack in this.musicPacks)
|
||||
pack.Value.songInformation.initializeSeasonalMusic();
|
||||
foreach (var pack in this.MusicPacks)
|
||||
pack.Value.SongInformation.initializeSeasonalMusic();
|
||||
}
|
||||
|
||||
/// <summary>Initializes all of the potential key triggers for playing songs.</summary>
|
||||
public void initializeMenuMusic()
|
||||
{
|
||||
foreach (var pack in this.musicPacks)
|
||||
pack.Value.songInformation.initializeMenuMusic();
|
||||
foreach (var pack in this.MusicPacks)
|
||||
pack.Value.SongInformation.initializeMenuMusic();
|
||||
}
|
||||
|
||||
/// <summary>Initializes all of the potential key triggers for playing songs.</summary>
|
||||
public void initializeFestivalMusic()
|
||||
{
|
||||
foreach (var pack in this.musicPacks)
|
||||
pack.Value.songInformation.initializeFestivalMusic();
|
||||
foreach (var pack in this.MusicPacks)
|
||||
pack.Value.SongInformation.initializeFestivalMusic();
|
||||
}
|
||||
|
||||
/// <summary>Initializes all of the potential key triggers for playing songs.</summary>
|
||||
public void initializeEventMusic()
|
||||
{
|
||||
foreach (var pack in this.musicPacks)
|
||||
pack.Value.songInformation.initializeEventMusic();
|
||||
}
|
||||
|
||||
/// <summary>Play a random song from a given music pack.</summary>
|
||||
public void playRandomSongFromPack(string musicPackName)
|
||||
{
|
||||
this.musicPacks.TryGetValue(musicPackName, out MusicPack musicPack);
|
||||
this.currentMusicPack?.stopSong();
|
||||
musicPack.playRandomSong();
|
||||
this.currentMusicPack = musicPack;
|
||||
foreach (var pack in this.MusicPacks)
|
||||
pack.Value.SongInformation.initializeEventMusic();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,85 +1,232 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using NAudio.Vorbis;
|
||||
using NAudio.Wave;
|
||||
using StardewModdingAPI;
|
||||
using StardewValley;
|
||||
using StardustCore.UIUtilities;
|
||||
|
||||
namespace StardewSymphonyRemastered.Framework
|
||||
{
|
||||
/// <summary>A base class that xnb and wav packs will derive commonalities from.</summary>
|
||||
/// <summary>A content pack which can provide music and sounds.</summary>
|
||||
public class MusicPack
|
||||
{
|
||||
public string directory;
|
||||
public SongSpecifics songInformation;
|
||||
public MusicPackMetaData musicPackInformation;
|
||||
/*********
|
||||
** Fields
|
||||
*********/
|
||||
/// <summary>The name of the folder which contains the saved player settings.</summary>
|
||||
private readonly string DataFolderName = "data";
|
||||
|
||||
/// <summary>The name of the folder which contains available music.</summary>
|
||||
private readonly string MusicFolderName = "music";
|
||||
|
||||
|
||||
public virtual void playSong(string name) { }
|
||||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The underlying content pack.</summary>
|
||||
public IContentPack ContentPack { get; }
|
||||
|
||||
public virtual void pauseSong() { }
|
||||
/// <summary>The songs to play when.</summary>
|
||||
public SongSpecifics SongInformation { get; }
|
||||
|
||||
public virtual void stopSong() { }
|
||||
/// <summary>The music pack icon.</summary>
|
||||
public Texture2DExtended Icon { get; }
|
||||
|
||||
public virtual void resumeSong() { }
|
||||
/// <summary>The current song name being played, if any.</summary>
|
||||
public string CurrentSongName { get; private set; }
|
||||
|
||||
public virtual void loadMusicFiles() { }
|
||||
/// <summary>The currently sound being played, if any.</summary>
|
||||
public SoundEffectInstance CurrentSound { get; private set; }
|
||||
|
||||
public virtual void swapSong(string songName) { }
|
||||
/// <summary>The manifest info.</summary>
|
||||
public IManifest Manifest => this.ContentPack.Manifest;
|
||||
|
||||
public virtual string getNameOfCurrentSong()
|
||||
/// <summary>The name of the music pack.</summary>
|
||||
public string Name => this.ContentPack.Manifest.Name;
|
||||
|
||||
/// <summary>The available sounds.</summary>
|
||||
public Dictionary<string, SoundEffectInstance> Sounds { get; } = new Dictionary<string, SoundEffectInstance>();
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="contentPack">The underlying content pack.</param>
|
||||
public MusicPack(IContentPack contentPack)
|
||||
{
|
||||
return "";
|
||||
this.ContentPack = contentPack;
|
||||
this.SongInformation = new SongSpecifics();
|
||||
this.Icon = this.LoadIcon();
|
||||
this.LoadMusicFiles();
|
||||
}
|
||||
|
||||
public virtual void setModDirectoryFromFullDirectory() { }
|
||||
|
||||
public virtual void playRandomSong() { }
|
||||
|
||||
public virtual bool isPlaying()
|
||||
/// <summary>Play a song.</summary>
|
||||
/// <param name="name">The song name to play.</param>
|
||||
public void PlaySong(string name)
|
||||
{
|
||||
return false;
|
||||
// get sound
|
||||
if (!this.Sounds.TryGetValue(name, out SoundEffectInstance sound))
|
||||
{
|
||||
StardewSymphony.ModMonitor.Log("An error occured where we can't find the song anymore. Weird. Please contact Omegasis with a SMAPI Log and describe when/how the event occured.");
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>Save functionality.</summary>
|
||||
public virtual void writeToJson()
|
||||
// play sound
|
||||
this.CurrentSongName = name;
|
||||
this.CurrentSound = sound;
|
||||
this.CurrentSound.Play();
|
||||
}
|
||||
|
||||
/// <summary>Stop the currently playing song.</summary>
|
||||
public void StopSong()
|
||||
{
|
||||
Game1.currentSong?.Stop(AudioStopOptions.Immediate);
|
||||
this.CurrentSound?.Stop(true);
|
||||
this.CurrentSongName = null;
|
||||
}
|
||||
|
||||
/// <summary>Get whether the content pack is currently playing a song.</summary>
|
||||
public bool IsPlaying()
|
||||
{
|
||||
return this.CurrentSound?.State == SoundState.Playing;
|
||||
}
|
||||
|
||||
/// <summary>Write the song conditions to disk.</summary>
|
||||
public virtual void SaveSettings()
|
||||
{
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log("Saving music for this pack:" + this.musicPackInformation.name + ". Please wait.");
|
||||
string data = Path.Combine(this.directory, "data");
|
||||
if (!Directory.Exists(data))
|
||||
Directory.CreateDirectory(data);
|
||||
foreach (var list in this.songInformation.listOfSongsWithTriggers)
|
||||
StardewSymphony.ModMonitor.Log($"Saving music for {this.Name}...");
|
||||
foreach (var list in this.SongInformation.listOfSongsWithTriggers)
|
||||
{
|
||||
if (!StardewSymphony.Config.writeAllConfigMusicOptions)
|
||||
if (!StardewSymphony.Config.WriteAllConfigMusicOptions)
|
||||
{
|
||||
if (list.Value.Count == 0)
|
||||
continue;
|
||||
}
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log("Saving music: " + list.Key + ". Please wait.");
|
||||
StardewSymphony.ModMonitor.Log($" Saving song: {list.Key}...");
|
||||
SongListNode node = new SongListNode(list.Key, list.Value);
|
||||
node.WriteToJson(Path.Combine(data, node.trigger + ".json"));
|
||||
this.ContentPack.WriteJsonFile($"{this.DataFolderName}/{node.Trigger}.json", node);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Load functionality.</summary>
|
||||
public virtual void readFromJson()
|
||||
/// <summary>Read the song conditions from disk.</summary>
|
||||
public virtual void LoadSettings()
|
||||
{
|
||||
DirectoryInfo dataFolder = new DirectoryInfo(Path.Combine(this.ContentPack.DirectoryPath, this.DataFolderName));
|
||||
if (dataFolder.Exists)
|
||||
{
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log("Loading music for this pack:" + this.musicPackInformation.name + ". Please wait as this will take quite some time.");
|
||||
string data = Path.Combine(this.directory, "data");
|
||||
if (!Directory.Exists(data))
|
||||
Directory.CreateDirectory(data);
|
||||
string[] files = Directory.GetFiles(data);
|
||||
foreach (string file in files)
|
||||
StardewSymphony.ModMonitor.Log($"Loading music for {this.Name}. This may take quite some time.");
|
||||
|
||||
foreach (FileInfo file in dataFolder.GetFiles())
|
||||
{
|
||||
SongListNode node = SongListNode.ReadFromJson(Path.Combine(data, file));
|
||||
//var pair = this.songInformation.getSongList(node.trigger + ".json");
|
||||
foreach (var v in node.songList)
|
||||
SongListNode node = this.ContentPack.ReadJsonFile<SongListNode>($"{this.DataFolderName}/{file.Name}");
|
||||
foreach (string song in node.SongList)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.songInformation.addSongToTriggerList(node.trigger, v.name);
|
||||
this.SongInformation.addSongToTriggerList(node.Trigger, song);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
/// <summary>Load the icon from the content pack.</summary>
|
||||
private Texture2DExtended LoadIcon()
|
||||
{
|
||||
try
|
||||
{
|
||||
Texture2D texture = this.ContentPack.LoadAsset<Texture2D>("icon.png");
|
||||
return new Texture2DExtended(texture);
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log(err.ToString());
|
||||
return 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);
|
||||
}
|
||||
|
||||
// log loading time
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log($"Time to load WAV music pack {this.Name}: {startTime.Subtract(DateTime.Now)}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using StardustCore.UIUtilities;
|
||||
|
||||
namespace StardewSymphonyRemastered.Framework
|
||||
{
|
||||
/// <summary>Holds information regarding information relating to music packs such as name, description, author, and version.</summary>
|
||||
public class MusicPackMetaData
|
||||
{
|
||||
public string name;
|
||||
public string author;
|
||||
public string description;
|
||||
public string versionInfo;
|
||||
public string pathToMusicPackIcon;
|
||||
private Texture2DExtended Icon;
|
||||
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="name">The name to be displayed for the music pack.</param>
|
||||
/// <param name="author">The author who compiled ths music pack.</param>
|
||||
/// <param name="description">The description of</param>
|
||||
public MusicPackMetaData(string name, string author, string description, string versionInfo, string pathToMusicPackIcon)
|
||||
{
|
||||
this.name = name;
|
||||
this.author = author;
|
||||
this.description = description;
|
||||
this.versionInfo = versionInfo;
|
||||
this.pathToMusicPackIcon = pathToMusicPackIcon;
|
||||
try
|
||||
{
|
||||
this.Icon = new Texture2DExtended(StardewSymphony.ModHelper, StardewSymphony.Manifest, this.pathToMusicPackIcon + ".png");
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
this.Icon = null;
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log(err.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Construct an instance.</summary>
|
||||
public MusicPackMetaData() { }
|
||||
|
||||
/// <summary>Loads the music pack information from a json file.</summary>
|
||||
public static MusicPackMetaData readFromJson(string path)
|
||||
{
|
||||
string json = Path.Combine(path, "MusicPackInformation.json");
|
||||
var meta = StardewSymphony.ModHelper.ReadJsonFile<MusicPackMetaData>(json);
|
||||
|
||||
string[] pathParse = path.Split(new string[] { StardewSymphony.ModHelper.DirectoryPath }, StringSplitOptions.None);
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
meta.Icon = new Texture2DExtended(StardewSymphony.ModHelper, StardewSymphony.Manifest, Path.Combine(pathParse[1].Remove(0, 1), meta.pathToMusicPackIcon + ".png"));
|
||||
}
|
||||
catch
|
||||
{
|
||||
meta.Icon = new Texture2DExtended(StardewSymphony.ModHelper, StardewSymphony.Manifest, Path.Combine(pathParse[1].Remove(0, 1), meta.pathToMusicPackIcon));
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log(err.ToString());
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
|
||||
/// <summary>Writes the music pack information to a json file.</summary>
|
||||
public void writeToJson(string path)
|
||||
{
|
||||
StardewSymphony.ModHelper.WriteJsonFile<MusicPackMetaData>(path, this);
|
||||
}
|
||||
|
||||
public Texture2DExtended getTexture()
|
||||
{
|
||||
return this.Icon;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
using System.IO;
|
||||
|
||||
namespace StardewSymphonyRemastered.Framework
|
||||
{
|
||||
/// <summary>The class to be used to manage individual songs.</summary>
|
||||
public class Song
|
||||
{
|
||||
/// <summary>The path to the song. In the case of XACT songs this points to the .xwb file. For WAV files this points directly to the WAV file itself.</summary>
|
||||
private readonly string pathToSong;
|
||||
|
||||
/// <summary>The name of the song itself.</summary>
|
||||
public string name;
|
||||
|
||||
/// <summary>The relative path to the song.</summary>
|
||||
private readonly string relativePath;
|
||||
|
||||
/// <summary>Blank Constructor;</summary>
|
||||
public Song() { }
|
||||
|
||||
/// <summary>Constructor to be used for WAV files.</summary>
|
||||
public Song(string PathToSong)
|
||||
{
|
||||
this.pathToSong = PathToSong;
|
||||
this.name = this.getNameFromPath(this.pathToSong);
|
||||
this.relativePath = this.getRelativePathFromFullPath();
|
||||
}
|
||||
|
||||
/// <summary>Constructor to be used for XACT music packs.</summary>
|
||||
public Song(string PathToSong, string Name)
|
||||
{
|
||||
this.pathToSong = PathToSong;
|
||||
this.name = Name;
|
||||
this.relativePath = this.getRelativePathFromFullPath();
|
||||
}
|
||||
|
||||
/// <summary>Parse the name of the file from the path provided.</summary>
|
||||
public string getNameFromPath(string path)
|
||||
{
|
||||
return Path.GetFileNameWithoutExtension(path);
|
||||
}
|
||||
|
||||
/// <summary>Get the relative path to this song from the full path on disk provided.</summary>
|
||||
public string getRelativePathFromFullPath()
|
||||
{
|
||||
string[] spliter = this.pathToSong.Split(Path.DirectorySeparatorChar);
|
||||
string relative = "";
|
||||
int index = 0;
|
||||
foreach (string str in spliter) //iterate across all of the strings until Content is found.
|
||||
{
|
||||
if (str == "Content")
|
||||
{
|
||||
//Once content is found add it to the relative string and append a newline character.
|
||||
for (int i = index; i < spliter.Length; i++)
|
||||
{
|
||||
relative += spliter[i];
|
||||
if (i != spliter.Length - 1)
|
||||
relative += Path.DirectorySeparatorChar;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return relative; //Return the relative path string
|
||||
}
|
||||
|
||||
/// <summary>Read the info from a .json file.</summary>
|
||||
public static Song ReadFromJson(string path)
|
||||
{
|
||||
return StardewSymphony.ModHelper.ReadJsonFile<Song>(path);
|
||||
}
|
||||
|
||||
/// <summary>Write the information of the instance to a .json file.</summary>
|
||||
/// <param name="path">The path to which the json file is written to.</param>
|
||||
public void writeToJson(string path)
|
||||
{
|
||||
StardewSymphony.ModHelper.WriteJsonFile<Song>(path, this);
|
||||
}
|
||||
|
||||
public string getRelativePath()
|
||||
{
|
||||
return this.relativePath;
|
||||
}
|
||||
|
||||
public string getPathToSong()
|
||||
{
|
||||
return this.pathToSong;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,38 +1,31 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace StardewSymphonyRemastered.Framework
|
||||
{
|
||||
/// <summary>A class that keeps track of the trigger and the list of songs associated with that trigger.</summary>
|
||||
class SongListNode
|
||||
internal class SongListNode
|
||||
{
|
||||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The trigger name for the list of songs.</summary>
|
||||
public string trigger;
|
||||
public string Trigger { get; }
|
||||
|
||||
/// <summary>The list of songs associated with a trigger.</summary>
|
||||
public List<Song> songList;
|
||||
public string[] SongList { get; }
|
||||
|
||||
/// <summary>Empty constructor.</summary>
|
||||
public SongListNode() { }
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="Trigger"></param>
|
||||
/// <param name="SongList"></param>
|
||||
public SongListNode(string Trigger, List<Song> SongList)
|
||||
/// <param name="trigger">The trigger name for the list of songs.</param>
|
||||
/// <param name="songList">The list of songs associated with a trigger.</param>
|
||||
public SongListNode(string trigger, IEnumerable<string> songList)
|
||||
{
|
||||
this.trigger = Trigger;
|
||||
this.songList = SongList;
|
||||
}
|
||||
|
||||
/// <summary>Save functionality.</summary>
|
||||
public void WriteToJson(string path)
|
||||
{
|
||||
StardewSymphony.ModHelper.WriteJsonFile(path, this);
|
||||
}
|
||||
|
||||
/// <summary>Load functionality.</summary>
|
||||
public static SongListNode ReadFromJson(string path)
|
||||
{
|
||||
return StardewSymphony.ModHelper.ReadJsonFile<SongListNode>(path);
|
||||
this.Trigger = trigger;
|
||||
this.SongList = songList.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using StardewValley;
|
||||
using static System.String;
|
||||
|
||||
|
@ -8,12 +9,12 @@ namespace StardewSymphonyRemastered.Framework
|
|||
/// <summary>Stores information about what songs play when.</summary>
|
||||
public class SongSpecifics
|
||||
{
|
||||
public SortedDictionary<string, List<Song>> listOfSongsWithTriggers; //triggerName, <songs>. Seasonal music
|
||||
public SortedDictionary<string, List<string>> listOfSongsWithTriggers; //triggerName, <songs>. Seasonal music
|
||||
|
||||
public List<Song> listOfSongsWithoutTriggers;
|
||||
public List<string> listOfSongsWithoutTriggers;
|
||||
|
||||
public List<Song> festivalSongs;
|
||||
public List<Song> eventSongs;
|
||||
public List<string> festivalSongs;
|
||||
public List<string> eventSongs;
|
||||
|
||||
public static List<string> locations = new List<string>();
|
||||
public static List<string> festivals = new List<string>();
|
||||
|
@ -90,10 +91,10 @@ namespace StardewSymphonyRemastered.Framework
|
|||
};
|
||||
|
||||
|
||||
this.listOfSongsWithTriggers = new SortedDictionary<string, List<Song>>();
|
||||
this.listOfSongsWithoutTriggers = new List<Song>();
|
||||
this.eventSongs = new List<Song>();
|
||||
this.festivalSongs = new List<Song>();
|
||||
this.listOfSongsWithTriggers = new SortedDictionary<string, List<string>>();
|
||||
this.listOfSongsWithoutTriggers = new List<string>();
|
||||
this.eventSongs = new List<string>();
|
||||
this.festivalSongs = new List<string>();
|
||||
|
||||
}
|
||||
|
||||
|
@ -107,7 +108,7 @@ namespace StardewSymphonyRemastered.Framework
|
|||
/// <summary>Sum up some conditionals to parse the correct string key to access the songs list.</summary>
|
||||
public static string getCurrentConditionalString(bool getJustLocation = false)
|
||||
{
|
||||
string key = "";
|
||||
string key;
|
||||
//Event id's are the number found before the : for the event in Content/events/<location>.yaml file where location is the name of the stardew valley location.
|
||||
|
||||
if (!getJustLocation)
|
||||
|
@ -117,7 +118,7 @@ namespace StardewSymphonyRemastered.Framework
|
|||
//Get the event id an hijack it with some different music
|
||||
//String key="Event_EventName";
|
||||
|
||||
var reflected = StardewSymphony.ModHelper.Reflection.GetField<int>(Game1.CurrentEvent, "id", true);
|
||||
var reflected = StardewSymphony.ModHelper.Reflection.GetField<int>(Game1.CurrentEvent, "id");
|
||||
|
||||
int id = reflected.GetValue();
|
||||
key = id.ToString(); //get the event id. Really really messy.
|
||||
|
@ -151,7 +152,7 @@ namespace StardewSymphonyRemastered.Framework
|
|||
{
|
||||
key = getSeasonNameString() + seperator + getWeatherString() + seperator + getTimeOfDayString(true) + seperator + getLocationString() + seperator + getDayOfWeekString();
|
||||
|
||||
if (StardewSymphony.musicManager.getListOfApplicableMusicPacks(key).Count == 0)
|
||||
if (StardewSymphony.musicManager.GetApplicableMusicPacks(key).Count == 0)
|
||||
{
|
||||
key = getSeasonNameString() + seperator + getWeatherString() + seperator + getTimeOfDayString(false) + seperator + getLocationString() + seperator + getDayOfWeekString();
|
||||
}
|
||||
|
@ -221,13 +222,6 @@ namespace StardewSymphonyRemastered.Framework
|
|||
festivals.Add(name);
|
||||
}
|
||||
|
||||
// TODO: Get a list of all of the vanilla events in the game. But how to determine what event is playing is the question.
|
||||
public static void initializeEventsList()
|
||||
{
|
||||
//Do some logic here
|
||||
//addEvent(12345.ToString());
|
||||
}
|
||||
|
||||
/// <summary>Custom way to add in event to hijack music.</summary>
|
||||
public static void addEvent(string id)
|
||||
{
|
||||
|
@ -340,10 +334,6 @@ namespace StardewSymphonyRemastered.Framework
|
|||
}
|
||||
}
|
||||
|
||||
public static string getCurrentMenuString()
|
||||
{
|
||||
return Game1.activeClickableMenu == null ? "" : Game1.activeClickableMenu.GetType().ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
@ -352,13 +342,6 @@ namespace StardewSymphonyRemastered.Framework
|
|||
|
||||
|
||||
#region
|
||||
/// <summary>Adds the song's reference to a music pack.</summary>
|
||||
/// <param name="song">The FULL namespace of the menu. Example is StardewValley.Menus.TitleMenu</param>
|
||||
public void addSongToMusicPack(Song song)
|
||||
{
|
||||
this.listOfSongsWithoutTriggers.Add(song);
|
||||
}
|
||||
|
||||
/// <summary>Initialize a basic list of menus supported.</summary>
|
||||
public static void initializeMenuList()
|
||||
{
|
||||
|
@ -390,20 +373,6 @@ namespace StardewSymphonyRemastered.Framework
|
|||
|
||||
}
|
||||
|
||||
/// <summary>Add a menu to stardew symphony so that it may have unique music.</summary>
|
||||
public static void addMenu(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
name = name.Replace('.', seperator); //Sanitize the name passed in to use my parsing conventions.
|
||||
menus.Add(name);
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
err.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Add amenu to stardew symphony so that it may have unique music.</summary>
|
||||
/// <param name="menuType">The type of menu to add in. Typically this is typeof(MyMenuClass)</param>
|
||||
public static void addMenu(Type menuType)
|
||||
|
@ -423,7 +392,7 @@ namespace StardewSymphonyRemastered.Framework
|
|||
{
|
||||
try
|
||||
{
|
||||
this.listOfSongsWithTriggers.Add(v, new List<Song>());
|
||||
this.listOfSongsWithTriggers.Add(v, new List<string>());
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
@ -435,7 +404,7 @@ namespace StardewSymphonyRemastered.Framework
|
|||
{
|
||||
try
|
||||
{
|
||||
this.listOfSongsWithTriggers.Add(v, new List<Song>());
|
||||
this.listOfSongsWithTriggers.Add(v, new List<string>());
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
@ -447,40 +416,33 @@ namespace StardewSymphonyRemastered.Framework
|
|||
{
|
||||
try
|
||||
{
|
||||
this.listOfSongsWithTriggers.Add(v, new List<Song>());
|
||||
this.listOfSongsWithTriggers.Add(v, new List<string>());
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Checks if the song exists at all in this music pack.</summary>
|
||||
public bool isSongInList(string songName)
|
||||
{
|
||||
Song song = this.getSongFromList(this.listOfSongsWithoutTriggers, songName);
|
||||
return song != null && this.listOfSongsWithoutTriggers.Contains(song);
|
||||
}
|
||||
|
||||
/// <summary>A pretty big function to add in all of the specific songs that play at certain locations_seasons_weather_dayOfWeek_times. </summary>
|
||||
public void initializeSeasonalMusic()
|
||||
{
|
||||
foreach (string loc in locations)
|
||||
this.listOfSongsWithTriggers.Add(loc, new List<Song>());
|
||||
this.listOfSongsWithTriggers.Add(loc, new List<string>());
|
||||
|
||||
foreach (string season in this.seasons)
|
||||
{
|
||||
this.listOfSongsWithTriggers.Add(season, new List<Song>());
|
||||
this.listOfSongsWithTriggers.Add(season, new List<string>());
|
||||
foreach (string weather in this.weather)
|
||||
{
|
||||
this.listOfSongsWithTriggers.Add(season + seperator + weather, new List<Song>());
|
||||
this.listOfSongsWithTriggers.Add(season + seperator + weather, new List<string>());
|
||||
foreach (string time in this.timesOfDay)
|
||||
{
|
||||
this.listOfSongsWithTriggers.Add(season + seperator + weather + seperator + time, new List<Song>());
|
||||
this.listOfSongsWithTriggers.Add(season + seperator + weather + seperator + time, new List<string>());
|
||||
foreach (string loc in locations)
|
||||
{
|
||||
this.listOfSongsWithTriggers.Add(season + seperator + weather + seperator + time + seperator + loc, new List<Song>());
|
||||
this.listOfSongsWithTriggers.Add(season + seperator + weather + seperator + time + seperator + loc, new List<string>());
|
||||
foreach (string day in this.daysOfWeek)
|
||||
{
|
||||
this.listOfSongsWithTriggers.Add(season + seperator + weather + seperator + time + seperator + loc + seperator + day, new List<Song>());
|
||||
this.listOfSongsWithTriggers.Add(season + seperator + weather + seperator + time + seperator + loc + seperator + day, new List<string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -489,38 +451,32 @@ namespace StardewSymphonyRemastered.Framework
|
|||
}
|
||||
|
||||
/// <summary>Used to access the master list of songs this music pack contains.</summary>
|
||||
public KeyValuePair<string, List<Song>> getSongList(string key)
|
||||
public KeyValuePair<string, List<string>> getSongList(string key)
|
||||
{
|
||||
if (!this.listOfSongsWithTriggers.ContainsKey(key))
|
||||
return new KeyValuePair<string, List<Song>>("", null);
|
||||
return new KeyValuePair<string, List<string>>("", null);
|
||||
|
||||
//This is just the plain song name with no extra info.
|
||||
foreach (KeyValuePair<string, List<Song>> pair in this.listOfSongsWithTriggers)
|
||||
foreach (KeyValuePair<string, List<string>> pair in this.listOfSongsWithTriggers)
|
||||
{
|
||||
//StardewSymphony.ModMonitor.Log(pair.Key);
|
||||
if (pair.Key == key)
|
||||
return pair;
|
||||
}
|
||||
|
||||
return new KeyValuePair<string, List<Song>>("", null);
|
||||
return new KeyValuePair<string, List<string>>("", null);
|
||||
}
|
||||
|
||||
public List<Song> getFestivalMusic()
|
||||
public List<string> getFestivalMusic()
|
||||
{
|
||||
return this.festivalSongs;
|
||||
}
|
||||
|
||||
public List<Song> getEventMusic()
|
||||
public List<string> getEventMusic()
|
||||
{
|
||||
return this.eventSongs;
|
||||
}
|
||||
|
||||
public List<Song> getMenuMusic()
|
||||
{
|
||||
return null;
|
||||
//return this.menuSongs();
|
||||
}
|
||||
|
||||
/// <summary>Add a song name to a specific list of songs to play that will play under certain conditions.</summary>
|
||||
public void addSongToTriggerList(string songListKey, string songName)
|
||||
{
|
||||
|
@ -534,7 +490,7 @@ namespace StardewSymphonyRemastered.Framework
|
|||
StardewSymphony.ModMonitor.Log("For some reason you are trying to add a song to a list that is null. The name of the song list is " + songListKey);
|
||||
return;
|
||||
}
|
||||
var song = this.getSongFromList(this.listOfSongsWithoutTriggers, songName); //Get the song from the master song pool
|
||||
string song = this.getSongFromList(this.listOfSongsWithoutTriggers, songName); //Get the song from the master song pool
|
||||
if (song == null)
|
||||
{
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
|
@ -546,7 +502,7 @@ namespace StardewSymphonyRemastered.Framework
|
|||
|
||||
public void addSongToFestivalList(string songName)
|
||||
{
|
||||
var song = this.getSongFromList(this.listOfSongsWithoutTriggers, songName); //Get the song from the master song pool
|
||||
string song = this.getSongFromList(this.listOfSongsWithoutTriggers, songName); //Get the song from the master song pool
|
||||
if (song == null)
|
||||
{
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
|
@ -560,7 +516,7 @@ namespace StardewSymphonyRemastered.Framework
|
|||
{
|
||||
var songKeyPair = this.eventSongs;
|
||||
|
||||
var song = this.getSongFromList(this.listOfSongsWithoutTriggers, songName); //Get the song from the master song pool
|
||||
string song = this.getSongFromList(this.listOfSongsWithoutTriggers, songName); //Get the song from the master song pool
|
||||
if (song == null)
|
||||
{
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
|
@ -574,35 +530,28 @@ namespace StardewSymphonyRemastered.Framework
|
|||
public void removeSongFromTriggerList(string songListKey, string songName)
|
||||
{
|
||||
var songKeyPair = this.getSongList(songListKey);
|
||||
var song = this.getSongFromList(songKeyPair.Value, songName);
|
||||
string song = this.getSongFromList(songKeyPair.Value, songName);
|
||||
songKeyPair.Value.Remove(song);
|
||||
}
|
||||
|
||||
/// <summary>Remove a song from the event list.</summary>
|
||||
public void removeSongFromEventList(string songName)
|
||||
{
|
||||
var song = this.getSongFromList(this.eventSongs, songName);
|
||||
string song = this.getSongFromList(this.eventSongs, songName);
|
||||
this.eventSongs.Remove(song);
|
||||
}
|
||||
|
||||
/// <summary>Remove a song from the festival list.</summary>
|
||||
public void removeSongFromFestivalList(string songName)
|
||||
{
|
||||
var song = this.getSongFromList(this.festivalSongs, songName);
|
||||
string song = this.getSongFromList(this.festivalSongs, songName);
|
||||
this.festivalSongs.Remove(song);
|
||||
}
|
||||
|
||||
/// <summary>Get the Song instance that is referenced with the song's name.</summary>
|
||||
public Song getSongFromList(List<Song> songList, string songName)
|
||||
public string getSongFromList(List<string> songList, string songName)
|
||||
{
|
||||
//StardewSymphony.ModMonitor.Log("Get the song: " + songName);
|
||||
foreach (var song in songList)
|
||||
{
|
||||
//StardewSymphony.ModMonitor.Log("Looking at song: " + song.name);
|
||||
if (song.name == songName)
|
||||
return song;
|
||||
}
|
||||
return null;
|
||||
return songList.FirstOrDefault(p => p == songName);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -1,250 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using NAudio.Vorbis;
|
||||
using NAudio.Wave;
|
||||
using StardewValley;
|
||||
|
||||
namespace StardewSymphonyRemastered.Framework
|
||||
{
|
||||
/// <summary>TODO: Make this class</summary>
|
||||
public class WavMusicPack : MusicPack
|
||||
{
|
||||
/// <summary>The refererence to the information for the current song.</summary>
|
||||
public Song currentSong;
|
||||
|
||||
/// <summary>The directory where all of the songs are stored.</summary>
|
||||
public string songsDirectory;
|
||||
|
||||
/// <summary>The currently playing sound.</summary>
|
||||
public SoundEffectInstance sound;
|
||||
|
||||
bool loop;
|
||||
|
||||
/// <summary>The name of the music pack/</summary>
|
||||
public string Name => this.musicPackInformation.name;
|
||||
|
||||
public Dictionary<string, SoundEffectInstance> sounds;
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="directoryToMusicPack"></param>
|
||||
public WavMusicPack(string directoryToMusicPack, bool loop = false)
|
||||
{
|
||||
this.directory = directoryToMusicPack;
|
||||
this.setModDirectoryFromFullDirectory();
|
||||
this.songsDirectory = Path.Combine(this.directory, "Songs");
|
||||
this.songInformation = new SongSpecifics();
|
||||
this.musicPackInformation = MusicPackMetaData.readFromJson(directoryToMusicPack);
|
||||
this.loop = loop;
|
||||
this.sounds = new Dictionary<string, SoundEffectInstance>();
|
||||
/*
|
||||
if (this.musicPackInformation == null)
|
||||
{
|
||||
//StardewSymphony.ModMonitor.Log("Error: MusicPackInformation.json not found at: " + directoryToMusicPack + ". Blank information will be put in place.", StardewModdingAPI.LogLevel.Warn);
|
||||
//this.musicPackInformation = new MusicPackMetaData("???", "???", "", "0.0.0","");
|
||||
}
|
||||
*/
|
||||
//StardewSymphony.ModMonitor.Log(this.musicPackInformation.name.ToString());
|
||||
this.loadMusicFiles();
|
||||
}
|
||||
|
||||
/// <summary>A shortened directory name for display purposes.</summary>
|
||||
public override void setModDirectoryFromFullDirectory()
|
||||
{
|
||||
string[] spliter = this.directory.Split(Path.DirectorySeparatorChar);
|
||||
string directoryLocation = "";
|
||||
for (int i = spliter.Length - 6; i < spliter.Length; i++)
|
||||
{
|
||||
directoryLocation += spliter[i];
|
||||
|
||||
if (i != spliter.Length - 1)
|
||||
directoryLocation += Path.DirectorySeparatorChar;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>Load a wav file into the stream to be played.</summary>
|
||||
public void LoadWavFromFileToStream(string file)
|
||||
{
|
||||
// Create a new SpriteBatch, which can be used to draw textures.
|
||||
|
||||
System.IO.Stream waveFileStream = File.OpenRead(file); //TitleContainer.OpenStream(file);
|
||||
this.effect = SoundEffect.FromStream(waveFileStream);
|
||||
this.sound=this.effect.CreateInstance();
|
||||
this.currentSong = new Song(file);
|
||||
waveFileStream.Dispose();
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>Returns the name of the currently playing song.</summary>
|
||||
public override string getNameOfCurrentSong()
|
||||
{
|
||||
return this.currentSong?.name ?? "";
|
||||
}
|
||||
|
||||
/// <summary>Load in the music files from the pack's respective Directory/Songs folder. Typically Content/Music/Wav/FolderName/Songs</summary>
|
||||
public override void loadMusicFiles()
|
||||
{
|
||||
List<string> wavFiles = Directory.GetFiles(this.songsDirectory, "*.wav").ToList();
|
||||
wavFiles.AddRange(Directory.GetFiles(this.songsDirectory, "*.mp3"));
|
||||
wavFiles.AddRange(Directory.GetFiles(this.songsDirectory, "*.ogg"));
|
||||
|
||||
DateTime span = DateTime.Now;
|
||||
foreach (string wav in wavFiles)
|
||||
{
|
||||
SoundEffect eff = null;
|
||||
|
||||
Stream waveFileStream = File.OpenRead(wav); //TitleContainer.OpenStream(file);
|
||||
|
||||
|
||||
if (wav.Contains(".wav"))
|
||||
{
|
||||
eff = SoundEffect.FromStream(waveFileStream);
|
||||
waveFileStream.Close();
|
||||
}
|
||||
else if (wav.Contains(".mp3"))
|
||||
{
|
||||
using (Mp3FileReader reader = new Mp3FileReader(waveFileStream))
|
||||
{
|
||||
using (WaveStream pcmMP3Stream = WaveFormatConversionStream.CreatePcmStream(reader))
|
||||
{
|
||||
StardewSymphony.DebugLog("Converting: " + this.songsDirectory + Path.GetFileName(wav));
|
||||
WaveFileWriter.CreateWaveFile(Path.Combine(this.songsDirectory, (Path.GetFileNameWithoutExtension(wav) + ".wav")), pcmMP3Stream);
|
||||
|
||||
waveFileStream = File.OpenRead(Path.Combine(this.songsDirectory, (Path.GetFileNameWithoutExtension(wav) + ".wav"))); //TitleContainer.OpenStream(file);
|
||||
eff = SoundEffect.FromStream(waveFileStream);
|
||||
|
||||
waveFileStream.Close();
|
||||
File.Delete(Path.Combine(this.songsDirectory, (Path.GetFileNameWithoutExtension(wav) + ".wav")));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (wav.Contains(".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(wav))
|
||||
{
|
||||
|
||||
StardewSymphony.DebugLog("Converting: " + this.songsDirectory+Path.GetFileName(wav));
|
||||
WaveFileWriter.CreateWaveFile(Path.Combine(this.songsDirectory, (Path.GetFileNameWithoutExtension(wav) + ".wav")), vorbisStream.ToWaveProvider16());
|
||||
|
||||
//WaveFileReader reader = new WaveFileReader(Path.Combine(this.songsDirectory, (Path.GetFileNameWithoutExtension(wav) + ".wav")));
|
||||
|
||||
waveFileStream = File.OpenRead(Path.Combine(this.songsDirectory, (Path.GetFileNameWithoutExtension(wav) + ".wav"))); //TitleContainer.OpenStream(file);
|
||||
eff = SoundEffect.FromStream(waveFileStream);
|
||||
|
||||
waveFileStream.Close();
|
||||
|
||||
File.Delete(Path.Combine(this.songsDirectory, (Path.GetFileNameWithoutExtension(wav) + ".wav")));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//SoundEffect eff = new SoundEffect(wavData, 48000 , AudioChannels.Mono);
|
||||
|
||||
if (eff == null)
|
||||
continue;
|
||||
SoundEffectInstance instance = eff.CreateInstance();
|
||||
|
||||
|
||||
string name = Path.GetFileNameWithoutExtension(wav);
|
||||
if (this.sounds.ContainsKey(name))
|
||||
continue;
|
||||
this.sounds.Add(name, instance);
|
||||
|
||||
//waveFileStream.Dispose();
|
||||
Song song = new Song(wav);
|
||||
this.songInformation.listOfSongsWithoutTriggers.Add(song);
|
||||
//listOfSongs.Add(song);
|
||||
}
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log("Time to load WAV music pack: " + this.musicPackInformation.name + span.Subtract(DateTime.Now).ToString());
|
||||
}
|
||||
|
||||
/// <summary>Used to pause the current song.</summary>
|
||||
public override void pauseSong()
|
||||
{
|
||||
this.sound?.Pause();
|
||||
}
|
||||
|
||||
/// <summary>Used to play a song.</summary>
|
||||
public override void playSong(string name)
|
||||
{
|
||||
//string pathToSong = this.getSongPathFromName(name);
|
||||
|
||||
bool exists = this.sounds.TryGetValue(name, out this.sound);
|
||||
|
||||
if (exists)
|
||||
{
|
||||
this.currentSong = new Song(name);
|
||||
this.sound.Play();
|
||||
}
|
||||
else
|
||||
{
|
||||
StardewSymphony.ModMonitor.Log("An error occured where we can't find the song anymore. Weird. Please contact Omegasis with a SMAPI Log and describe when/how the event occured.");
|
||||
}
|
||||
}
|
||||
|
||||
public override void playRandomSong()
|
||||
{
|
||||
Random r = Game1.random;
|
||||
int value = r.Next(0, this.songInformation.listOfSongsWithoutTriggers.Count);
|
||||
Song s = this.songInformation.listOfSongsWithoutTriggers.ElementAt(value);
|
||||
this.swapSong(s.name);
|
||||
}
|
||||
|
||||
/// <summary>Used to resume the currently playing song.</summary>
|
||||
public override void resumeSong()
|
||||
{
|
||||
this.sound?.Resume();
|
||||
}
|
||||
|
||||
/// <summary>Used to stop the currently playing song.</summary>
|
||||
public override void stopSong()
|
||||
{
|
||||
Game1.currentSong?.Stop(AudioStopOptions.Immediate);
|
||||
if (this.currentSong == null)
|
||||
return;
|
||||
|
||||
this.sound?.Stop(true);
|
||||
this.currentSong = null;
|
||||
}
|
||||
|
||||
/// <summary>Used to change from one playing song to another;</summary>
|
||||
public override void swapSong(string songName)
|
||||
{
|
||||
this.stopSong();
|
||||
this.playSong(songName);
|
||||
}
|
||||
|
||||
/// <summary>Get the son's name from the path.</summary>
|
||||
public string getSongNameFromPath(string path)
|
||||
{
|
||||
foreach (var song in this.songInformation.listOfSongsWithoutTriggers)
|
||||
{
|
||||
if (song.getPathToSong() == path)
|
||||
return song.name;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>Gets the song's path that shares the same name.</summary>
|
||||
public string getSongPathFromName(string name)
|
||||
{
|
||||
foreach (var song in this.songInformation.listOfSongsWithoutTriggers)
|
||||
{
|
||||
if (song.name == name)
|
||||
return song.getPathToSong();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public override bool isPlaying()
|
||||
{
|
||||
return this.sound?.State == SoundState.Playing;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using StardewValley;
|
||||
|
||||
namespace StardewSymphonyRemastered.Framework
|
||||
{
|
||||
/// <summary>TODO: Make this work and add in overrided functions.</summary>
|
||||
public class XACTMusicPack : MusicPack
|
||||
{
|
||||
public WaveBank WaveBank;
|
||||
public ISoundBank SoundBank;
|
||||
|
||||
public Cue currentCue;
|
||||
|
||||
public string WaveBankPath;
|
||||
public string SoundBankPath;
|
||||
|
||||
/// <summary>Construct an instance.</summary>
|
||||
public XACTMusicPack(string directoryToXwb, string pathToWaveBank, string pathToSoundBank)
|
||||
{
|
||||
this.directory = directoryToXwb;
|
||||
this.WaveBankPath = pathToWaveBank;
|
||||
this.SoundBankPath = pathToSoundBank;
|
||||
this.setModDirectoryFromFullDirectory();
|
||||
this.songInformation = new SongSpecifics();
|
||||
this.currentCue = null;
|
||||
this.musicPackInformation = MusicPackMetaData.readFromJson(directoryToXwb);
|
||||
if (this.musicPackInformation == null)
|
||||
{
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log("Error: MusicPackInformation.json not found at: " + directoryToXwb + ". Blank information will be put in place.", StardewModdingAPI.LogLevel.Warn);
|
||||
this.musicPackInformation = new MusicPackMetaData("???", "???", "", "0.0.0", "");
|
||||
}
|
||||
|
||||
this.WaveBank = new WaveBank(Game1.audioEngine, this.WaveBankPath);
|
||||
this.SoundBank = new SoundBankWrapper(new SoundBank(Game1.audioEngine, this.SoundBankPath));
|
||||
this.loadMusicFiles();
|
||||
}
|
||||
|
||||
/// <summary>Load all of the generic music file names into the music pack's information.</summary>
|
||||
public override void loadMusicFiles()
|
||||
{
|
||||
var listOfSongStrings = MusicHexProcessor.ProcessSongNamesFromHex(this, StardewSymphony.Reset, this.SoundBankPath);
|
||||
|
||||
List<Song> listofSongs = new List<Song>();
|
||||
foreach (string songname in listOfSongStrings)
|
||||
{
|
||||
Song song = new Song(this.WaveBankPath, songname);
|
||||
listofSongs.Add(song);
|
||||
}
|
||||
|
||||
this.songInformation.listOfSongsWithoutTriggers = listofSongs;
|
||||
}
|
||||
|
||||
public override void playRandomSong()
|
||||
{
|
||||
Random r = new Random();
|
||||
int value = r.Next(0, this.songInformation.listOfSongsWithoutTriggers.Count);
|
||||
Song s = this.songInformation.listOfSongsWithoutTriggers.ElementAt(value);
|
||||
this.swapSong(s.name);
|
||||
}
|
||||
|
||||
/// <summary>Get the cue from the list of songs.</summary>
|
||||
/// <param name="name">The name of the song to get.</param>
|
||||
private Cue getCue(string name)
|
||||
{
|
||||
if (!this.songInformation.isSongInList(name))
|
||||
{
|
||||
if (StardewSymphony.Config.EnableDebugLog)
|
||||
StardewSymphony.ModMonitor.Log("Error! The song " + name + " could not be found in music pack " + this.musicPackInformation.name + ". Please ensure that this song is part of this music pack located at: " + this.WaveBankPath + " or contact the music pack author: " + this.musicPackInformation.author, StardewModdingAPI.LogLevel.Error);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.SoundBank.GetCue(name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public override void pauseSong()
|
||||
{
|
||||
if (this.currentCue != null)
|
||||
{
|
||||
Game1.waveBank = this.WaveBank;
|
||||
Game1.soundBank = this.SoundBank;
|
||||
this.currentCue.Pause();
|
||||
StardewSymphony.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Resume playing the current set cue.</summary>
|
||||
public override void resumeSong()
|
||||
{
|
||||
if (this.currentCue != null)
|
||||
{
|
||||
Game1.waveBank = this.WaveBank;
|
||||
Game1.soundBank = this.SoundBank;
|
||||
this.currentCue.Resume();
|
||||
StardewSymphony.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Stops the currently playing song and nulls the current song.</summary>
|
||||
public override void stopSong()
|
||||
{
|
||||
Game1.currentSong?.Stop(AudioStopOptions.Immediate);
|
||||
if (this.currentCue != null)
|
||||
{
|
||||
Game1.waveBank = this.WaveBank;
|
||||
Game1.soundBank = this.SoundBank;
|
||||
this.currentCue.Stop(AudioStopOptions.Immediate);
|
||||
StardewSymphony.Reset();
|
||||
this.currentCue = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Stops the currently playing song and starts playing a new song.</summary>
|
||||
/// <param name="newSongName">The name of the new song to play.</param>
|
||||
public override void swapSong(string newSongName)
|
||||
{
|
||||
this.stopSong();
|
||||
this.playSong(newSongName);
|
||||
}
|
||||
|
||||
/// <summary>Returns the name of the currently playing song.</summary>
|
||||
public override string getNameOfCurrentSong()
|
||||
{
|
||||
return this.currentCue?.Name ?? "";
|
||||
}
|
||||
|
||||
/// <summary>Returns a shortened directory name for display purposes.</summary>
|
||||
public override void setModDirectoryFromFullDirectory()
|
||||
{
|
||||
string[] spliter = this.WaveBankPath.Split(Path.DirectorySeparatorChar);
|
||||
string directoryLocation = "";
|
||||
for (int i = spliter.Length - 5; i < spliter.Length; i++)
|
||||
{
|
||||
directoryLocation += spliter[i];
|
||||
|
||||
if (i != spliter.Length - 1)
|
||||
directoryLocation += Path.DirectorySeparatorChar;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool isPlaying()
|
||||
{
|
||||
if (this.currentCue == null) return false;
|
||||
return this.currentCue.IsPlaying;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
**Stardew Symphony Remastered** is a [Stardew Valley](http://stardewvalley.net/) mod that lets you
|
||||
add music packs to Stardew Valley and play them without editing the game's default sound files.
|
||||
|
||||
## Contents
|
||||
* [For players](#for-players)
|
||||
* [Install](#install)
|
||||
* [Use](#use)
|
||||
* [Configure](#configure)
|
||||
* [Compatibility](#compatibility)
|
||||
* [For content pack creators](#for-content-pack-creators)
|
||||
* [For SMAPI mod creators](#for-smapi-mod-creators)
|
||||
* [See also](#see-also)
|
||||
|
||||
## For players
|
||||
### Install
|
||||
1. [Install the latest version of SMAPI](https://smapi.io/).
|
||||
2. [Install Stardust Core](https://www.nexusmods.com/stardewvalley/mods/2341).
|
||||
2. [Install this mod from Nexus mods](http://www.nexusmods.com/stardewvalley/mods/1100).
|
||||
3. Run the game using SMAPI.
|
||||
|
||||
### Use
|
||||
1. Unzip any content packs you want to use into `Mods`.
|
||||
2. Press `L` in-game to open the music menu, which will show icons representing the loaded music
|
||||
albums. (You can click the left/right arrows to scroll if you have more than seven albums loaded.)
|
||||
3. Choose an album icon to see a list of available songs on the right.
|
||||
4. Click a song to select it. You can click the play/stop button to preview the song.
|
||||
5. Next configure when the music will play by choosing options on the right. You can play it during
|
||||
a specified season, festival, event, date, weather, time of day, location, or menu. The
|
||||
conditions can be very broad (like 'play in winter') or very specific (like 'play during snowy
|
||||
winter nights at the Saloon on Wednesdays'). Note that when two songs can be applied, the one
|
||||
with the more specific conditions will be played.
|
||||
6. **Make sure you click 'Add' when you're done!**
|
||||
|
||||
Your music options are saved when the game saves, so they'll be lost if you exit without saving.
|
||||
|
||||
### Configure
|
||||
The mod creates a `config.json` file in its mod folder the first time you run it. You can open that
|
||||
file in a text editor to configure the mod.
|
||||
|
||||
These are the available settings:
|
||||
|
||||
setting | what it affects
|
||||
---------- | -------------------
|
||||
`EnableDebugLog` | Default false. Whether to show debug logs in the SMAPI console.
|
||||
`MinimumDelayBetweenSongsInMilliseconds` | Default 5000. The minimum delay between songs in milliseconds.
|
||||
`MaximumDelayBetweenSongsInMilliseconds` | Default 60000. The maximum delay between songs in milliseconds.
|
||||
`KeyBinding` | Default `L`. The key binding to open the menu music.
|
||||
`WriteAllConfigMusicOptions` | Default false. Whether to write a JSON file for every possible option for a music pack. Use at your own risk!
|
||||
`DisableStardewMusic` | Default false. Whether to completely disable the Stardew Valley OST.
|
||||
|
||||
### Compatibility
|
||||
Stardew Symphony Remastered is compatible with Stardew Valley 1.3+ on Linux/Mac/Windows, both
|
||||
single-player and multiplayer. There are no known issues in multiplayer (even if other players
|
||||
don't have it installed), but it will only affect you.
|
||||
|
||||
## For content pack creators
|
||||
To create a content pack:
|
||||
|
||||
1. [Create a standard content pack](https://stardewvalleywiki.com/Modding:Content_packs), using `Omegasis.StardewSymphonyRemastered` as the 'content pack for' ID.
|
||||
2. Add an `icon.png` image, which is the album logo to show in-game.
|
||||
2. Create a `songs` subfolder containing the `.mp3`, `.ogg`, or `.wav` files to include. The file
|
||||
names (without extensions) will be shown in-game as the song names.
|
||||
|
||||
## For SMAPI mod creators
|
||||
You can reference Stardew Symphony in your own SMAPI mods in order to add new events, festivals,
|
||||
locations, and menus for music selection.
|
||||
|
||||
1. Reference the Stardew Symphony DLL directly (see [how to reference a DLL](https://stackoverflow.com/questions/12992286/how-to-add-a-dll-reference-to-a-project-in-visual-studio)).
|
||||
2. Add `Omegasis.StardewSymphonyRemastered` as a dependency (see [manifest dependencies](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Manifest#Dependencies)).
|
||||
3. Now you can access the Stardew Symphony API to add music contexts:
|
||||
|
||||
```cs
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewModdingAPI.Utilities;
|
||||
using StardewValley;
|
||||
using StardewSymphonyRemastered;
|
||||
|
||||
namespace YourProjectName
|
||||
{
|
||||
/// <summary>The mod entry point.</summary>
|
||||
public class ModEntry : Mod
|
||||
{
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
StardewSymphonyRemaster.SongSpecifics.addLocation(“NameOfLocation”);
|
||||
StardewSymphonyRemaster.SongSpecifics.addEvent(“UniqueEventID”);
|
||||
StardewSymphonyRemaster.SongSpecifics.addFestival(“FestivalName”);
|
||||
StardewSymphonyRemaster.SongSpecifics.addMenu(typeOf(MyMenu));
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Happy modding!
|
||||
|
||||
## See also
|
||||
* [Nexus mod](http://www.nexusmods.com/stardewvalley/mods/425)
|
||||
* [Discussion thread](https://community.playstarbound.com/threads/stardew-symphony-add-music-packs-to-stardew-valley.115686/)
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewSymphonyRemastered.Framework;
|
||||
|
@ -25,40 +26,26 @@ namespace StardewSymphonyRemastered
|
|||
// All mods must add events/locations/festivals/menu information to this mod during the Entry function of their mod because once the player is loaded that's when all of the packs are initialized with all of their music.
|
||||
public class StardewSymphony : Mod
|
||||
{
|
||||
public static WaveBank DefaultWaveBank;
|
||||
public static ISoundBank DefaultSoundBank;
|
||||
|
||||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
public static IModHelper ModHelper;
|
||||
public static IMonitor ModMonitor;
|
||||
public static IManifest Manifest;
|
||||
|
||||
public static MusicManager musicManager;
|
||||
|
||||
private string MusicPath;
|
||||
public static string WavMusicDirectory;
|
||||
public static string XACTMusicDirectory;
|
||||
public static string TemplateMusicDirectory;
|
||||
|
||||
public bool musicPacksInitialized;
|
||||
|
||||
public static bool festivalStart;
|
||||
public static bool eventStart;
|
||||
|
||||
public static bool menuChangedMusic;
|
||||
|
||||
public static Config Config;
|
||||
|
||||
public static TextureManager textureManager;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>The mod entry point, called after the mod is first loaded.</summary>
|
||||
/// <param name="helper">Provides simplified APIs for writing mods.</param>
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
DefaultSoundBank = Game1.soundBank;
|
||||
DefaultWaveBank = Game1.waveBank;
|
||||
ModHelper = helper;
|
||||
ModMonitor = this.Monitor;
|
||||
Manifest = this.ModManifest;
|
||||
Config = helper.ReadConfig<Config>();
|
||||
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;
|
||||
// EventArgsLocationsChanged += LocationEvents_CurrentLocationChanged;
|
||||
|
@ -76,33 +63,22 @@ namespace StardewSymphonyRemastered
|
|||
|
||||
|
||||
musicManager = new MusicManager();
|
||||
|
||||
this.MusicPath = Path.Combine(ModHelper.DirectoryPath, "Content", "Music");
|
||||
WavMusicDirectory = Path.Combine(this.MusicPath, "Wav");
|
||||
XACTMusicDirectory = Path.Combine(this.MusicPath, "XACT");
|
||||
TemplateMusicDirectory = Path.Combine(this.MusicPath, "Templates");
|
||||
|
||||
|
||||
textureManager = new TextureManager();
|
||||
this.createDirectories();
|
||||
this.createBlankXACTTemplate();
|
||||
this.createBlankWAVTemplate();
|
||||
this.LoadTextures();
|
||||
|
||||
this.musicPacksInitialized = false;
|
||||
menuChangedMusic = false;
|
||||
|
||||
|
||||
//Initialize all of the lists upon creation during entry.
|
||||
SongSpecifics.initializeMenuList();
|
||||
SongSpecifics.initializeEventsList();
|
||||
SongSpecifics.initializeFestivalsList();
|
||||
|
||||
this.initializeMusicPacks();
|
||||
this.LoadMusicPacks();
|
||||
}
|
||||
|
||||
private void GameEvents_OneSecondTick(object sender, EventArgs e)
|
||||
{
|
||||
musicManager?.updateTimer();
|
||||
musicManager?.UpdateTimer();
|
||||
}
|
||||
|
||||
/// <summary>Raised when the player changes locations. This should determine the next song to play.</summary>
|
||||
|
@ -118,14 +94,10 @@ namespace StardewSymphonyRemastered
|
|||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event arguments.</param>
|
||||
private void GameEvents_FirstUpdateTick(object sender, EventArgs e)
|
||||
{
|
||||
if (!this.musicPacksInitialized)
|
||||
{
|
||||
musicManager.initializeMenuMusic(); //Initialize menu music that has been added to SongSpecifics.menus from all other mods during their Entry function.
|
||||
musicManager.initializeFestivalMusic(); //Initialize festival music that has been added to SongSpecifics.menus from all other mods during their Entry function.
|
||||
musicManager.initializeEventMusic(); //Initialize event music that has been added to SongSpecifics.menus from all other mods during their Entry function.
|
||||
this.musicPacksInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Events to occur after the game has loaded in.</summary>
|
||||
|
@ -140,8 +112,8 @@ namespace StardewSymphonyRemastered
|
|||
musicManager.initializeFestivalMusic();
|
||||
musicManager.initializeEventMusic();
|
||||
|
||||
foreach (var musicPack in musicManager.musicPacks)
|
||||
musicPack.Value.readFromJson();
|
||||
foreach (var musicPack in musicManager.MusicPacks)
|
||||
musicPack.Value.LoadSettings();
|
||||
|
||||
SongSpecifics.menus.Sort();
|
||||
SongSpecifics.locations.Sort();
|
||||
|
@ -149,7 +121,6 @@ namespace StardewSymphonyRemastered
|
|||
SongSpecifics.events.Sort();
|
||||
|
||||
musicManager.selectMusic(SongSpecifics.getCurrentConditionalString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -168,16 +139,14 @@ namespace StardewSymphonyRemastered
|
|||
private void MenuEvents_MenuChanged(object sender, EventArgsClickableMenuChanged e)
|
||||
{
|
||||
//var ok = musicManager.currentMusicPack.getNameOfCurrentSong();
|
||||
musicManager.selectMenuMusic(SongSpecifics.getCurrentConditionalString());
|
||||
musicManager.SelectMenuMusic(SongSpecifics.getCurrentConditionalString());
|
||||
}
|
||||
|
||||
private void SaveEvents_BeforeSave(object sender, EventArgs e)
|
||||
{
|
||||
// THIS IS WAY TO LONG to run. Better make it save individual lists when I am editing songs.
|
||||
foreach (var musicPack in musicManager.musicPacks)
|
||||
{
|
||||
musicPack.Value.writeToJson();
|
||||
}
|
||||
foreach (var musicPack in musicManager.MusicPacks)
|
||||
musicPack.Value.SaveSettings();
|
||||
}
|
||||
|
||||
/// <summary>Fires when a key is pressed to open the music selection menu.</summary>
|
||||
|
@ -197,7 +166,7 @@ namespace StardewSymphonyRemastered
|
|||
{
|
||||
if (musicManager == null) return;
|
||||
|
||||
if (Config.disableStardewMusic)
|
||||
if (Config.DisableStardewMusic)
|
||||
{
|
||||
if (Game1.currentSong != null)
|
||||
{
|
||||
|
@ -208,8 +177,8 @@ namespace StardewSymphonyRemastered
|
|||
}
|
||||
else
|
||||
{
|
||||
if (musicManager.currentMusicPack == null) return;
|
||||
if (Game1.currentSong != null && musicManager.currentMusicPack.isPlaying())
|
||||
if (musicManager.CurrentMusicPack == null) return;
|
||||
if (Game1.currentSong != null && musicManager.CurrentMusicPack.IsPlaying())
|
||||
{
|
||||
//ModMonitor.Log("STOP THE MUSIC!!!");
|
||||
Game1.currentSong.Stop(AudioStopOptions.Immediate); //stop the normal songs from playing over the new songs
|
||||
|
@ -219,249 +188,79 @@ namespace StardewSymphonyRemastered
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>Load in the music packs to the music manager.</summary>
|
||||
public void initializeMusicPacks()
|
||||
/// <summary>Load the textures needed by the mod.</summary>
|
||||
public void LoadTextures()
|
||||
{
|
||||
//load in all packs here.
|
||||
this.loadXACTMusicPacks();
|
||||
this.loadWAVMusicPacks();
|
||||
Texture2DExtended LoadTexture(string name)
|
||||
{
|
||||
return new Texture2DExtended(this.Helper.Content.Load<Texture2D>($"assets/{name}"));
|
||||
}
|
||||
|
||||
/// <summary>Create the core directories needed by the mod.</summary>
|
||||
public void createDirectories()
|
||||
{
|
||||
string path = Path.Combine(ModHelper.DirectoryPath, "Content", "Graphics", "MusicMenu");
|
||||
if (!Directory.Exists(path)) Directory.CreateDirectory(path);
|
||||
path = Path.Combine("Content", "Graphics", "MusicMenu");
|
||||
//Generic Icons
|
||||
string musicNote = Path.Combine(path, "MusicNote.png");
|
||||
string musicCD = Path.Combine(path, "MusicDisk.png");
|
||||
string outlineBox = Path.Combine(path, "OutlineBox.png");
|
||||
|
||||
string addIcon = Path.Combine(path, "AddButton.png");
|
||||
string deleteButton = Path.Combine(path, "DeleteButton.png");
|
||||
|
||||
string greenBallon = Path.Combine(path, "GreenBallon.png");
|
||||
string redBallon = Path.Combine(path, "RedBallon.png");
|
||||
string starIcon = Path.Combine(path, "StarIcon.png");
|
||||
|
||||
string menuIcon = Path.Combine(path, "MenuIcon.png");
|
||||
textureManager.addTexture("MusicNote", LoadTexture("MusicNote.png"));
|
||||
textureManager.addTexture("MusicDisk", LoadTexture("MusicDisk.png"));
|
||||
textureManager.addTexture("MusicCD", LoadTexture("MusicDisk.png"));
|
||||
textureManager.addTexture("OutlineBox", LoadTexture("OutlineBox.png"));
|
||||
textureManager.addTexture("AddIcon", LoadTexture("AddButton.png"));
|
||||
textureManager.addTexture("DeleteIcon", LoadTexture("DeleteButton.png"));
|
||||
textureManager.addTexture("GreenBallon", LoadTexture("GreenBallon.png"));
|
||||
textureManager.addTexture("RedBallon", LoadTexture("RedBallon.png"));
|
||||
textureManager.addTexture("StarIcon", LoadTexture("StarIcon.png"));
|
||||
textureManager.addTexture("MenuIcon", LoadTexture("MenuIcon.png"));
|
||||
|
||||
//Time Icons
|
||||
string dayIcon = Path.Combine(path, "TimeIcon_Day.png");
|
||||
string nightIcon = Path.Combine(path, "TimeIcon_Night.png");
|
||||
textureManager.addTexture("DayIcon", LoadTexture("TimeIcon_Day.png"));
|
||||
textureManager.addTexture("NightIcon", LoadTexture("TimeIcon_Night.png"));
|
||||
|
||||
//Fun Icons
|
||||
string eventIcon = Path.Combine(path, "EventIcon.png");
|
||||
string festivalIcon = Path.Combine(path, "FestivalIcon.png");
|
||||
textureManager.addTexture("EventIcon", LoadTexture("EventIcon.png"));
|
||||
textureManager.addTexture("FestivalIcon", LoadTexture("FestivalIcon.png"));
|
||||
|
||||
//WeatherIcons
|
||||
string sunnyIcon = Path.Combine(path, "WeatherIcon_Sunny.png");
|
||||
string rainyIcon = Path.Combine(path, "WeatherIcon_Rainy.png");
|
||||
string debrisIconSpring = Path.Combine(path, "WeatherIcon_DebrisSpring.png");
|
||||
string debrisIconSummer = Path.Combine(path, "WeatherIcon_DebrisSummer.png");
|
||||
string debrisIconFall = Path.Combine(path, "WeatherIcon_DebrisFall.png");
|
||||
string weatherFestivalIcon = Path.Combine(path, "WeatherIcon_Festival.png");
|
||||
string snowIcon = Path.Combine(path, "WeatherIcon_Snowing.png");
|
||||
string stormIcon = Path.Combine(path, "WeatherIcon_Stormy.png");
|
||||
string weddingIcon = Path.Combine(path, "WeatherIcon_WeddingHeart.png");
|
||||
textureManager.addTexture("SunnyIcon", LoadTexture("WeatherIcon_Sunny.png"));
|
||||
textureManager.addTexture("RainyIcon", LoadTexture("WeatherIcon_Rainy.png"));
|
||||
textureManager.addTexture("DebrisSpringIcon", LoadTexture("WeatherIcon_DebrisSpring.png"));
|
||||
textureManager.addTexture("DebrisSummerIcon", LoadTexture("WeatherIcon_DebrisSummer.png"));
|
||||
textureManager.addTexture("DebrisFallIcon", LoadTexture("WeatherIcon_DebrisFall.png"));
|
||||
textureManager.addTexture("WeatherFestivalIcon", LoadTexture("WeatherIcon_Festival.png"));
|
||||
textureManager.addTexture("SnowIcon", LoadTexture("WeatherIcon_Snowing.png"));
|
||||
textureManager.addTexture("StormIcon", LoadTexture("WeatherIcon_Stormy.png"));
|
||||
textureManager.addTexture("WeddingIcon", LoadTexture("WeatherIcon_WeddingHeart.png"));
|
||||
|
||||
//Season Icons
|
||||
string springIcon = Path.Combine(path, "SeasonIcon_Spring.png");
|
||||
string summerIcon = Path.Combine(path, "SeasonIcon_Summer.png");
|
||||
string fallIcon = Path.Combine(path, "SeasonIcon_Fall.png");
|
||||
string winterIcon = Path.Combine(path, "SeasonIcon_Winter.png");
|
||||
textureManager.addTexture("SpringIcon", LoadTexture("SeasonIcon_Spring.png"));
|
||||
textureManager.addTexture("SummerIcon", LoadTexture("SeasonIcon_Summer.png"));
|
||||
textureManager.addTexture("FallIcon", LoadTexture("SeasonIcon_Fall.png"));
|
||||
textureManager.addTexture("WinterIcon", LoadTexture("SeasonIcon_Winter.png"));
|
||||
|
||||
//Day Icons
|
||||
string mondayIcon = Path.Combine(path, "DayIcons_Monday.png");
|
||||
string tuesdayIcon = Path.Combine(path, "DayIcons_Tuesday.png");
|
||||
string wednesdayIcon = Path.Combine(path, "DayIcons_Wednesday.png");
|
||||
string thursdayIcon = Path.Combine(path, "DayIcons_Thursday.png");
|
||||
string fridayIcon = Path.Combine(path, "DayIcons_Friday.png");
|
||||
string saturdayIcon = Path.Combine(path, "DayIcons_Saturday.png");
|
||||
string sundayIcon = Path.Combine(path, "DayIcons_Sunday.png");
|
||||
textureManager.addTexture("MondayIcon", LoadTexture("DayIcons_Monday.png"));
|
||||
textureManager.addTexture("TuesdayIcon", LoadTexture("DayIcons_Tuesday.png"));
|
||||
textureManager.addTexture("WednesdayIcon", LoadTexture("DayIcons_Wednesday.png"));
|
||||
textureManager.addTexture("ThursdayIcon", LoadTexture("DayIcons_Thursday.png"));
|
||||
textureManager.addTexture("FridayIcon", LoadTexture("DayIcons_Friday.png"));
|
||||
textureManager.addTexture("SaturdayIcon", LoadTexture("DayIcons_Saturday.png"));
|
||||
textureManager.addTexture("SundayIcon", LoadTexture("DayIcons_Sunday.png"));
|
||||
|
||||
string houseIcon = Path.Combine(path, "HouseIcon.png");
|
||||
string playButton = Path.Combine(path, "PlayButton.png");
|
||||
string stopButton = Path.Combine(path, "StopButton.png");
|
||||
string backButton = Path.Combine(path, "BackButton.png");
|
||||
textureManager.addTexture("HouseIcon", LoadTexture("HouseIcon.png"));
|
||||
|
||||
textureManager.addTexture("MusicNote", new Texture2DExtended(ModHelper, Manifest.UniqueID, musicNote));
|
||||
textureManager.addTexture("MusicDisk", new Texture2DExtended(ModHelper, Manifest.UniqueID, musicCD));
|
||||
textureManager.addTexture("MusicCD", new Texture2DExtended(ModHelper, Manifest.UniqueID, musicCD));
|
||||
textureManager.addTexture("OutlineBox", new Texture2DExtended(ModHelper, Manifest.UniqueID, outlineBox));
|
||||
textureManager.addTexture("AddIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, addIcon));
|
||||
textureManager.addTexture("DeleteIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, deleteButton));
|
||||
textureManager.addTexture("GreenBallon", new Texture2DExtended(ModHelper, Manifest.UniqueID, greenBallon));
|
||||
textureManager.addTexture("RedBallon", new Texture2DExtended(ModHelper, Manifest.UniqueID, redBallon));
|
||||
textureManager.addTexture("StarIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, starIcon));
|
||||
textureManager.addTexture("MenuIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, menuIcon));
|
||||
textureManager.addTexture("DayIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, dayIcon));
|
||||
textureManager.addTexture("NightIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, nightIcon));
|
||||
textureManager.addTexture("EventIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, eventIcon));
|
||||
textureManager.addTexture("FestivalIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, festivalIcon));
|
||||
textureManager.addTexture("SunnyIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, sunnyIcon));
|
||||
textureManager.addTexture("RainyIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, rainyIcon));
|
||||
textureManager.addTexture("DebrisSpringIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, debrisIconSpring));
|
||||
textureManager.addTexture("DebrisSummerIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, debrisIconSummer));
|
||||
textureManager.addTexture("DebrisFallIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, debrisIconFall));
|
||||
textureManager.addTexture("WeatherFestivalIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, weatherFestivalIcon));
|
||||
textureManager.addTexture("SnowIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, snowIcon));
|
||||
textureManager.addTexture("StormIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, stormIcon));
|
||||
textureManager.addTexture("WeddingIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, weddingIcon));
|
||||
textureManager.addTexture("SpringIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, springIcon));
|
||||
textureManager.addTexture("SummerIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, summerIcon));
|
||||
textureManager.addTexture("FallIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, fallIcon));
|
||||
textureManager.addTexture("WinterIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, winterIcon));
|
||||
textureManager.addTexture("MondayIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, mondayIcon));
|
||||
textureManager.addTexture("TuesdayIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, tuesdayIcon));
|
||||
textureManager.addTexture("WednesdayIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, wednesdayIcon));
|
||||
textureManager.addTexture("ThursdayIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, thursdayIcon));
|
||||
textureManager.addTexture("FridayIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, fridayIcon));
|
||||
textureManager.addTexture("SaturdayIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, saturdayIcon));
|
||||
textureManager.addTexture("SundayIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, sundayIcon));
|
||||
|
||||
textureManager.addTexture("HouseIcon", new Texture2DExtended(ModHelper, Manifest.UniqueID, houseIcon));
|
||||
|
||||
textureManager.addTexture("PlayButton", new Texture2DExtended(ModHelper, Manifest.UniqueID, playButton));
|
||||
textureManager.addTexture("StopButton", new Texture2DExtended(ModHelper, Manifest.UniqueID, stopButton));
|
||||
textureManager.addTexture("BackButton", new Texture2DExtended(ModHelper, Manifest.UniqueID, backButton));
|
||||
|
||||
|
||||
if (!Directory.Exists(this.MusicPath))
|
||||
Directory.CreateDirectory(this.MusicPath);
|
||||
if (!Directory.Exists(WavMusicDirectory))
|
||||
Directory.CreateDirectory(WavMusicDirectory);
|
||||
if (!Directory.Exists(XACTMusicDirectory))
|
||||
Directory.CreateDirectory(XACTMusicDirectory);
|
||||
if (!Directory.Exists(TemplateMusicDirectory))
|
||||
Directory.CreateDirectory(TemplateMusicDirectory);
|
||||
textureManager.addTexture("PlayButton", LoadTexture("PlayButton.png"));
|
||||
textureManager.addTexture("StopButton", LoadTexture("StopButton.png"));
|
||||
textureManager.addTexture("BackButton", LoadTexture("BackButton.png"));
|
||||
}
|
||||
|
||||
/// <summary>Used to create a blank XACT music pack example.</summary>
|
||||
public void createBlankXACTTemplate()
|
||||
/// <summary>Load the available music packs.</summary>
|
||||
public void LoadMusicPacks()
|
||||
{
|
||||
string path = Path.Combine(TemplateMusicDirectory, "XACT");
|
||||
if (!Directory.Exists(path))
|
||||
Directory.CreateDirectory(path);
|
||||
if (!File.Exists(Path.Combine(path, "MusicPackInformation.json")))
|
||||
foreach (IContentPack contentPack in this.Helper.ContentPacks.GetOwned())
|
||||
{
|
||||
MusicPackMetaData blankMetaData = new MusicPackMetaData("Omegas's Music Data Example", "Omegasis", "Just a simple example of how metadata is formated for music packs. Feel free to copy and edit this one!", "1.0.0 CoolExample", "Icon.png");
|
||||
blankMetaData.writeToJson(Path.Combine(path, "MusicPackInformation.json"));
|
||||
}
|
||||
if (!File.Exists(Path.Combine(path, "readme.txt")))
|
||||
{
|
||||
string info = "Place the Wave Bank.xwb file and Sound Bank.xsb file you created in XACT in a similar directory in Content/Music/XACT/SoundPackName.\nModify MusicPackInformation.json as desire!\nRun the mod!";
|
||||
File.WriteAllText(Path.Combine(path, "readme.txt"), info);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>USed to create a blank WAV music pack example.</summary>
|
||||
public void createBlankWAVTemplate()
|
||||
{
|
||||
string path = Path.Combine(TemplateMusicDirectory, "WAV");
|
||||
string pathSongs = Path.Combine(path, "Songs");
|
||||
if (!Directory.Exists(path))
|
||||
Directory.CreateDirectory(path);
|
||||
if (!Directory.Exists(pathSongs))
|
||||
Directory.CreateDirectory(pathSongs);
|
||||
if (!File.Exists(Path.Combine(path, "MusicPackInformation.json")))
|
||||
{
|
||||
MusicPackMetaData blankMetaData = new MusicPackMetaData("Omegas's Music Data Example", "Omegasis", "Just a simple example of how metadata is formated for music packs. Feel free to copy and edit this one!", "1.0.0 CoolExample", "Icon");
|
||||
blankMetaData.writeToJson(Path.Combine(path, "MusicPackInformation.json"));
|
||||
}
|
||||
if (!File.Exists(Path.Combine(path, "readme.txt")))
|
||||
{
|
||||
string info = "Place the .wav song files in the Songs folder, modify the MusicPackInformation.json as desired, and then run!";
|
||||
File.WriteAllText(Path.Combine(path, "readme.txt"), info);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Load in the XACT music packs.</summary>
|
||||
public void loadXACTMusicPacks()
|
||||
{
|
||||
string[] listOfDirectories = Directory.GetDirectories(XACTMusicDirectory);
|
||||
foreach (string folder in listOfDirectories)
|
||||
{
|
||||
//This chunk essentially allows people to name .xwb and .xsb files whatever they want.
|
||||
string[] xwb = Directory.GetFiles(folder, "*.xwb");
|
||||
string[] xsb = Directory.GetFiles(folder, "*.xsb");
|
||||
|
||||
//string[] debug = Directory.GetFiles(folder);
|
||||
if (xwb.Length == 0)
|
||||
{
|
||||
if (Config.EnableDebugLog)
|
||||
ModMonitor.Log("Error loading in attempting to load music pack from: " + folder + ". There is no wave bank music file: .xwb located in this directory. AKA there is no valid music here.", LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
if (xwb.Length >= 2)
|
||||
{
|
||||
if (Config.EnableDebugLog)
|
||||
ModMonitor.Log("Error loading in attempting to load music pack from: " + folder + ". There are too many wave bank music files or .xwbs located in this directory. Please ensure that there is only one music pack in this folder. You can make another music pack but putting a wave bank file in a different folder.", LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (xsb.Length == 0)
|
||||
{
|
||||
if (Config.EnableDebugLog)
|
||||
ModMonitor.Log("Error loading in attempting to load music pack from: " + folder + ". There is no sound bank music file: .xsb located in this directory. AKA there is no valid music here.", LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
if (xsb.Length >= 2)
|
||||
{
|
||||
if (Config.EnableDebugLog)
|
||||
ModMonitor.Log("Error loading in attempting to load music pack from: " + folder + ". There are too many sound bank music files or .xsbs located in this directory. Please ensure that there is only one sound reference file in this folder. You can make another music pack but putting a sound file in a different folder.", LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
string waveBank = xwb[0];
|
||||
string soundBank = xsb[0];
|
||||
string metaData = Path.Combine(folder, "MusicPackInformation.json");
|
||||
|
||||
if (!File.Exists(metaData))
|
||||
{
|
||||
if (Config.EnableDebugLog)
|
||||
ModMonitor.Log("WARNING! Loading in a music pack from: " + folder + ". There is no MusicPackInformation.json associated with this music pack meaning that while songs can be played from this pack, no information about it will be displayed.", LogLevel.Error);
|
||||
}
|
||||
XACTMusicPack musicPack = new XACTMusicPack(folder, waveBank, soundBank);
|
||||
|
||||
musicPack.songInformation.initializeMenuMusic();
|
||||
musicPack.readFromJson();
|
||||
|
||||
MusicPack musicPack = new MusicPack(contentPack);
|
||||
musicPack.SongInformation.initializeMenuMusic();
|
||||
musicPack.LoadSettings();
|
||||
musicManager.addMusicPack(musicPack, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Load in WAV music packs.</summary>
|
||||
public void loadWAVMusicPacks()
|
||||
{
|
||||
string[] listOfDirectories = Directory.GetDirectories(WavMusicDirectory);
|
||||
foreach (string folder in listOfDirectories)
|
||||
{
|
||||
string metaData = Path.Combine(folder, "MusicPackInformation.json");
|
||||
|
||||
if (!File.Exists(metaData))
|
||||
{
|
||||
if (Config.EnableDebugLog)
|
||||
ModMonitor.Log("WARNING! Loading in a music pack from: " + folder + ". There is no MusicPackInformation.json associated with this music pack meaning that while songs can be played from this pack, no information about it will be displayed.", LogLevel.Error);
|
||||
}
|
||||
|
||||
WavMusicPack musicPack = new WavMusicPack(folder);
|
||||
|
||||
musicPack.songInformation.initializeMenuMusic();
|
||||
musicPack.readFromJson();
|
||||
|
||||
musicManager.addMusicPack(musicPack, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Reset the music files for the game.</summary>
|
||||
public static void Reset()
|
||||
{
|
||||
Game1.waveBank = DefaultWaveBank;
|
||||
Game1.soundBank = DefaultSoundBank;
|
||||
}
|
||||
|
||||
public static void DebugLog(string s)
|
||||
{
|
||||
if (Config.EnableDebugLog)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
|
@ -11,8 +11,6 @@
|
|||
<AssemblyName>StardewSymphonyRemastered</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -68,18 +66,11 @@
|
|||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="NAudio">
|
||||
<HintPath>..\..\..\..\..\..\..\..\Desktop\NAudio.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NAudio.Vorbis">
|
||||
<HintPath>..\..\..\..\..\..\..\..\Desktop\NAudioVorbis\NAudio.Vorbis\obj\Debug\NAudio.Vorbis.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NVorbis">
|
||||
<HintPath>..\..\..\..\..\..\..\..\Desktop\NAudioVorbis\bin\NVorbis.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="StardustCore">
|
||||
<HintPath>..\..\StardustCore\bin\Release\StardustCore.dll</HintPath>
|
||||
</Reference>
|
||||
<PackageReference Include="NAudio" Version="1.8.5" />
|
||||
<PackageReference Include="NAudio.Vorbis" Version="1.0.0" />
|
||||
<PackageReference Include="Pathoschild.Stardew.ModBuildConfig" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
|
@ -92,176 +83,139 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="Config.cs" />
|
||||
<Compile Include="Framework\Menus\MusicManagerMenu.cs" />
|
||||
<Compile Include="Framework\Music\MusicPackMetaData.cs" />
|
||||
<Compile Include="Framework\Music\Song.cs" />
|
||||
<Compile Include="Framework\Music\SongListNode.cs" />
|
||||
<Compile Include="StardewSymphony.cs" />
|
||||
<Compile Include="Framework\Music\MusicHexProcessor.cs" />
|
||||
<Compile Include="Framework\Music\MusicManager.cs" />
|
||||
<Compile Include="Framework\Music\MusicPack.cs" />
|
||||
<Compile Include="Framework\Music\SongSpecifics.cs" />
|
||||
<Compile Include="Framework\Music\WavMusicPack.cs" />
|
||||
<Compile Include="Framework\Music\XACTMusicPack.cs" />
|
||||
<Compile Include="Framework\Music\MusicPack.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Content\Graphics\MusicMenu\AddButton.png">
|
||||
<Content Include="assets\AddButton.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\BackButton.png">
|
||||
<Content Include="assets\BackButton.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\DayIcons_Friday.png">
|
||||
<Content Include="assets\DayIcons_Friday.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\DayIcons_Monday.png">
|
||||
<Content Include="assets\DayIcons_Monday.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\DayIcons_Saturday.png">
|
||||
<Content Include="assets\DayIcons_Saturday.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\DayIcons_Sunday.png">
|
||||
<Content Include="assets\DayIcons_Sunday.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\DayIcons_Thursday.png">
|
||||
<Content Include="assets\DayIcons_Thursday.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\DayIcons_Tuesday.png">
|
||||
<Content Include="assets\DayIcons_Tuesday.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\DayIcons_Wednesday.png">
|
||||
<Content Include="assets\DayIcons_Wednesday.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\DeleteButton.png">
|
||||
<Content Include="assets\DeleteButton.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\EventIcon.png">
|
||||
<Content Include="assets\EventIcon.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\FestivalIcon.png">
|
||||
<Content Include="assets\FestivalIcon.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\GreenBallon.png">
|
||||
<Content Include="assets\GreenBallon.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\HouseIcon.png">
|
||||
<Content Include="assets\HouseIcon.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\MenuIcon.png">
|
||||
<Content Include="assets\MenuIcon.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\OutlineBox.png">
|
||||
<Content Include="assets\OutlineBox.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\PlayButton.png">
|
||||
<Content Include="assets\PlayButton.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\RedBallon.png">
|
||||
<Content Include="assets\RedBallon.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\SeasonIcon_Fall.png">
|
||||
<Content Include="assets\SeasonIcon_Fall.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\SeasonIcon_Spring.png">
|
||||
<Content Include="assets\SeasonIcon_Spring.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\SeasonIcon_Summer.png">
|
||||
<Content Include="assets\SeasonIcon_Summer.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\SeasonIcon_Winter.png">
|
||||
<Content Include="assets\SeasonIcon_Winter.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\StarIcon.png">
|
||||
<Content Include="assets\StarIcon.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\StopButton.png">
|
||||
<Content Include="assets\StopButton.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\TimeIcon_Day.png">
|
||||
<Content Include="assets\TimeIcon_Day.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\TimeIcon_Night.png">
|
||||
<Content Include="assets\TimeIcon_Night.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\WeatherIcon_DebrisFall.png">
|
||||
<Content Include="assets\WeatherIcon_DebrisFall.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\WeatherIcon_DebrisSpring.png">
|
||||
<Content Include="assets\WeatherIcon_DebrisSpring.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\WeatherIcon_DebrisSummer.png">
|
||||
<Content Include="assets\WeatherIcon_DebrisSummer.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\WeatherIcon_Festival.png">
|
||||
<Content Include="assets\WeatherIcon_Festival.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\WeatherIcon_Rainy.png">
|
||||
<Content Include="assets\WeatherIcon_Rainy.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\WeatherIcon_Snowing.png">
|
||||
<Content Include="assets\WeatherIcon_Snowing.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\WeatherIcon_Stormy.png">
|
||||
<Content Include="assets\WeatherIcon_Stormy.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\WeatherIcon_Sunny.png">
|
||||
<Content Include="assets\WeatherIcon_Sunny.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\WeatherIcon_WeddingHeart.png">
|
||||
<Content Include="assets\WeatherIcon_WeddingHeart.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\WeatherIcon_WeddingLetter.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Music\Templates\WAV\MusicPackInformation.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Music\Templates\WAV\Songs\SongsGoHere.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Music\Templates\XACT\MusicPackInformation.json">
|
||||
<Content Include="assets\WeatherIcon_WeddingLetter.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="manifest.json" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="README.md" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Content\Graphics\MusicMenu\MusicDisk.png">
|
||||
<Content Include="assets\MusicDisk.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Graphics\MusicMenu\MusicNote.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Music\Templates\WAV\readme.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Music\Templates\XACT\readme.txt">
|
||||
<Content Include="assets\MusicNote.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Content\Music\Wav\" />
|
||||
<Folder Include="Content\Music\XACT\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Analyzer Include="..\..\packages\Pathoschild.Stardew.ModBuildConfig.2.2.0\analyzers\dotnet\cs\StardewModdingAPI.ModBuildConfig.Analyzer.dll" />
|
||||
<ProjectReference Include="..\..\StardustCore\StardustCore.csproj">
|
||||
<Project>{0756d36a-95c8-480d-8ea6-4584c03010c6}</Project>
|
||||
<Name>StardustCore</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\deploy.targets" />
|
||||
<Import Project="..\packages\Pathoschild.Stardew.ModBuildConfig.2.0.2\build\Pathoschild.Stardew.ModBuildConfig.targets" Condition="Exists('..\packages\Pathoschild.Stardew.ModBuildConfig.2.0.2\build\Pathoschild.Stardew.ModBuildConfig.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Pathoschild.Stardew.ModBuildConfig.2.0.2\build\Pathoschild.Stardew.ModBuildConfig.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Pathoschild.Stardew.ModBuildConfig.2.0.2\build\Pathoschild.Stardew.ModBuildConfig.targets'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Pathoschild.Stardew.ModBuildConfig.2.2.0\build\Pathoschild.Stardew.ModBuildConfig.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Pathoschild.Stardew.ModBuildConfig.2.2.0\build\Pathoschild.Stardew.ModBuildConfig.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\..\packages\Pathoschild.Stardew.ModBuildConfig.2.2.0\build\Pathoschild.Stardew.ModBuildConfig.targets" Condition="Exists('..\..\packages\Pathoschild.Stardew.ModBuildConfig.2.2.0\build\Pathoschild.Stardew.ModBuildConfig.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
Before Width: | Height: | Size: 363 B After Width: | Height: | Size: 363 B |
Before Width: | Height: | Size: 256 B After Width: | Height: | Size: 256 B |
Before Width: | Height: | Size: 309 B After Width: | Height: | Size: 309 B |
Before Width: | Height: | Size: 286 B After Width: | Height: | Size: 286 B |
Before Width: | Height: | Size: 335 B After Width: | Height: | Size: 335 B |
Before Width: | Height: | Size: 327 B After Width: | Height: | Size: 327 B |
Before Width: | Height: | Size: 296 B After Width: | Height: | Size: 296 B |
Before Width: | Height: | Size: 304 B After Width: | Height: | Size: 304 B |
Before Width: | Height: | Size: 316 B After Width: | Height: | Size: 316 B |
Before Width: | Height: | Size: 351 B After Width: | Height: | Size: 351 B |
Before Width: | Height: | Size: 381 B After Width: | Height: | Size: 381 B |
Before Width: | Height: | Size: 637 B After Width: | Height: | Size: 637 B |
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 295 B |
Before Width: | Height: | Size: 473 B After Width: | Height: | Size: 473 B |
Before Width: | Height: | Size: 304 B After Width: | Height: | Size: 304 B |
Before Width: | Height: | Size: 270 B After Width: | Height: | Size: 270 B |
Before Width: | Height: | Size: 242 B After Width: | Height: | Size: 242 B |
Before Width: | Height: | Size: 179 B After Width: | Height: | Size: 179 B |
Before Width: | Height: | Size: 234 B After Width: | Height: | Size: 234 B |
Before Width: | Height: | Size: 303 B After Width: | Height: | Size: 303 B |
Before Width: | Height: | Size: 743 B After Width: | Height: | Size: 743 B |
Before Width: | Height: | Size: 815 B After Width: | Height: | Size: 815 B |
Before Width: | Height: | Size: 649 B After Width: | Height: | Size: 649 B |
Before Width: | Height: | Size: 774 B After Width: | Height: | Size: 774 B |
Before Width: | Height: | Size: 315 B After Width: | Height: | Size: 315 B |
Before Width: | Height: | Size: 208 B After Width: | Height: | Size: 208 B |
Before Width: | Height: | Size: 331 B After Width: | Height: | Size: 331 B |
Before Width: | Height: | Size: 447 B After Width: | Height: | Size: 447 B |
Before Width: | Height: | Size: 413 B After Width: | Height: | Size: 413 B |
Before Width: | Height: | Size: 390 B After Width: | Height: | Size: 390 B |
Before Width: | Height: | Size: 389 B After Width: | Height: | Size: 389 B |
Before Width: | Height: | Size: 734 B After Width: | Height: | Size: 734 B |
Before Width: | Height: | Size: 402 B After Width: | Height: | Size: 402 B |
Before Width: | Height: | Size: 484 B After Width: | Height: | Size: 484 B |
Before Width: | Height: | Size: 539 B After Width: | Height: | Size: 539 B |
Before Width: | Height: | Size: 312 B After Width: | Height: | Size: 312 B |
Before Width: | Height: | Size: 340 B After Width: | Height: | Size: 340 B |
Before Width: | Height: | Size: 376 B After Width: | Height: | Size: 376 B |
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Pathoschild.Stardew.ModBuildConfig" version="2.2.0" targetFramework="net45" />
|
||||
</packages>
|
|
@ -33,9 +33,9 @@ namespace StardustCore
|
|||
|
||||
TextureManagers = new Dictionary<string, TextureManager>();
|
||||
TextureManager = new TextureManager();
|
||||
TextureManager.addTexture("Test1", new Texture2DExtended(ModCore.ModHelper, Manifest, Path.Combine("Content", "Graphics", "MultiTest", "Test1.png")));
|
||||
TextureManager.addTexture("Test2", new Texture2DExtended(ModCore.ModHelper, Manifest, Path.Combine("Content", "Graphics", "MultiTest", "Test2.png")));
|
||||
TextureManager.addTexture("Test3", new Texture2DExtended(ModCore.ModHelper, Manifest, Path.Combine("Content", "Graphics", "MultiTest", "Test3.png")));
|
||||
TextureManager.addTexture("Test1", new Texture2DExtended(ModCore.ModHelper, Path.Combine("Content", "Graphics", "MultiTest", "Test1.png")));
|
||||
TextureManager.addTexture("Test2", new Texture2DExtended(ModCore.ModHelper, Path.Combine("Content", "Graphics", "MultiTest", "Test2.png")));
|
||||
TextureManager.addTexture("Test3", new Texture2DExtended(ModCore.ModHelper, Path.Combine("Content", "Graphics", "MultiTest", "Test3.png")));
|
||||
TextureManagers.Add(this.ModManifest.UniqueID, TextureManager);
|
||||
|
||||
this.config = ModHelper.ReadConfig<ModConfig>();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.IO;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using StardewModdingAPI;
|
||||
|
||||
|
@ -6,64 +7,53 @@ namespace StardustCore.UIUtilities
|
|||
{
|
||||
public class Texture2DExtended
|
||||
{
|
||||
public string Name;
|
||||
public Texture2D texture;
|
||||
public string path;
|
||||
readonly IModHelper helper;
|
||||
public string modID;
|
||||
public ContentSource source;
|
||||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The underlying texture.</summary>
|
||||
public Texture2D Texture { get; }
|
||||
|
||||
/// <summary>The texture width.</summary>
|
||||
public int Width => this.Texture.Width;
|
||||
|
||||
/// <summary>The texture height.</summary>
|
||||
public int Height => this.Texture.Height;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Empty/null constructor.</summary>
|
||||
public Texture2DExtended()
|
||||
{
|
||||
this.Name = "";
|
||||
this.texture = null;
|
||||
this.path = "";
|
||||
this.helper = null;
|
||||
this.modID = "";
|
||||
this.Texture = null;
|
||||
}
|
||||
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="path">The relative path to file on disk. See StardustCore.Utilities.getRelativePath(modname,path);
|
||||
public Texture2DExtended(IModHelper helper, IManifest manifest, string path, ContentSource contentSource = ContentSource.ModFolder)
|
||||
public Texture2DExtended(Texture2D texture)
|
||||
{
|
||||
this.Name = Path.GetFileNameWithoutExtension(path);
|
||||
this.path = path;
|
||||
this.texture = helper.Content.Load<Texture2D>(path, contentSource);
|
||||
this.helper = helper;
|
||||
this.modID = manifest.UniqueID;
|
||||
this.source = contentSource;
|
||||
this.Texture = texture;
|
||||
}
|
||||
|
||||
public Texture2DExtended(IModHelper helper, string modID, string path, ContentSource contentSource = ContentSource.ModFolder)
|
||||
public Texture2DExtended(IModHelper helper, string path, ContentSource contentSource = ContentSource.ModFolder)
|
||||
{
|
||||
this.Name = Path.GetFileNameWithoutExtension(path);
|
||||
this.path = path;
|
||||
this.texture = helper.Content.Load<Texture2D>(path, contentSource);
|
||||
this.helper = helper;
|
||||
this.modID = modID;
|
||||
this.source = contentSource;
|
||||
this.Texture = helper.Content.Load<Texture2D>(path, contentSource);
|
||||
}
|
||||
|
||||
public Texture2DExtended Copy()
|
||||
{
|
||||
return new Texture2DExtended(this.helper, this.modID, this.path);
|
||||
}
|
||||
Texture2D clone = new Texture2D(this.Texture.GraphicsDevice, this.Texture.Width, this.Texture.Height);
|
||||
Color[] data = new Color[clone.Width * clone.Height];
|
||||
this.Texture.GetData(data);
|
||||
clone.SetData(data);
|
||||
|
||||
public IModHelper getHelper()
|
||||
{
|
||||
return this.helper;
|
||||
return new Texture2DExtended(clone);
|
||||
}
|
||||
|
||||
/// <summary>Returns the actual 2D texture held by this wrapper class.</summary>
|
||||
public Texture2D getTexture()
|
||||
{
|
||||
return this.texture;
|
||||
}
|
||||
|
||||
public void setTexure(Texture2D text)
|
||||
{
|
||||
this.texture = text;
|
||||
return this.Texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,19 +33,19 @@ namespace Vocalization.Framework.Menus
|
|||
|
||||
public void setUpButtons()
|
||||
{
|
||||
Texture2DExtended buttonTexture = new Texture2DExtended(Vocalization.ModHelper, Vocalization.Manifest, Path.Combine("Content", "Graphics", "SliderButton.png"));
|
||||
Button bar = new Button(new Rectangle(this.xPositionOnScreen + 100, this.yPositionOnScreen + 220, 200, 40), new Texture2DExtended(Vocalization.ModHelper, Vocalization.Manifest, Path.Combine("Content", "Graphics", "SliderBar.png")), new Rectangle(0, 0, 100, 10), 2f);
|
||||
Texture2DExtended buttonTexture = new Texture2DExtended(Vocalization.ModHelper, Path.Combine("Content", "Graphics", "SliderButton.png"));
|
||||
Button bar = new Button(new Rectangle(this.xPositionOnScreen + 100, this.yPositionOnScreen + 220, 200, 40), new Texture2DExtended(Vocalization.ModHelper, Path.Combine("Content", "Graphics", "SliderBar.png")), new Rectangle(0, 0, 100, 10), 2f);
|
||||
//Texture2DExtended barTexture = new Texture2DExtended(Vocalization.ModHelper, Vocalization.Manifest, Path.Combine("Content", "Graphics", "SliderBar.png"));
|
||||
Rectangle sourceRect = new Rectangle(0, 0, 4, 16);
|
||||
this.sliderButton = new SliderButton("Slider", "Volume", new Rectangle(this.xPositionOnScreen + 100, this.yPositionOnScreen + 220, 4, 16), buttonTexture, bar, sourceRect, 2f, new SliderInformation(SliderStyle.Horizontal, (int)(Vocalization.config.voiceVolume * 100), 1), new StardustCore.Animations.Animation(sourceRect), Color.White, Color.Black, new StardustCore.UIUtilities.MenuComponents.Delegates.Functionality.ButtonFunctionality(null, null, null), false, null, true);
|
||||
|
||||
Button english = new Button("EnglishButton", "English", new Rectangle(0, 0, 174, 39), new Texture2DExtended(Vocalization.ModHelper, Vocalization.Manifest, Path.Combine("LooseSprites", "LanguageButtons.xnb"), StardewModdingAPI.ContentSource.GameContent), new Rectangle(0, 0, 174, 39), 1f);
|
||||
Button spanish = new Button("SpanishButton", "Spanish", new Rectangle(0, 0, 174, 39), new Texture2DExtended(Vocalization.ModHelper, Vocalization.Manifest, Path.Combine("LooseSprites", "LanguageButtons.xnb"), StardewModdingAPI.ContentSource.GameContent), new Rectangle(0, 39 * 2, 174, 39), 1f);
|
||||
Button portuguese = new Button("PortugueseButton", "Brazillian Portuguese", new Rectangle(0, 0, 174, 39), new Texture2DExtended(Vocalization.ModHelper, Vocalization.Manifest, Path.Combine("LooseSprites", "LanguageButtons.xnb"), StardewModdingAPI.ContentSource.GameContent), new Rectangle(0, 39 * 4, 174, 39), 1f);
|
||||
Button russian = new Button("RussianButton", "Russian", new Rectangle(0, 0, 174, 39), new Texture2DExtended(Vocalization.ModHelper, Vocalization.Manifest, Path.Combine("LooseSprites", "LanguageButtons.xnb"), StardewModdingAPI.ContentSource.GameContent), new Rectangle(0, 39 * 6, 174, 39), 1f);
|
||||
Button chinese = new Button("ChineseButton", "Chinese", new Rectangle(0, 0, 174, 39), new Texture2DExtended(Vocalization.ModHelper, Vocalization.Manifest, Path.Combine("LooseSprites", "LanguageButtons.xnb"), StardewModdingAPI.ContentSource.GameContent), new Rectangle(0, 39 * 8, 174, 39), 1f);
|
||||
Button japanese = new Button("JapaneseButton", "Japanese", new Rectangle(0, 0, 174, 39), new Texture2DExtended(Vocalization.ModHelper, Vocalization.Manifest, Path.Combine("LooseSprites", "LanguageButtons.xnb"), StardewModdingAPI.ContentSource.GameContent), new Rectangle(0, 39 * 10, 174, 39), 1f);
|
||||
Button german = new Button("GermanButton", "German", new Rectangle(0, 0, 174, 39), new Texture2DExtended(Vocalization.ModHelper, Vocalization.Manifest, Path.Combine("LooseSprites", "LanguageButtons.xnb"), StardewModdingAPI.ContentSource.GameContent), new Rectangle(0, 39 * 12, 174, 39), 1f);
|
||||
Button english = new Button("EnglishButton", "English", new Rectangle(0, 0, 174, 39), new Texture2DExtended(Vocalization.ModHelper, Path.Combine("LooseSprites", "LanguageButtons.xnb"), StardewModdingAPI.ContentSource.GameContent), new Rectangle(0, 0, 174, 39), 1f);
|
||||
Button spanish = new Button("SpanishButton", "Spanish", new Rectangle(0, 0, 174, 39), new Texture2DExtended(Vocalization.ModHelper, Path.Combine("LooseSprites", "LanguageButtons.xnb"), StardewModdingAPI.ContentSource.GameContent), new Rectangle(0, 39 * 2, 174, 39), 1f);
|
||||
Button portuguese = new Button("PortugueseButton", "Brazillian Portuguese", new Rectangle(0, 0, 174, 39), new Texture2DExtended(Vocalization.ModHelper, Path.Combine("LooseSprites", "LanguageButtons.xnb"), StardewModdingAPI.ContentSource.GameContent), new Rectangle(0, 39 * 4, 174, 39), 1f);
|
||||
Button russian = new Button("RussianButton", "Russian", new Rectangle(0, 0, 174, 39), new Texture2DExtended(Vocalization.ModHelper, Path.Combine("LooseSprites", "LanguageButtons.xnb"), StardewModdingAPI.ContentSource.GameContent), new Rectangle(0, 39 * 6, 174, 39), 1f);
|
||||
Button chinese = new Button("ChineseButton", "Chinese", new Rectangle(0, 0, 174, 39), new Texture2DExtended(Vocalization.ModHelper, Path.Combine("LooseSprites", "LanguageButtons.xnb"), StardewModdingAPI.ContentSource.GameContent), new Rectangle(0, 39 * 8, 174, 39), 1f);
|
||||
Button japanese = new Button("JapaneseButton", "Japanese", new Rectangle(0, 0, 174, 39), new Texture2DExtended(Vocalization.ModHelper, Path.Combine("LooseSprites", "LanguageButtons.xnb"), StardewModdingAPI.ContentSource.GameContent), new Rectangle(0, 39 * 10, 174, 39), 1f);
|
||||
Button german = new Button("GermanButton", "German", new Rectangle(0, 0, 174, 39), new Texture2DExtended(Vocalization.ModHelper, Path.Combine("LooseSprites", "LanguageButtons.xnb"), StardewModdingAPI.ContentSource.GameContent), new Rectangle(0, 39 * 12, 174, 39), 1f);
|
||||
List<Button> buttons = new List<Button>
|
||||
{
|
||||
english,
|
||||
|
|
|
@ -270,7 +270,7 @@ namespace Vocalization
|
|||
new KeyValuePair<ClickableTextureComponent, ExtraTextureDrawOrder>(speech, ExtraTextureDrawOrder.after)
|
||||
};
|
||||
|
||||
Button menuTab = new Button("", new Rectangle(0, 0, 32, 32), new Texture2DExtended(ModHelper, this.ModManifest, Path.Combine("Content", "Graphics", "MenuTab.png")), "", new Rectangle(0, 0, 32, 32), 2f, new StardustCore.Animations.Animation(new Rectangle(0, 0, 32, 32)), Color.White, Color.White, new StardustCore.UIUtilities.MenuComponents.Delegates.Functionality.ButtonFunctionality(new StardustCore.UIUtilities.MenuComponents.Delegates.DelegatePairing(null, null), new StardustCore.UIUtilities.MenuComponents.Delegates.DelegatePairing(null, null), new StardustCore.UIUtilities.MenuComponents.Delegates.DelegatePairing(null, null)), false, components);
|
||||
Button menuTab = new Button("", new Rectangle(0, 0, 32, 32), new Texture2DExtended(ModHelper, Path.Combine("Content", "Graphics", "MenuTab.png")), "", new Rectangle(0, 0, 32, 32), 2f, new StardustCore.Animations.Animation(new Rectangle(0, 0, 32, 32)), Color.White, Color.White, new StardustCore.UIUtilities.MenuComponents.Delegates.Functionality.ButtonFunctionality(new StardustCore.UIUtilities.MenuComponents.Delegates.DelegatePairing(null, null), new StardustCore.UIUtilities.MenuComponents.Delegates.DelegatePairing(null, null), new StardustCore.UIUtilities.MenuComponents.Delegates.DelegatePairing(null, null)), false, components);
|
||||
|
||||
//Change this to take the vocalization menu instead
|
||||
var modTabs = new List<KeyValuePair<Button, IClickableMenuExtended>>
|
||||
|
@ -308,7 +308,7 @@ namespace Vocalization
|
|||
components.Add(new KeyValuePair<ClickableTextureComponent, ExtraTextureDrawOrder>(c, ExtraTextureDrawOrder.after));
|
||||
components.Add(new KeyValuePair<ClickableTextureComponent, ExtraTextureDrawOrder>(speech, ExtraTextureDrawOrder.after));
|
||||
|
||||
Button menuTab = new Button("", new Rectangle(0, 0, 32, 32), new Texture2DExtended(ModHelper, this.ModManifest, Path.Combine("Content", "Graphics", "MenuTab.png")), "", new Rectangle(0, 0, 32, 32), 2f, new StardustCore.Animations.Animation(new Rectangle(0, 0, 32, 32)), Color.White, Color.White, new StardustCore.UIUtilities.MenuComponents.Delegates.Functionality.ButtonFunctionality(null, null, null), false, components);
|
||||
Button menuTab = new Button("", new Rectangle(0, 0, 32, 32), new Texture2DExtended(ModHelper, Path.Combine("Content", "Graphics", "MenuTab.png")), "", new Rectangle(0, 0, 32, 32), 2f, new StardustCore.Animations.Animation(new Rectangle(0, 0, 32, 32)), Color.White, Color.White, new StardustCore.UIUtilities.MenuComponents.Delegates.Functionality.ButtonFunctionality(null, null, null), false, components);
|
||||
|
||||
//Change this to take the vocalization menu instead
|
||||
List<KeyValuePair<Button, IClickableMenuExtended>> modTabs = new List<KeyValuePair<Button, IClickableMenuExtended>>();
|
||||
|
|