using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using Microsoft.Win32;
using StardewModdingApi.Installer.Enums;
using StardewModdingAPI.Installer.Framework;
using StardewModdingAPI.Internal;
using StardewModdingAPI.Internal.ConsoleWriting;
using StardewModdingAPI.Toolkit;
using StardewModdingAPI.Toolkit.Framework.ModScanning;
using StardewModdingAPI.Toolkit.Utilities;
#if !SMAPI_FOR_WINDOWS
using System.Diagnostics;
#endif
namespace StardewModdingApi.Installer
{
/// <summary>Interactively performs the install and uninstall logic.</summary>
internal class InteractiveInstaller
{
/*********
** Fields
*********/
/// <summary>The absolute path to the directory containing the files to copy into the game folder.</summary>
private readonly string BundlePath;
/// <summary>The <see cref="Environment.OSVersion"/> value that represents Windows 7.</summary>
private readonly Version Windows7Version = new Version(6, 1);
/// <summary>The mod IDs which the installer should allow as bundled mods.</summary>
private readonly string[] BundledModIDs = new[]
{
"SMAPI.SaveBackup",
"SMAPI.ConsoleCommands"
};
/// <summary>The default file paths where Stardew Valley can be installed.</summary>
/// <param name="platform">The target platform.</param>
/// <remarks>Derived from the crossplatform mod config: https://github.com/Pathoschild/Stardew.ModBuildConfig. </remarks>
private IEnumerable<string> GetDefaultInstallPaths(Platform platform)
{
switch (platform)
{
case Platform.Linux:
case Platform.Mac:
{
string home = Environment.GetEnvironmentVariable("HOME");
// Linux
yield return $"{home}/GOG Games/Stardew Valley/game";
yield return Directory.Exists($"{home}/.steam/steam/steamapps/common/Stardew Valley")
? $"{home}/.steam/steam/steamapps/common/Stardew Valley"
: $"{home}/.local/share/Steam/steamapps/common/Stardew Valley";
// Mac
yield return "/Applications/Stardew Valley.app/Contents/MacOS";
yield return $"{home}/Library/Application Support/Steam/steamapps/common/Stardew Valley/Contents/MacOS";
}
break;
case Platform.Windows:
{
// Windows
foreach (string programFiles in new[] { @"C:\Program Files", @"C:\Program Files (x86)" })
{
yield return $@"{programFiles}\GalaxyClient\Games\Stardew Valley";
yield return $@"{programFiles}\GOG Galaxy\Games\Stardew Valley";
yield return $@"{programFiles}\Steam\steamapps\common\Stardew Valley";
}
// Windows registry
IDictionary<string, string> registryKeys = new Dictionary<string, string>
{
[@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 413150"] = "InstallLocation", // Steam
[@"SOFTWARE\WOW6432Node\GOG.com\Games\1453375253"] = "PATH", // GOG on 64-bit Windows
};
foreach (var pair in registryKeys)
{
string path = this.GetLocalMachineRegistryValue(pair.Key, pair.Value);
if (!string.IsNullOrWhiteSpace(path))
yield return path;
}
// via Steam library path
string steampath = this.GetCurrentUserRegistryValue(@"Software\Valve\Steam", "SteamPath");
if (steampath != null)
yield return Path.Combine(steampath.Replace('/', '\\'), @"steamapps\common\Stardew Valley");
}
break;
default:
throw new InvalidOperationException($"Unknown platform '{platform}'.");
}
}
/// <summary>Get the absolute file or folder paths to remove when uninstalling SMAPI.</summary>
/// <param name="installDir">The folder for Stardew Valley and SMAPI.</param>
/// <param name="modsDir">The folder for SMAPI mods.</param>
private IEnumerable<string> GetUninstallPaths(DirectoryInfo installDir, DirectoryInfo modsDir)
{
string GetInstallPath(string path) => Path.Combine(installDir.FullName, path);
// current files
yield return GetInstallPath("libgdiplus.dylib"); // Linux/Mac only
yield return GetInstallPath("StardewModdingAPI"); // Linux/Mac only
yield return GetInstallPath("StardewModdingAPI.exe");
yield return GetInstallPath("StardewModdingAPI.exe.config");
yield return GetInstallPath("StardewModdingAPI.exe.mdb"); // Linux/Mac only
yield return GetInstallPath("StardewModdingAPI.pdb"); // Windows only
yield return GetInstallPath("StardewModdingAPI.xml");
yield return GetInstallPath("smapi-internal");
// obsolete
yield return GetInstallPath(Path.Combine("Mods", ".cache")); // 1.3-1.4
yield return GetInstallPath(Path.Combine("Mods", "TrainerMod")); // *–2.0 (renamed to ConsoleCommands)
yield return GetInstallPath("Mono.Cecil.Rocks.dll"); // 1.3–1.8
yield return GetInstallPath("StardewModdingAPI-settings.json"); // 1.0-1.4
yield return GetInstallPath("StardewModdingAPI.AssemblyRewriters.dll"); // 1.3-2.5.5
yield return GetInstallPath("0Harmony.dll"); // moved in 2.8
yield return GetInstallPath("0Harmony.pdb"); // moved in 2.8
yield return GetInstallPath("Mono.Cecil.dll"); // moved in 2.8