diff --git a/build/prepare-install-package.targets b/build/prepare-install-package.targets
index 09114aee..127a8dd5 100644
--- a/build/prepare-install-package.targets
+++ b/build/prepare-install-package.targets
@@ -11,8 +11,8 @@
$(CompiledRootPath)\SMAPI
$(CompiledRootPath)\SMAPI.Toolkit\net4.5
$(SolutionDir)\..\bin\Packaged
- $(PackagePath)\internal\Windows
- $(PackagePath)\internal\Mono
+ bundle.windows.zipped
+ bundle.mono.zipped
@@ -22,38 +22,63 @@
-
-
-
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/release-notes.md b/docs/release-notes.md
index 6288f0bd..d39e6f3e 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -5,6 +5,7 @@
* Reorganised SMAPI files:
* Most SMAPI files are now tucked into a `smapi-internal` subfolder.
* Save backups are now in a `save-backups` subfolder, so they're easier to access. Note that previous backups will be deleted when you update.
+ * Simplified the installer files to avoid confusion.
* Added support for organising mods:
* You can now group mods into subfolders to organise them.
* You can now mark a mod folder ignored by starting the name with a dot (like `.disabled mods`).
diff --git a/src/SMAPI.Installer/Framework/InstallerPaths.cs b/src/SMAPI.Installer/Framework/InstallerPaths.cs
index 65e7699b..e5396018 100644
--- a/src/SMAPI.Installer/Framework/InstallerPaths.cs
+++ b/src/SMAPI.Installer/Framework/InstallerPaths.cs
@@ -8,8 +8,8 @@ namespace StardewModdingAPI.Installer.Framework
/*********
** Accessors
*********/
- /// The directory containing the installer files for the current platform.
- public DirectoryInfo PackageDir { get; }
+ /// The directory path containing the files to copy into the game folder.
+ public DirectoryInfo BundleDir { get; }
/// The directory containing the installed game.
public DirectoryInfo GameDir { get; }
@@ -17,8 +17,8 @@ namespace StardewModdingAPI.Installer.Framework
/// The directory into which to install mods.
public DirectoryInfo ModsDir { get; }
- /// The full path to the directory containing the installer files for the current platform.
- public string PackagePath => this.PackageDir.FullName;
+ /// The full path to directory path containing the files to copy into the game folder.
+ public string BundlePath => this.BundleDir.FullName;
/// The full path to the directory containing the installed game.
public string GamePath => this.GameDir.FullName;
@@ -46,12 +46,12 @@ namespace StardewModdingAPI.Installer.Framework
** Public methods
*********/
/// Construct an instance.
- /// The directory path containing the installer files for the current platform.
+ /// The directory path containing the files to copy into the game folder.
/// The directory path for the installed game.
/// The name of the game's executable file for the current platform.
- public InstallerPaths(DirectoryInfo packageDir, DirectoryInfo gameDir, string gameExecutableName)
+ public InstallerPaths(DirectoryInfo bundleDir, DirectoryInfo gameDir, string gameExecutableName)
{
- this.PackageDir = packageDir;
+ this.BundleDir = bundleDir;
this.GameDir = gameDir;
this.ModsDir = new DirectoryInfo(Path.Combine(gameDir.FullName, "Mods"));
diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs
index cef0d26c..4212418d 100644
--- a/src/SMAPI.Installer/InteractiveInstaller.cs
+++ b/src/SMAPI.Installer/InteractiveInstaller.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
-using System.Reflection;
using System.Threading;
using Microsoft.Win32;
using StardewModdingApi.Installer.Enums;
@@ -22,8 +21,8 @@ namespace StardewModdingApi.Installer
/*********
** Properties
*********/
- /// The name of the installer file in the package.
- private readonly string InstallerFileName = "install.exe";
+ /// The absolute path to the directory containing the files to copy into the game folder.
+ private readonly string BundlePath;
/// The value that represents Windows 7.
private readonly Version Windows7Version = new Version(6, 1);
@@ -153,8 +152,10 @@ namespace StardewModdingApi.Installer
** Public methods
*********/
/// Construct an instance.
- public InteractiveInstaller()
+ /// The absolute path to the directory containing the files to copy into the game folder.
+ public InteractiveInstaller(string bundlePath)
{
+ this.BundlePath = bundlePath;
this.ConsoleWriter = new ColorfulConsoleWriter(EnvironmentUtility.DetectPlatform(), MonitorColorScheme.AutoDetect);
}
@@ -329,8 +330,8 @@ namespace StardewModdingApi.Installer
}
// get folders
- DirectoryInfo packageDir = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
- paths = new InstallerPaths(packageDir, installDir, EnvironmentUtility.GetExecutableName(platform));
+ DirectoryInfo bundleDir = new DirectoryInfo(this.BundlePath);
+ paths = new InstallerPaths(bundleDir, installDir, EnvironmentUtility.GetExecutableName(platform));
}
Console.Clear();
@@ -338,23 +339,11 @@ namespace StardewModdingApi.Installer
/*********
** Step 4: validate assumptions
*********/
+ if (!File.Exists(paths.ExecutablePath))
{
- if (!paths.PackageDir.Exists)
- {
- this.PrintError(platform == Platform.Windows && paths.PackagePath.Contains(Path.GetTempPath()) && paths.PackagePath.Contains(".zip")
- ? "The installer is missing some files. It looks like you're running the installer from inside the downloaded zip; make sure you unzip the downloaded file first, then run the installer from the unzipped folder."
- : $"The 'internal/{paths.PackageDir.Name}' package folder is missing (should be at {paths.PackagePath})."
- );
- Console.ReadLine();
- return;
- }
-
- if (!File.Exists(paths.ExecutablePath))
- {
- this.PrintError("The detected game install path doesn't contain a Stardew Valley executable.");
- Console.ReadLine();
- return;
- }
+ this.PrintError("The detected game install path doesn't contain a Stardew Valley executable.");
+ Console.ReadLine();
+ return;
}
@@ -446,11 +435,8 @@ namespace StardewModdingApi.Installer
{
// copy SMAPI files to game dir
this.PrintDebug("Adding SMAPI files...");
- foreach (FileSystemInfo sourceEntry in paths.PackageDir.EnumerateFileSystemInfos().Where(this.ShouldCopy))
+ foreach (FileSystemInfo sourceEntry in paths.BundleDir.EnumerateFileSystemInfos().Where(this.ShouldCopy))
{
- if (sourceEntry.Name.StartsWith(this.InstallerFileName)) // e.g. install.exe or install.exe.config
- continue;
-
this.InteractivelyDelete(Path.Combine(paths.GameDir.FullName, sourceEntry.Name));
this.RecursiveCopy(sourceEntry, paths.GameDir);
}
@@ -478,14 +464,14 @@ namespace StardewModdingApi.Installer
}
// add or replace bundled mods
- DirectoryInfo packagedModsDir = new DirectoryInfo(Path.Combine(paths.PackageDir.FullName, "Mods"));
- if (packagedModsDir.Exists && packagedModsDir.EnumerateDirectories().Any())
+ DirectoryInfo bundledModsDir = new DirectoryInfo(Path.Combine(paths.BundlePath, "Mods"));
+ if (bundledModsDir.Exists && bundledModsDir.EnumerateDirectories().Any())
{
this.PrintDebug("Adding bundled mods...");
ModToolkit toolkit = new ModToolkit();
ModFolder[] targetMods = toolkit.GetModFolders(paths.ModsPath).ToArray();
- foreach (ModFolder sourceMod in toolkit.GetModFolders(packagedModsDir.FullName))
+ foreach (ModFolder sourceMod in toolkit.GetModFolders(bundledModsDir.FullName))
{
// validate source mod
if (sourceMod.Manifest == null)
@@ -527,7 +513,7 @@ namespace StardewModdingApi.Installer
}
// remove obsolete appdata mods
- this.InteractivelyRemoveAppDataMods(paths.ModsDir, packagedModsDir);
+ this.InteractivelyRemoveAppDataMods(paths.ModsDir, bundledModsDir);
}
}
Console.WriteLine();
diff --git a/src/SMAPI.Installer/Program.cs b/src/SMAPI.Installer/Program.cs
index ad5cf47f..4056e52a 100644
--- a/src/SMAPI.Installer/Program.cs
+++ b/src/SMAPI.Installer/Program.cs
@@ -1,7 +1,10 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
+using System.IO.Compression;
using System.Reflection;
+using StardewModdingAPI.Internal;
+using StardewModdingAPI.Toolkit.Utilities;
namespace StardewModdingApi.Installer
{
@@ -11,9 +14,15 @@ namespace StardewModdingApi.Installer
/*********
** Properties
*********/
- /// The absolute path to search for referenced assemblies.
+ /// The absolute path of the installer folder.
[SuppressMessage("ReSharper", "AssignNullToNotNullAttribute", Justification = "The assembly location is never null in this context.")]
- private static readonly string DllSearchPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "smapi-internal");
+ private static readonly string InstallerPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+
+ /// The absolute path of the folder containing the unzipped installer files.
+ private static readonly string ExtractedBundlePath = Path.Combine(Path.GetTempPath(), $"SMAPI-installer-{Guid.NewGuid():N}");
+
+ /// The absolute path for referenced assemblies.
+ private static readonly string InternalFilesPath = Path.Combine(Program.ExtractedBundlePath, "smapi-internal");
/*********
** Public methods
@@ -22,11 +31,26 @@ namespace StardewModdingApi.Installer
/// The command line arguments.
public static void Main(string[] args)
{
+ // find install bundle
+ PlatformID platform = Environment.OSVersion.Platform;
+ FileInfo zipFile = new FileInfo(Path.Combine(Program.InstallerPath, $"bundle.{(platform == PlatformID.Win32NT ? "windows" : "mono")}.zipped"));
+ if (!zipFile.Exists)
+ {
+ Console.WriteLine($"Oops! Some of the installer files are missing; try redownloading the installer. (Missing file: {zipFile.FullName})");
+ Console.ReadLine();
+ return;
+ }
+
+ // unzip bundle into temp folder
+ DirectoryInfo bundleDir = new DirectoryInfo(Program.ExtractedBundlePath);
+ Console.WriteLine("Extracting install files...");
+ ZipFile.ExtractToDirectory(zipFile.FullName, bundleDir.FullName);
+
// set up assembly resolution
AppDomain.CurrentDomain.AssemblyResolve += Program.CurrentDomain_AssemblyResolve;
// launch installer
- var installer = new InteractiveInstaller();
+ var installer = new InteractiveInstaller(bundleDir.FullName);
installer.Run(args);
}
@@ -41,7 +65,7 @@ namespace StardewModdingApi.Installer
try
{
AssemblyName name = new AssemblyName(e.Name);
- foreach (FileInfo dll in new DirectoryInfo(Program.DllSearchPath).EnumerateFiles("*.dll"))
+ foreach (FileInfo dll in new DirectoryInfo(Program.InternalFilesPath).EnumerateFiles("*.dll"))
{
if (name.Name.Equals(AssemblyName.GetAssemblyName(dll.FullName).Name, StringComparison.InvariantCultureIgnoreCase))
return Assembly.LoadFrom(dll.FullName);
diff --git a/src/SMAPI.Installer/README.txt b/src/SMAPI.Installer/README.txt
index 88fe4a03..72617240 100644
--- a/src/SMAPI.Installer/README.txt
+++ b/src/SMAPI.Installer/README.txt
@@ -16,7 +16,7 @@ SMAPI lets you run Stardew Valley with mods. Don't forget to download mods separ
Player's guide
--------------------------------
-See https://stardewvalleywiki.com/Modding:Player_Guide
+See https://stardewvalleywiki.com/Modding:Player_Guide for help installing SMAPI, adding mods, etc.
Manual install
@@ -24,12 +24,11 @@ Manual install
THIS IS NOT RECOMMENDED FOR MOST PLAYERS. See instructions above instead.
If you really want to install SMAPI manually, here's how.
-1. Download the latest version of SMAPI: https://github.com/Pathoschild/SMAPI/releases
-2. Unzip the .zip file somewhere (not in your game folder).
-3. Copy the files from the "internal/Windows" folder (on Windows) or "internal/Mono" folder (on
- Linux/Mac) into your game folder. The `StardewModdingAPI.exe` file should be right next to the
- game's executable.
-4.
+1. Unzip "internal/bundle.windows.zipped" (on Windows) or "internal/bundle.mono.zipped" (on
+ Linux/Mac). You can change '.zipped' to '.zip', it's just a normal zip file.
+2. Copy the files from the folder you just unzipped into your game folder. The
+ `StardewModdingAPI.exe` file should be right next to the game's executable.
+3.
- Windows only: if you use Steam, see the install guide above to enable achievements and
overlay. Otherwise, just run StardewModdingAPI.exe in your game folder to play with mods.
diff --git a/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj b/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj
index 22c55af7..8000e4e7 100644
--- a/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj
+++ b/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj
@@ -34,6 +34,8 @@
+
+
diff --git a/src/SMAPI.Installer/unix-install.sh b/src/SMAPI.Installer/unix-install.sh
index 8379ed87..57e48f4b 100644
--- a/src/SMAPI.Installer/unix-install.sh
+++ b/src/SMAPI.Installer/unix-install.sh
@@ -14,7 +14,7 @@ fi
# validate Mono & run installer
if $COMMAND mono >/dev/null 2>&1; then
- mono internal/Mono/install.exe
+ mono internal/install.exe
else
echo "Oops! Looks like Mono isn't installed. Please install Mono from https://mono-project.com, reboot, and run this installer again."
read
diff --git a/src/SMAPI.Installer/windows-install.bat b/src/SMAPI.Installer/windows-install.bat
index 716c7789..1ebec989 100644
--- a/src/SMAPI.Installer/windows-install.bat
+++ b/src/SMAPI.Installer/windows-install.bat
@@ -1 +1 @@
-START /WAIT /B internal/Windows/install.exe
+START /WAIT /B internal/install.exe