summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2018-08-11 14:18:52 -0400
committerJesse Plamondon-Willard <github@jplamondonw.com>2018-08-11 14:18:52 -0400
commitef731de8318c7f01567baf2e23ae9a09789b4bdd (patch)
tree6479ee93233ee0a1e64c383ee3776894c6937e24
parent04404952c8006069eb79774c92467a1c231c83d2 (diff)
downloadSMAPI-ef731de8318c7f01567baf2e23ae9a09789b4bdd.tar.gz
SMAPI-ef731de8318c7f01567baf2e23ae9a09789b4bdd.tar.bz2
SMAPI-ef731de8318c7f01567baf2e23ae9a09789b4bdd.zip
add --mods-path CLI argument to allow switching between mod folders (#579)
-rw-r--r--docs/release-notes.md3
-rw-r--r--docs/technical-docs.md1
-rw-r--r--src/SMAPI/Constants.cs2
-rw-r--r--src/SMAPI/Program.cs37
4 files changed, 33 insertions, 10 deletions
diff --git a/docs/release-notes.md b/docs/release-notes.md
index d6a72b90..183d8e2e 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -8,7 +8,8 @@
* Fixed some SMAPI logs not deleted when starting a new session.
* For modders:
- * All enums in `config.json` are now serialised to string by default, since that's more user-friendly. Previously only certain predefined enums were serialised that way. Note that `config.json` files which already have integer enums will still be parsed fine.
+ * Added `--mods-path` command-line argument to allow switching between mod folders.
+ * All enums are now JSON-serialised by name, since that's more user-friendly. Previously only certain predefined enums were serialised that way. JSON files which already have integer enums will still be parsed fine.
* Fixed false compatibility error when constructing multidimensional arrays.
* Fixed `.ToSButton()` methods not being public.
* Updated compatibility list.
diff --git a/docs/technical-docs.md b/docs/technical-docs.md
index d829baf9..ed45871a 100644
--- a/docs/technical-docs.md
+++ b/docs/technical-docs.md
@@ -138,6 +138,7 @@ change without warning.
argument | purpose
-------- | -------
`--no-terminal` | SMAPI won't write anything to the console window. (Messages will still be written to the log file.)
+`--mods-path` | The path to search for mods, if not the standard `Mods` folder. This can be a path relative to the game folder (like `--mods-path "Mods (test)"`) or an absolute path.
### Compile flags
SMAPI uses a small number of conditional compilation constants, which you can set by editing the
diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs
index 07bb3e17..c7cd6e41 100644
--- a/src/SMAPI/Constants.cs
+++ b/src/SMAPI/Constants.cs
@@ -89,7 +89,7 @@ namespace StardewModdingAPI
internal static string UpdateMarker => Path.Combine(Constants.ExecutionPath, "StardewModdingAPI.update.marker");
/// <summary>The full path to the folder containing mods.</summary>
- internal static string ModPath { get; } = Path.Combine(Constants.ExecutionPath, "Mods");
+ internal static string DefaultModsPath { get; } = Path.Combine(Constants.ExecutionPath, "Mods");
/// <summary>The game's current semantic version.</summary>
internal static ISemanticVersion GameVersion { get; } = new GameVersion(Constants.GetGameVersion());
diff --git a/src/SMAPI/Program.cs b/src/SMAPI/Program.cs
index 4e4c913a..a894e831 100644
--- a/src/SMAPI/Program.cs
+++ b/src/SMAPI/Program.cs
@@ -100,6 +100,9 @@ namespace StardewModdingAPI
/// <summary>The mod toolkit used for generic mod interactions.</summary>
private readonly ModToolkit Toolkit = new ModToolkit();
+ /// <summary>The path to search for mods.</summary>
+ private readonly string ModsPath;
+
/*********
** Public methods
@@ -113,18 +116,34 @@ namespace StardewModdingAPI
// get flags from arguments
bool writeToConsole = !args.Contains("--no-terminal");
+ // get mods path from arguments
+ string modsPath = null;
+ {
+ int pathIndex = Array.LastIndexOf(args, "--mods-path") + 1;
+ if (pathIndex >= 1 && args.Length >= pathIndex)
+ {
+ modsPath = args[pathIndex];
+ if (!string.IsNullOrWhiteSpace(modsPath) && !Path.IsPathRooted(modsPath))
+ modsPath = Path.Combine(Constants.ExecutionPath, modsPath);
+ }
+ if (string.IsNullOrWhiteSpace(modsPath))
+ modsPath = Constants.DefaultModsPath;
+ }
+
// load SMAPI
- using (Program program = new Program(writeToConsole))
+ using (Program program = new Program(modsPath, writeToConsole))
program.RunInteractively();
}
/// <summary>Construct an instance.</summary>
+ /// <param name="modsPath">The path to search for mods.</param>
/// <param name="writeToConsole">Whether to output log messages to the console.</param>
- public Program(bool writeToConsole)
+ public Program(string modsPath, bool writeToConsole)
{
// init paths
- this.VerifyPath(Constants.ModPath);
+ this.VerifyPath(modsPath);
this.VerifyPath(Constants.LogDir);
+ this.ModsPath = modsPath;
// init log file
this.PurgeLogFiles();
@@ -143,7 +162,9 @@ namespace StardewModdingAPI
// init logging
this.Monitor.Log($"SMAPI {Constants.ApiVersion} with Stardew Valley {Constants.GameVersion} on {EnvironmentUtility.GetFriendlyPlatformName(Constants.Platform)}", LogLevel.Info);
- this.Monitor.Log($"Mods go here: {Constants.ModPath}");
+ this.Monitor.Log($"Mods go here: {modsPath}");
+ if (modsPath != Constants.DefaultModsPath)
+ this.Monitor.Log("(Using custom --mods-path argument.)", LogLevel.Trace);
this.Monitor.Log($"Log started at {DateTime.UtcNow:s} UTC", LogLevel.Trace);
// validate game version
@@ -412,7 +433,7 @@ namespace StardewModdingAPI
ModResolver resolver = new ModResolver();
// load manifests
- IModMetadata[] mods = resolver.ReadManifests(toolkit, Constants.ModPath, modDatabase).ToArray();
+ IModMetadata[] mods = resolver.ReadManifests(toolkit, this.ModsPath, modDatabase).ToArray();
resolver.ValidateManifests(mods, Constants.ApiVersion, toolkit.GetUpdateUrl);
// process dependencies
@@ -429,7 +450,7 @@ namespace StardewModdingAPI
Exported = DateTime.UtcNow.ToString("O"),
ApiVersion = Constants.ApiVersion.ToString(),
GameVersion = Constants.GameVersion.ToString(),
- ModFolderPath = Constants.ModPath,
+ ModFolderPath = this.ModsPath,
Mods = mods
};
this.Toolkit.JsonHelper.WriteJsonFile(Path.Combine(Constants.LogDir, $"{Constants.LogNamePrefix}metadata-dump.json"), export);
@@ -740,7 +761,7 @@ namespace StardewModdingAPI
// load content packs
foreach (IModMetadata metadata in mods.Where(p => p.IsContentPack))
{
- this.Monitor.Log($" {metadata.DisplayName} (content pack, {PathUtilities.GetRelativePath(Constants.ModPath, metadata.DirectoryPath)})...", LogLevel.Trace);
+ this.Monitor.Log($" {metadata.DisplayName} (content pack, {PathUtilities.GetRelativePath(this.ModsPath, metadata.DirectoryPath)})...", LogLevel.Trace);
// show warning for missing update key
if (metadata.HasManifest() && !metadata.HasUpdateKeys())
@@ -785,7 +806,7 @@ namespace StardewModdingAPI
// get basic info
IManifest manifest = metadata.Manifest;
this.Monitor.Log(metadata.Manifest?.EntryDll != null
- ? $" {metadata.DisplayName} ({PathUtilities.GetRelativePath(Constants.ModPath, metadata.DirectoryPath)}{Path.DirectorySeparatorChar}{metadata.Manifest.EntryDll})..." // don't use Path.Combine here, since EntryDLL might not be valid
+ ? $" {metadata.DisplayName} ({PathUtilities.GetRelativePath(this.ModsPath, metadata.DirectoryPath)}{Path.DirectorySeparatorChar}{metadata.Manifest.EntryDll})..." // don't use Path.Combine here, since EntryDLL might not be valid
: $" {metadata.DisplayName}...", LogLevel.Trace);
// show warnings