From 23988a3c33a7a1616c2d36a2c4b7e3a2d06f4216 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 18 Dec 2016 15:37:23 -0500 Subject: migrate manifest & version to interfaces with backwards compatibility (#197) --- src/StardewModdingAPI/Program.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src/StardewModdingAPI/Program.cs') diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index 62b9dabd..7c9cdcc3 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -98,7 +98,7 @@ namespace StardewModdingAPI Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB"); // add info header - Program.Monitor.Log($"SMAPI {Constants.Version} with Stardew Valley {Game1.version} on {Environment.OSVersion}", LogLevel.Info); + Program.Monitor.Log($"SMAPI {Constants.ApiVersion} with Stardew Valley {Game1.version} on {Environment.OSVersion}", LogLevel.Info); // load user settings { @@ -191,9 +191,9 @@ namespace StardewModdingAPI try { GitRelease release = UpdateHelper.GetLatestVersionAsync(Constants.GitHubRepository).Result; - Version latestVersion = new Version(release.Tag); - if (latestVersion.IsNewerThan(Constants.Version)) - Program.Monitor.Log($"You can update SMAPI from version {Constants.Version} to {latestVersion}", LogLevel.Alert); + ISemanticVersion latestVersion = new SemanticVersion(release.Tag); + if (latestVersion.IsNewerThan(Constants.ApiVersion)) + Program.Monitor.Log($"You can update SMAPI from version {Constants.ApiVersion} to {latestVersion}", LogLevel.Alert); } catch (Exception ex) { @@ -212,7 +212,7 @@ namespace StardewModdingAPI Program.StardewAssembly = Assembly.UnsafeLoadFrom(Program.GameExecutablePath); Program.StardewProgramType = Program.StardewAssembly.GetType("StardewValley.Program", true); Program.StardewGameInfo = Program.StardewProgramType.GetField("gamePtr"); - Game1.version += $"-Z_MODDED | SMAPI {Constants.Version}"; + Game1.version += $"-Z_MODDED | SMAPI {Constants.ApiVersion}"; // add error interceptors #if SMAPI_FOR_WINDOWS @@ -335,7 +335,7 @@ namespace StardewModdingAPI string errorPrefix = $"Couldn't load mod for manifest '{manifestPath}'"; // read manifest - Manifest manifest; + ManifestImpl manifest; try { // read manifest text @@ -347,7 +347,7 @@ namespace StardewModdingAPI } // deserialise manifest - manifest = helper.ReadJsonFile("manifest.json"); + manifest = helper.ReadJsonFile("manifest.json"); if (manifest == null) { Program.Monitor.Log($"{errorPrefix}: the manifest file does not exist.", LogLevel.Error); @@ -374,8 +374,8 @@ namespace StardewModdingAPI { try { - Version minVersion = new Version(manifest.MinimumApiVersion); - if (minVersion.IsNewerThan(Constants.Version)) + ISemanticVersion minVersion = new SemanticVersion(manifest.MinimumApiVersion); + if (minVersion.IsNewerThan(Constants.ApiVersion)) { Program.Monitor.Log($"{errorPrefix}: this mod requires SMAPI {minVersion} or later. Please update SMAPI to the latest version to use this mod.", LogLevel.Error); continue; @@ -473,11 +473,11 @@ namespace StardewModdingAPI Program.ModRegistry.Add(manifest, modAssembly); // hook up mod - modEntry.Manifest = manifest; + modEntry.ModManifest = manifest; modEntry.Helper = helper; modEntry.Monitor = new Monitor(manifest.Name, Program.LogFile) { ShowTraceInConsole = Program.DeveloperMode }; modEntry.PathOnDisk = directory; - Program.Monitor.Log($"Loaded mod: {modEntry.Manifest.Name} by {modEntry.Manifest.Author}, v{modEntry.Manifest.Version} | {modEntry.Manifest.Description}", LogLevel.Info); + Program.Monitor.Log($"Loaded mod: {modEntry.ModManifest.Name} by {modEntry.ModManifest.Author}, v{modEntry.ModManifest.Version} | {modEntry.ModManifest.Description}", LogLevel.Info); Program.ModsLoaded += 1; modEntry.Entry(); // deprecated since 1.0 modEntry.Entry((ModHelper)modEntry.Helper); // deprecated since 1.1 -- cgit From c257d705758a23cf28ce2c1f00b6d3d42cd30a26 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 21 Dec 2016 13:27:56 -0500 Subject: rename SMAPI config file for consistency (#192, #202) --- README.md | 8 ++++---- src/StardewModdingAPI.Installer/InteractiveInstaller.cs | 5 +++-- .../StardewModdingAPI.Installer.csproj | 4 ++-- src/StardewModdingAPI/Program.cs | 2 +- src/StardewModdingAPI/StardewModdingAPI-settings.json | 4 ---- src/StardewModdingAPI/StardewModdingAPI.config.json | 4 ++++ src/StardewModdingAPI/StardewModdingAPI.csproj | 3 ++- 7 files changed, 16 insertions(+), 14 deletions(-) delete mode 100644 src/StardewModdingAPI/StardewModdingAPI-settings.json create mode 100644 src/StardewModdingAPI/StardewModdingAPI.config.json (limited to 'src/StardewModdingAPI/Program.cs') diff --git a/README.md b/README.md index 39cfb25c..c4bcd8d4 100644 --- a/README.md +++ b/README.md @@ -78,9 +78,9 @@ directory containing `src`). Mono.Cecil.Rocks.dll Newtonsoft.Json.dll StardewModdingAPI + StardewModdingAPI.config.json StardewModdingAPI.exe StardewModdingAPI.exe.mdb - StardewModdingAPI-settings.json StardewModdingAPI.AssemblyRewriters.dll System.Numerics.dll System.Runtime.Caching.dll @@ -90,10 +90,10 @@ directory containing `src`). Mono.Cecil.dll Mono.Cecil.Rocks.dll Newtonsoft.Json.dll + StardewModdingAPI.config.json StardewModdingAPI.exe StardewModdingAPI.pdb StardewModdingAPI.xml - StardewModdingAPI-settings.json StardewModdingAPI.AssemblyRewriters.dll steam_appid.txt install.exe @@ -102,7 +102,7 @@ directory containing `src`). 4. Open a terminal in the `SMAPI-` directory and run `chmod 755 Mono/StardewModdingAPI`. 5. Copy & paste the `SMAPI-` directory as `SMAPI--for-developers`. 6. In the `SMAPI-` directory, delete the following files: - * `Mono/StardewModdingAPI-settings.json` + * `Mono/StardewModdingAPI.config.json` + * `Windows/StardewModdingAPI.config.json` * `Windows/StardewModdingAPI.xml` - * `Windows/StardewModdingAPI-settings.json` 7. Compress the two folders into `SMAPI-.zip` and `SMAPI--for-developers.zip`. \ No newline at end of file diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index 4cef1a12..ce6c83d9 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -55,7 +55,7 @@ namespace StardewModdingApi.Installer { // common "StardewModdingAPI.exe", - "StardewModdingAPI-settings.json", + "StardewModdingAPI.config.json", "StardewModdingAPI.AssemblyRewriters.dll", "steam_appid.txt", @@ -72,7 +72,8 @@ namespace StardewModdingApi.Installer "StardewModdingAPI.pdb", // obsolete - "Mods/.cache" + "Mods/.cache", // 1.3-1.4 + "StardewModdingAPI-settings.json" // 1.0-1.4 }; diff --git a/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj b/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj index f82bce0f..c9dedd45 100644 --- a/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj +++ b/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj @@ -73,7 +73,7 @@ - + @@ -87,7 +87,7 @@ - + diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index 7c9cdcc3..9de7496e 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -102,7 +102,7 @@ namespace StardewModdingAPI // load user settings { - string settingsFileName = $"{typeof(Program).Assembly.GetName().Name}-settings.json"; + string settingsFileName = $"{typeof(Program).Assembly.GetName().Name}.config.json"; string settingsPath = Path.Combine(Constants.ExecutionPath, settingsFileName); if (File.Exists(settingsPath)) { diff --git a/src/StardewModdingAPI/StardewModdingAPI-settings.json b/src/StardewModdingAPI/StardewModdingAPI-settings.json deleted file mode 100644 index d27d0141..00000000 --- a/src/StardewModdingAPI/StardewModdingAPI-settings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - /* show all deprecation notices in the console? */ - "DeveloperMode": true -} diff --git a/src/StardewModdingAPI/StardewModdingAPI.config.json b/src/StardewModdingAPI/StardewModdingAPI.config.json new file mode 100644 index 00000000..d27d0141 --- /dev/null +++ b/src/StardewModdingAPI/StardewModdingAPI.config.json @@ -0,0 +1,4 @@ +{ + /* show all deprecation notices in the console? */ + "DeveloperMode": true +} diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj index 875bc1f3..cbcd9964 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.csproj +++ b/src/StardewModdingAPI/StardewModdingAPI.csproj @@ -202,7 +202,7 @@ Designer - + Always @@ -251,6 +251,7 @@ + -- cgit From fa71bdd6c724fa02a5b6d58fb2c48a3d007d8a52 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 21 Dec 2016 13:43:04 -0500 Subject: make SemanticVersion constructor from version string public --- src/StardewModdingAPI/Program.cs | 2 +- src/StardewModdingAPI/SemanticVersion.cs | 31 ++++++++++++++++--------------- 2 files changed, 17 insertions(+), 16 deletions(-) (limited to 'src/StardewModdingAPI/Program.cs') diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index 9de7496e..8a87c15d 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -381,7 +381,7 @@ namespace StardewModdingAPI continue; } } - catch (FormatException ex) when (ex.Message.Contains("not a semantic version")) + catch (FormatException ex) when (ex.Message.Contains("not a valid semantic version")) { Program.Monitor.Log($"{errorPrefix}: the mod specified an invalid minimum SMAPI version '{manifest.MinimumApiVersion}'. This should be a semantic version number like {Constants.Version}.", LogLevel.Error); continue; diff --git a/src/StardewModdingAPI/SemanticVersion.cs b/src/StardewModdingAPI/SemanticVersion.cs index 9694375e..daefda51 100644 --- a/src/StardewModdingAPI/SemanticVersion.cs +++ b/src/StardewModdingAPI/SemanticVersion.cs @@ -53,6 +53,21 @@ namespace StardewModdingAPI this.Build = build; } + /// Construct an instance. + /// The semantic version string. + /// The is not a valid semantic version. + internal SemanticVersion(string version) + { + var match = SemanticVersion.Regex.Match(version); + if (!match.Success) + throw new FormatException($"The input '{version}' is not a valid semantic version."); + + this.MajorVersion = int.Parse(match.Groups["major"].Value); + this.MinorVersion = match.Groups["minor"].Success ? int.Parse(match.Groups["minor"].Value) : 0; + this.PatchVersion = match.Groups["patch"].Success ? int.Parse(match.Groups["patch"].Value) : 0; + this.Build = match.Groups["build"].Success ? match.Groups["build"].Value : null; + } + /// Get an integer indicating whether this version precedes (less than 0), supercedes (more than 0), or is equivalent to (0) the specified version. /// The version to compare with this instance. /// The implementation is defined by Semantic Version 2.0 (http://semver.org/). @@ -141,20 +156,6 @@ namespace StardewModdingAPI /********* ** Private methods *********/ - /// Construct an instance. - /// The semantic version string. - internal SemanticVersion(string version) - { - var match = SemanticVersion.Regex.Match(version); - if (!match.Success) - throw new FormatException($"The input '{version}' is not a semantic version."); - - this.MajorVersion = int.Parse(match.Groups["major"].Value); - this.MinorVersion = match.Groups["minor"].Success ? int.Parse(match.Groups["minor"].Value) : 0; - this.PatchVersion = match.Groups["patch"].Success ? int.Parse(match.Groups["patch"].Value) : 0; - this.Build = match.Groups["build"].Success ? match.Groups["build"].Value : null; - } - /// Get a normalised build tag. /// The tag to normalise. private string GetNormalisedTag(string tag) @@ -167,4 +168,4 @@ namespace StardewModdingAPI return tag; } } -} \ No newline at end of file +} -- cgit From f7eda265d9dd11af7bc9ce2540d45ba2668e2345 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 22 Dec 2016 10:48:05 -0500 Subject: track loaded mod instances & manifests via mod registry (#201) --- src/StardewModdingAPI/Framework/ModRegistry.cs | 18 ++++++-- src/StardewModdingAPI/IMod.cs | 26 +++++++++++ src/StardewModdingAPI/Mod.cs | 2 +- src/StardewModdingAPI/Program.cs | 60 ++++++++++++++++---------- src/StardewModdingAPI/StardewModdingAPI.csproj | 1 + 5 files changed, 80 insertions(+), 27 deletions(-) create mode 100644 src/StardewModdingAPI/IMod.cs (limited to 'src/StardewModdingAPI/Program.cs') diff --git a/src/StardewModdingAPI/Framework/ModRegistry.cs b/src/StardewModdingAPI/Framework/ModRegistry.cs index ba56a447..b593142d 100644 --- a/src/StardewModdingAPI/Framework/ModRegistry.cs +++ b/src/StardewModdingAPI/Framework/ModRegistry.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Reflection; namespace StardewModdingAPI.Framework @@ -11,6 +12,9 @@ namespace StardewModdingAPI.Framework /********* ** Properties *********/ + /// The registered mod data. + private readonly List Mods = new List(); + /// The friendly mod names treated as deprecation warning sources (assembly full name => mod name). private readonly IDictionary ModNamesByAssembly = new Dictionary(); @@ -19,11 +23,17 @@ namespace StardewModdingAPI.Framework ** Public methods *********/ /// Register a mod as a possible source of deprecation warnings. - /// The mod manifest. - /// The mod assembly. - public void Add(Manifest manifest, Assembly assembly) + /// The mod instance. + public void Add(IMod mod) + { + this.Mods.Add(mod); + this.ModNamesByAssembly[mod.GetType().Assembly.FullName] = mod.ModManifest.Name; + } + + /// Get all enabled mods. + public IEnumerable GetMods() { - this.ModNamesByAssembly[assembly.FullName] = manifest.Name; + return (from mod in this.Mods select mod); } /// Get the friendly name for the closest assembly registered as a source of deprecation warnings. diff --git a/src/StardewModdingAPI/IMod.cs b/src/StardewModdingAPI/IMod.cs new file mode 100644 index 00000000..35ac7c0f --- /dev/null +++ b/src/StardewModdingAPI/IMod.cs @@ -0,0 +1,26 @@ +namespace StardewModdingAPI +{ + /// The implementation for a Stardew Valley mod. + public interface IMod + { + /********* + ** Accessors + *********/ + /// Provides simplified APIs for writing mods. + IModHelper Helper { get; } + + /// Writes messages to the console and log file. + IMonitor Monitor { get; } + + /// The mod's manifest. + IManifest ModManifest { get; } + + + /********* + ** Public methods + *********/ + /// The mod entry point, called after the mod is first loaded. + /// Provides simplified APIs for writing mods. + void Entry(IModHelper helper); + } +} \ No newline at end of file diff --git a/src/StardewModdingAPI/Mod.cs b/src/StardewModdingAPI/Mod.cs index f0f876fa..d12a7e05 100644 --- a/src/StardewModdingAPI/Mod.cs +++ b/src/StardewModdingAPI/Mod.cs @@ -5,7 +5,7 @@ using StardewModdingAPI.Framework; namespace StardewModdingAPI { /// The base class for a mod. - public class Mod + public class Mod : IMod { /********* ** Properties diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index 8a87c15d..f2d7faa8 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -462,37 +462,53 @@ namespace StardewModdingAPI continue; } - // hook up mod + // get mod instance + Mod mod; try { + // get implementation TypeInfo modEntryType = modAssembly.DefinedTypes.First(x => x.BaseType == typeof(Mod)); - Mod modEntry = (Mod)modAssembly.CreateInstance(modEntryType.ToString()); - if (modEntry != null) + mod = (Mod)modAssembly.CreateInstance(modEntryType.ToString()); + if (mod == null) { - // track mod - Program.ModRegistry.Add(manifest, modAssembly); - - // hook up mod - modEntry.ModManifest = manifest; - modEntry.Helper = helper; - modEntry.Monitor = new Monitor(manifest.Name, Program.LogFile) { ShowTraceInConsole = Program.DeveloperMode }; - modEntry.PathOnDisk = directory; - Program.Monitor.Log($"Loaded mod: {modEntry.ModManifest.Name} by {modEntry.ModManifest.Author}, v{modEntry.ModManifest.Version} | {modEntry.ModManifest.Description}", LogLevel.Info); - Program.ModsLoaded += 1; - modEntry.Entry(); // deprecated since 1.0 - modEntry.Entry((ModHelper)modEntry.Helper); // deprecated since 1.1 - modEntry.Entry(modEntry.Helper); // deprecated since 1.1 - - // raise deprecation warning for old Entry() method - if (Program.DeprecationManager.IsVirtualMethodImplemented(modEntryType, typeof(Mod), nameof(Mod.Entry), new[] { typeof(object[]) })) - Program.DeprecationManager.Warn(manifest.Name, $"an old version of {nameof(Mod)}.{nameof(Mod.Entry)}", "1.0", DeprecationLevel.Notice); - if (Program.DeprecationManager.IsVirtualMethodImplemented(modEntryType, typeof(Mod), nameof(Mod.Entry), new[] { typeof(ModHelper) })) - Program.DeprecationManager.Warn(manifest.Name, $"an old version of {nameof(Mod)}.{nameof(Mod.Entry)}", "1.1", DeprecationLevel.Notice); + Program.Monitor.Log($"{errorPrefix}: the mod's entry class could not be instantiated."); + continue; } + + // inject data + mod.ModManifest = manifest; + mod.Helper = helper; + mod.Monitor = new Monitor(manifest.Name, Program.LogFile) { ShowTraceInConsole = Program.DeveloperMode }; + mod.PathOnDisk = directory; + + // track mod + Program.ModRegistry.Add(mod); + Program.ModsLoaded += 1; + Program.Monitor.Log($"Loaded mod: {manifest.Name} by {manifest.Author}, v{manifest.Version} | {manifest.Description}", LogLevel.Info); } catch (Exception ex) { Program.Monitor.Log($"{errorPrefix}: an error occurred while loading the target DLL.\n{ex.GetLogSummary()}", LogLevel.Error); + continue; + } + + // call mod entry + try + { + // call entry methods + mod.Entry(); // deprecated since 1.0 + mod.Entry((ModHelper)mod.Helper); // deprecated since 1.1 + mod.Entry(mod.Helper); + + // raise deprecation warning for old Entry() methods + if (Program.DeprecationManager.IsVirtualMethodImplemented(mod.GetType(), typeof(Mod), nameof(Mod.Entry), new[] { typeof(object[]) })) + Program.DeprecationManager.Warn(manifest.Name, $"an old version of {nameof(Mod)}.{nameof(Mod.Entry)}", "1.0", DeprecationLevel.Notice); + if (Program.DeprecationManager.IsVirtualMethodImplemented(mod.GetType(), typeof(Mod), nameof(Mod.Entry), new[] { typeof(ModHelper) })) + Program.DeprecationManager.Warn(manifest.Name, $"an old version of {nameof(Mod)}.{nameof(Mod.Entry)}", "1.1", DeprecationLevel.Notice); + } + catch (Exception ex) + { + Program.Monitor.Log($"The {manifest.Name} mod failed on entry initialisation. It will still be loaded, but may not function correctly.\n{ex.GetLogSummary()}", LogLevel.Warn); } } diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj index cbcd9964..9dec9881 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.csproj +++ b/src/StardewModdingAPI/StardewModdingAPI.csproj @@ -167,6 +167,7 @@ + -- cgit From ca3cf890008ebcf0557b29004514050484a08001 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 22 Dec 2016 11:20:01 -0500 Subject: autogenerate SMAPI config (#202) --- src/StardewModdingAPI/Constants.cs | 3 ++ src/StardewModdingAPI/Program.cs | 33 ++++++++++++---------- .../StardewModdingAPI.config.json | 1 - 3 files changed, 21 insertions(+), 16 deletions(-) (limited to 'src/StardewModdingAPI/Program.cs') diff --git a/src/StardewModdingAPI/Constants.cs b/src/StardewModdingAPI/Constants.cs index 57a89e76..6df9b76c 100644 --- a/src/StardewModdingAPI/Constants.cs +++ b/src/StardewModdingAPI/Constants.cs @@ -68,6 +68,9 @@ namespace StardewModdingAPI /// The file path to the error log where the latest output should be saved. public static string LogPath => Path.Combine(Constants.LogDir, "MODDED_ProgramLog.Log_LATEST.txt"); + /// The file path for the SMAPI configuration file. + internal static string ApiConfigPath => Path.Combine(Constants.ExecutionPath, $"{typeof(Program).Assembly.GetName().Name}.config.json"); + /********* ** Protected methods diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index f2d7faa8..e316dbd8 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -49,8 +49,8 @@ namespace StardewModdingAPI /// The core logger for SMAPI. private static readonly Monitor Monitor = new Monitor("SMAPI", Program.LogFile); - /// Whether SMAPI is running in developer mode. - private static bool DeveloperMode; + /// The user settings for SMAPI. + private static UserSettings Settings; /// Tracks whether the game should exit immediately and any pending initialisation should be cancelled. private static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource(); @@ -100,26 +100,29 @@ namespace StardewModdingAPI // add info header Program.Monitor.Log($"SMAPI {Constants.ApiVersion} with Stardew Valley {Game1.version} on {Environment.OSVersion}", LogLevel.Info); - // load user settings + // initialise user settings { - string settingsFileName = $"{typeof(Program).Assembly.GetName().Name}.config.json"; - string settingsPath = Path.Combine(Constants.ExecutionPath, settingsFileName); + string settingsPath = Constants.ApiConfigPath; if (File.Exists(settingsPath)) { string json = File.ReadAllText(settingsPath); - UserSettings settings = JsonConvert.DeserializeObject(json); - Program.DeveloperMode = settings?.DeveloperMode == true; - - if (Program.DeveloperMode) - { - Program.Monitor.ShowTraceInConsole = true; - Program.Monitor.Log($"SMAPI is running in developer mode. The console may be much more verbose. You can disable developer mode by deleting the {settingsFileName} file in the game directory.", LogLevel.Alert); - } + Program.Settings = JsonConvert.DeserializeObject(json); } + else + Program.Settings = new UserSettings(); + + File.WriteAllText(settingsPath, JsonConvert.SerializeObject(Program.Settings, Formatting.Indented)); + } + + // add warning headers + if (Program.Settings.DeveloperMode) + { + Program.Monitor.ShowTraceInConsole = true; + Program.Monitor.Log($"SMAPI is running in developer mode. The console may be much more verbose. You can disable developer mode by editing or deleting {Constants.ApiConfigPath}.", LogLevel.Alert); } // initialise legacy log - Log.Monitor = new Monitor("legacy mod", Program.LogFile) { ShowTraceInConsole = Program.DeveloperMode }; + Log.Monitor = new Monitor("legacy mod", Program.LogFile) { ShowTraceInConsole = Program.Settings.DeveloperMode }; Log.ModRegistry = Program.ModRegistry; // hook into & launch the game @@ -478,7 +481,7 @@ namespace StardewModdingAPI // inject data mod.ModManifest = manifest; mod.Helper = helper; - mod.Monitor = new Monitor(manifest.Name, Program.LogFile) { ShowTraceInConsole = Program.DeveloperMode }; + mod.Monitor = new Monitor(manifest.Name, Program.LogFile) { ShowTraceInConsole = Program.Settings.DeveloperMode }; mod.PathOnDisk = directory; // track mod diff --git a/src/StardewModdingAPI/StardewModdingAPI.config.json b/src/StardewModdingAPI/StardewModdingAPI.config.json index d27d0141..771c28e2 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.config.json +++ b/src/StardewModdingAPI/StardewModdingAPI.config.json @@ -1,4 +1,3 @@ { - /* show all deprecation notices in the console? */ "DeveloperMode": true } -- cgit From 90f5233cc7d8202a89e1878e1183562fe5ba17b9 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 22 Dec 2016 11:27:48 -0500 Subject: add config setting to disable update checks (#202) --- release-notes.md | 1 + src/StardewModdingAPI/Framework/UserSettings.cs | 6 ++++++ src/StardewModdingAPI/Program.cs | 7 +++++-- src/StardewModdingAPI/StardewModdingAPI.config.json | 3 ++- 4 files changed, 14 insertions(+), 3 deletions(-) (limited to 'src/StardewModdingAPI/Program.cs') diff --git a/release-notes.md b/release-notes.md index 04a9cc04..804d78ba 100644 --- a/release-notes.md +++ b/release-notes.md @@ -4,6 +4,7 @@ See [log](https://github.com/Pathoschild/SMAPI/compare/stable...develop). For players: + * Added option to disable update checks. * Fixed error when a mod uses the new reflection API on a missing field or method. For developers: diff --git a/src/StardewModdingAPI/Framework/UserSettings.cs b/src/StardewModdingAPI/Framework/UserSettings.cs index 199d19b3..6a4fb353 100644 --- a/src/StardewModdingAPI/Framework/UserSettings.cs +++ b/src/StardewModdingAPI/Framework/UserSettings.cs @@ -3,7 +3,13 @@ /// Contains user settings from SMAPI's JSON configuration file. internal class UserSettings { + /********* + ** Accessors + *********/ /// Whether to enable development features. public bool DeveloperMode { get; set; } + + /// Whether to check if a newer version of SMAPI is available on startup. + public bool CheckForUpdates { get; set; } = true; } } diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index e316dbd8..9ecb91e3 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -118,8 +118,10 @@ namespace StardewModdingAPI if (Program.Settings.DeveloperMode) { Program.Monitor.ShowTraceInConsole = true; - Program.Monitor.Log($"SMAPI is running in developer mode. The console may be much more verbose. You can disable developer mode by editing or deleting {Constants.ApiConfigPath}.", LogLevel.Alert); + Program.Monitor.Log($"You configured SMAPI to run in developer mode. The console may be much more verbose. You can disable developer mode by installing the non-developer version of SMAPI, or by editing or deleting {Constants.ApiConfigPath}.", LogLevel.Warn); } + if (!Program.Settings.CheckForUpdates) + Program.Monitor.Log($"You configured SMAPI to not check for updates. Running an old version of SMAPI is not recommended. You can enable update checks by editing or deleting {Constants.ApiConfigPath}.", LogLevel.Warn); // initialise legacy log Log.Monitor = new Monitor("legacy mod", Program.LogFile) { ShowTraceInConsole = Program.Settings.DeveloperMode }; @@ -148,7 +150,8 @@ namespace StardewModdingAPI } // check for update when game loads - GameEvents.GameLoaded += (sender, e) => Program.CheckForUpdateAsync(); + if (Program.Settings.CheckForUpdates) + GameEvents.GameLoaded += (sender, e) => Program.CheckForUpdateAsync(); // launch game Program.StartGame(); diff --git a/src/StardewModdingAPI/StardewModdingAPI.config.json b/src/StardewModdingAPI/StardewModdingAPI.config.json index 771c28e2..2abaf73a 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.config.json +++ b/src/StardewModdingAPI/StardewModdingAPI.config.json @@ -1,3 +1,4 @@ { - "DeveloperMode": true + "DeveloperMode": true, + "CheckForUpdates": true } -- cgit From 3fd16a65f181c710fbbe872f36428176efee7ffb Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 22 Dec 2016 12:45:42 -0500 Subject: move models into namespace (#192) --- src/StardewModdingAPI/Framework/GitRelease.cs | 19 ------------------- src/StardewModdingAPI/Framework/Models/GitRelease.cs | 19 +++++++++++++++++++ .../Framework/Models/UserSettings.cs | 15 +++++++++++++++ src/StardewModdingAPI/Framework/UpdateHelper.cs | 1 + src/StardewModdingAPI/Framework/UserSettings.cs | 15 --------------- src/StardewModdingAPI/Program.cs | 1 + src/StardewModdingAPI/StardewModdingAPI.csproj | 4 ++-- 7 files changed, 38 insertions(+), 36 deletions(-) delete mode 100644 src/StardewModdingAPI/Framework/GitRelease.cs create mode 100644 src/StardewModdingAPI/Framework/Models/GitRelease.cs create mode 100644 src/StardewModdingAPI/Framework/Models/UserSettings.cs delete mode 100644 src/StardewModdingAPI/Framework/UserSettings.cs (limited to 'src/StardewModdingAPI/Program.cs') diff --git a/src/StardewModdingAPI/Framework/GitRelease.cs b/src/StardewModdingAPI/Framework/GitRelease.cs deleted file mode 100644 index 0da57efd..00000000 --- a/src/StardewModdingAPI/Framework/GitRelease.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Newtonsoft.Json; - -namespace StardewModdingAPI.Framework -{ - /// Metadata about a GitHub release tag. - internal class GitRelease - { - /********* - ** Accessors - *********/ - /// The display name. - [JsonProperty("name")] - public string Name { get; set; } - - /// The semantic version string. - [JsonProperty("tag_name")] - public string Tag { get; set; } - } -} \ No newline at end of file diff --git a/src/StardewModdingAPI/Framework/Models/GitRelease.cs b/src/StardewModdingAPI/Framework/Models/GitRelease.cs new file mode 100644 index 00000000..bc53468f --- /dev/null +++ b/src/StardewModdingAPI/Framework/Models/GitRelease.cs @@ -0,0 +1,19 @@ +using Newtonsoft.Json; + +namespace StardewModdingAPI.Framework.Models +{ + /// Metadata about a GitHub release tag. + internal class GitRelease + { + /********* + ** Accessors + *********/ + /// The display name. + [JsonProperty("name")] + public string Name { get; set; } + + /// The semantic version string. + [JsonProperty("tag_name")] + public string Tag { get; set; } + } +} \ No newline at end of file diff --git a/src/StardewModdingAPI/Framework/Models/UserSettings.cs b/src/StardewModdingAPI/Framework/Models/UserSettings.cs new file mode 100644 index 00000000..a0074f77 --- /dev/null +++ b/src/StardewModdingAPI/Framework/Models/UserSettings.cs @@ -0,0 +1,15 @@ +namespace StardewModdingAPI.Framework.Models +{ + /// Contains user settings from SMAPI's JSON configuration file. + internal class UserSettings + { + /********* + ** Accessors + *********/ + /// Whether to enable development features. + public bool DeveloperMode { get; set; } + + /// Whether to check if a newer version of SMAPI is available on startup. + public bool CheckForUpdates { get; set; } = true; + } +} diff --git a/src/StardewModdingAPI/Framework/UpdateHelper.cs b/src/StardewModdingAPI/Framework/UpdateHelper.cs index ddd1d840..e01e55c8 100644 --- a/src/StardewModdingAPI/Framework/UpdateHelper.cs +++ b/src/StardewModdingAPI/Framework/UpdateHelper.cs @@ -3,6 +3,7 @@ using System.Net; using System.Reflection; using System.Threading.Tasks; using Newtonsoft.Json; +using StardewModdingAPI.Framework.Models; namespace StardewModdingAPI.Framework { diff --git a/src/StardewModdingAPI/Framework/UserSettings.cs b/src/StardewModdingAPI/Framework/UserSettings.cs deleted file mode 100644 index 6a4fb353..00000000 --- a/src/StardewModdingAPI/Framework/UserSettings.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace StardewModdingAPI.Framework -{ - /// Contains user settings from SMAPI's JSON configuration file. - internal class UserSettings - { - /********* - ** Accessors - *********/ - /// Whether to enable development features. - public bool DeveloperMode { get; set; } - - /// Whether to check if a newer version of SMAPI is available on startup. - public bool CheckForUpdates { get; set; } = true; - } -} diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index 9ecb91e3..cc3cb2bc 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -14,6 +14,7 @@ using StardewModdingAPI.AssemblyRewriters; using StardewModdingAPI.Events; using StardewModdingAPI.Framework; using StardewModdingAPI.Framework.AssemblyRewriting; +using StardewModdingAPI.Framework.Models; using StardewModdingAPI.Inheritance; using StardewValley; using Monitor = StardewModdingAPI.Framework.Monitor; diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj index 9dec9881..0c6697cb 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.csproj +++ b/src/StardewModdingAPI/StardewModdingAPI.csproj @@ -174,8 +174,8 @@ - - + + -- cgit From fdae87d340e90793ed00fa1766baf9dbd5bec9b6 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 22 Dec 2016 12:47:12 -0500 Subject: skip mods known to be incompatible and display error with update links (#192) --- README.md | 2 ++ .../InteractiveInstaller.cs | 1 + .../StardewModdingAPI.Installer.csproj | 2 ++ src/StardewModdingAPI/Constants.cs | 3 +++ .../Framework/Models/IncompatibleMod.cs | 24 ++++++++++++++++++++++ src/StardewModdingAPI/Manifest.cs | 2 +- src/StardewModdingAPI/Program.cs | 22 ++++++++++++++++++++ src/StardewModdingAPI/StardewModdingAPI.csproj | 5 +++++ src/StardewModdingAPI/StardewModdingAPI.data.json | 16 +++++++++++++++ 9 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs create mode 100644 src/StardewModdingAPI/StardewModdingAPI.data.json (limited to 'src/StardewModdingAPI/Program.cs') diff --git a/README.md b/README.md index c4bcd8d4..eb21f379 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ directory containing `src`). Newtonsoft.Json.dll StardewModdingAPI StardewModdingAPI.config.json + StardewModdingAPI.data.json StardewModdingAPI.exe StardewModdingAPI.exe.mdb StardewModdingAPI.AssemblyRewriters.dll @@ -91,6 +92,7 @@ directory containing `src`). Mono.Cecil.Rocks.dll Newtonsoft.Json.dll StardewModdingAPI.config.json + StardewModdingAPI.data.json StardewModdingAPI.exe StardewModdingAPI.pdb StardewModdingAPI.xml diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index ce6c83d9..5f89caf2 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -56,6 +56,7 @@ namespace StardewModdingApi.Installer // common "StardewModdingAPI.exe", "StardewModdingAPI.config.json", + "StardewModdingAPI.data.json", "StardewModdingAPI.AssemblyRewriters.dll", "steam_appid.txt", diff --git a/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj b/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj index c9dedd45..4e4872b6 100644 --- a/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj +++ b/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj @@ -74,6 +74,7 @@ + @@ -88,6 +89,7 @@ + diff --git a/src/StardewModdingAPI/Constants.cs b/src/StardewModdingAPI/Constants.cs index 6df9b76c..4f7a0c6e 100644 --- a/src/StardewModdingAPI/Constants.cs +++ b/src/StardewModdingAPI/Constants.cs @@ -71,6 +71,9 @@ namespace StardewModdingAPI /// The file path for the SMAPI configuration file. internal static string ApiConfigPath => Path.Combine(Constants.ExecutionPath, $"{typeof(Program).Assembly.GetName().Name}.config.json"); + /// The file path for the SMAPI data file containing metadata about known mods. + internal static string ApiModMetadataPath => Path.Combine(Constants.ExecutionPath, $"{typeof(Program).Assembly.GetName().Name}.data.json"); + /********* ** Protected methods diff --git a/src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs b/src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs new file mode 100644 index 00000000..f3ee7d0b --- /dev/null +++ b/src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs @@ -0,0 +1,24 @@ +namespace StardewModdingAPI.Framework.Models +{ + /// Contains abstract metadata about an incompatible mod. + internal class IncompatibleMod + { + /********* + ** Accessors + *********/ + /// The unique mod ID. + public string ID { get; set; } + + /// The mod name. + public string Name { get; set; } + + /// The most recent incompatible mod version. + public string Version { get; set; } + + /// The URL the user can check for an official updated version. + public string UpdateUrl { get; set; } + + /// The URL the user can check for an unofficial updated version. + public string UnofficialUpdateUrl { get; set; } + } +} \ No newline at end of file diff --git a/src/StardewModdingAPI/Manifest.cs b/src/StardewModdingAPI/Manifest.cs index 981ff023..018b31ae 100644 --- a/src/StardewModdingAPI/Manifest.cs +++ b/src/StardewModdingAPI/Manifest.cs @@ -40,7 +40,7 @@ namespace StardewModdingAPI public string EntryDll { get; set; } /// The unique mod ID. - public string UniqueID { get; set; } = Guid.NewGuid().ToString(); + public string UniqueID { get; set; } /**** diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index cc3cb2bc..7de22ee9 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -315,6 +315,11 @@ namespace StardewModdingAPI ModAssemblyLoader modAssemblyLoader = new ModAssemblyLoader(Program.CacheDirName, Program.TargetPlatform, Program.Monitor); AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => modAssemblyLoader.ResolveAssembly(e.Name); + // get known incompatible mods + IDictionary incompatibleMods = File.Exists(Constants.ApiModMetadataPath) + ? JsonConvert.DeserializeObject(File.ReadAllText(Constants.ApiModMetadataPath)).ToDictionary(p => p.ID, p => p) + : new Dictionary(0); + // load mods foreach (string directory in Directory.GetDirectories(Program.ModPath)) { @@ -376,6 +381,23 @@ namespace StardewModdingAPI continue; } + // validate known incompatible mods + IncompatibleMod incompatible; + if (incompatibleMods.TryGetValue(manifest.UniqueID ?? $"{manifest.Name}|{manifest.Author}|{manifest.EntryDll}", out incompatible)) + { + if (!manifest.Version.IsNewerThan(new SemanticVersion(incompatible.Version))) + { + string warning = $"Skipped {incompatible.Name} ≤v{incompatible.Version} because this version is not compatible with the latest version of the game. Please check for a newer version of the mod here:"; + if (!string.IsNullOrWhiteSpace(incompatible.UpdateUrl)) + warning += $"{Environment.NewLine}- official mod: {incompatible.UpdateUrl}"; + if (!string.IsNullOrWhiteSpace(incompatible.UnofficialUpdateUrl)) + warning += $"{Environment.NewLine}- unofficial update: {incompatible.UnofficialUpdateUrl}"; + + Program.Monitor.Log(warning, LogLevel.Error); + continue; + } + } + // validate version if (!string.IsNullOrWhiteSpace(manifest.MinimumApiVersion)) { diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj index 0c6697cb..07b1ff5e 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.csproj +++ b/src/StardewModdingAPI/StardewModdingAPI.csproj @@ -161,6 +161,7 @@ + @@ -206,6 +207,9 @@ Always + + Always + Always @@ -253,6 +257,7 @@ + diff --git a/src/StardewModdingAPI/StardewModdingAPI.data.json b/src/StardewModdingAPI/StardewModdingAPI.data.json new file mode 100644 index 00000000..91321c69 --- /dev/null +++ b/src/StardewModdingAPI/StardewModdingAPI.data.json @@ -0,0 +1,16 @@ +/* + + +This file contains advanced metadata for SMAPI. You shouldn't change this file. + + +*/ +[ + { + "ID": "CJBCheatsMenu", + "Name": "CJB Cheats Menu", + "Version": "1.12", + "UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/4", + "UnofficialUpdateUrl": "http://community.playstarbound.com/threads/125031" + } +] -- cgit From f6f52b653e59778f9e0b2684faa1ad554acce02f Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 22 Dec 2016 13:08:45 -0500 Subject: add known incompatible mods, update release notes (#192) --- release-notes.md | 1 + src/StardewModdingAPI/Program.cs | 6 ++++-- src/StardewModdingAPI/StardewModdingAPI.data.json | 21 +++++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) (limited to 'src/StardewModdingAPI/Program.cs') diff --git a/release-notes.md b/release-notes.md index 804d78ba..11f393bd 100644 --- a/release-notes.md +++ b/release-notes.md @@ -5,6 +5,7 @@ See [log](https://github.com/Pathoschild/SMAPI/compare/stable...develop). For players: * Added option to disable update checks. + * SMAPI will now show a friendly error with update links when you try to use a known incompatible mod version. * Fixed error when a mod uses the new reflection API on a missing field or method. For developers: diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index 7de22ee9..c3bd1646 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -323,8 +323,10 @@ namespace StardewModdingAPI // load mods foreach (string directory in Directory.GetDirectories(Program.ModPath)) { + string directoryName = new DirectoryInfo(directory).Name; + // ignore internal directory - if (new DirectoryInfo(directory).Name == ".cache") + if (directoryName == ".cache") continue; // check for cancellation @@ -341,7 +343,7 @@ namespace StardewModdingAPI string manifestPath = Path.Combine(directory, "manifest.json"); if (!File.Exists(manifestPath)) { - Program.Monitor.Log($"Ignored folder \"{new DirectoryInfo(directory).Name}\" which doesn't have a manifest.json.", LogLevel.Warn); + Program.Monitor.Log($"Ignored folder \"{directoryName}\" which doesn't have a manifest.json.", LogLevel.Warn); continue; } string errorPrefix = $"Couldn't load mod for manifest '{manifestPath}'"; diff --git a/src/StardewModdingAPI/StardewModdingAPI.data.json b/src/StardewModdingAPI/StardewModdingAPI.data.json index 91321c69..2f1d67e8 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.data.json +++ b/src/StardewModdingAPI/StardewModdingAPI.data.json @@ -6,11 +6,32 @@ This file contains advanced metadata for SMAPI. You shouldn't change this file. */ [ + { + "ID": "SPDSprinklersMod", + "Name": "Better Sprinklers", + "Version": "2.1", + "UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/41", + "UnofficialUpdateUrl": "http://community.playstarbound.com/threads/125031" + }, + { + "ID": "SPDChestLabel", + "Name": "Chest Label System", + "Version": "1.5", + "UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/242", + "UnofficialUpdateUrl": "http://community.playstarbound.com/threads/125031" + }, { "ID": "CJBCheatsMenu", "Name": "CJB Cheats Menu", "Version": "1.12", "UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/4", "UnofficialUpdateUrl": "http://community.playstarbound.com/threads/125031" + }, + { + "ID": "CJBItemSpawner", + "Name": "CJB Item Spawner", + "Version": "1.5", + "UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/93", + "UnofficialUpdateUrl": "http://community.playstarbound.com/threads/125031" } ] -- cgit From c7a08d08db3305a7cfd3a6438beda48b0791eaac Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 22 Dec 2016 22:34:49 -0500 Subject: add support for unofficial updates which suffix the official version number with a pre-release label (#192) --- .../Framework/Models/IncompatibleMod.cs | 23 ++++++++++++++++++++++ src/StardewModdingAPI/Program.cs | 18 ++++++++--------- src/StardewModdingAPI/StardewModdingAPI.data.json | 12 +++++++---- 3 files changed, 40 insertions(+), 13 deletions(-) (limited to 'src/StardewModdingAPI/Program.cs') diff --git a/src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs b/src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs index f3ee7d0b..9bf06552 100644 --- a/src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs +++ b/src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs @@ -1,3 +1,5 @@ +using System.Text.RegularExpressions; + namespace StardewModdingAPI.Framework.Models { /// Contains abstract metadata about an incompatible mod. @@ -20,5 +22,26 @@ namespace StardewModdingAPI.Framework.Models /// The URL the user can check for an unofficial updated version. public string UnofficialUpdateUrl { get; set; } + + /// A regular expression matching version strings to consider compatible, even if they technically precede . + public string ForceCompatibleVersion { get; set; } + + + /********* + ** Public methods + *********/ + /// Get whether the specified version is compatible according to this metadata. + /// The current version of the matching mod. + public bool IsCompatible(ISemanticVersion version) + { + ISemanticVersion incompatibleVersion = new SemanticVersion(this.Version); + + // allow newer versions + if (version.IsNewerThan(incompatibleVersion)) + return true; + + // allow versions matching override + return !string.IsNullOrWhiteSpace(this.ForceCompatibleVersion) && Regex.IsMatch(version.ToString(), this.ForceCompatibleVersion, RegexOptions.IgnoreCase); + } } } \ No newline at end of file diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index c3bd1646..0c232b1d 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -384,23 +384,23 @@ namespace StardewModdingAPI } // validate known incompatible mods - IncompatibleMod incompatible; - if (incompatibleMods.TryGetValue(manifest.UniqueID ?? $"{manifest.Name}|{manifest.Author}|{manifest.EntryDll}", out incompatible)) + IncompatibleMod compatibility; + if (incompatibleMods.TryGetValue(manifest.UniqueID ?? $"{manifest.Name}|{manifest.Author}|{manifest.EntryDll}", out compatibility)) { - if (!manifest.Version.IsNewerThan(new SemanticVersion(incompatible.Version))) + if (!compatibility.IsCompatible(manifest.Version)) { - string warning = $"Skipped {incompatible.Name} ≤v{incompatible.Version} because this version is not compatible with the latest version of the game. Please check for a newer version of the mod here:"; - if (!string.IsNullOrWhiteSpace(incompatible.UpdateUrl)) - warning += $"{Environment.NewLine}- official mod: {incompatible.UpdateUrl}"; - if (!string.IsNullOrWhiteSpace(incompatible.UnofficialUpdateUrl)) - warning += $"{Environment.NewLine}- unofficial update: {incompatible.UnofficialUpdateUrl}"; + string warning = $"Skipped {compatibility.Name} ≤v{compatibility.Version} because this version is not compatible with the latest version of the game. Please check for a newer version of the mod here:"; + if (!string.IsNullOrWhiteSpace(compatibility.UpdateUrl)) + warning += $"{Environment.NewLine}- official mod: {compatibility.UpdateUrl}"; + if (!string.IsNullOrWhiteSpace(compatibility.UnofficialUpdateUrl)) + warning += $"{Environment.NewLine}- unofficial update: {compatibility.UnofficialUpdateUrl}"; Program.Monitor.Log(warning, LogLevel.Error); continue; } } - // validate version + // validate SMAPI version if (!string.IsNullOrWhiteSpace(manifest.MinimumApiVersion)) { try diff --git a/src/StardewModdingAPI/StardewModdingAPI.data.json b/src/StardewModdingAPI/StardewModdingAPI.data.json index 2f1d67e8..49b45018 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.data.json +++ b/src/StardewModdingAPI/StardewModdingAPI.data.json @@ -11,27 +11,31 @@ This file contains advanced metadata for SMAPI. You shouldn't change this file. "Name": "Better Sprinklers", "Version": "2.1", "UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/41", - "UnofficialUpdateUrl": "http://community.playstarbound.com/threads/125031" + "UnofficialUpdateUrl": "http://community.playstarbound.com/threads/125031", + "ForceCompatibleVersion": "^2.1-EntoPatch" }, { "ID": "SPDChestLabel", "Name": "Chest Label System", "Version": "1.5", "UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/242", - "UnofficialUpdateUrl": "http://community.playstarbound.com/threads/125031" + "UnofficialUpdateUrl": "http://community.playstarbound.com/threads/125031", + "ForceCompatibleVersion": "^1.5-EntoPatch" }, { "ID": "CJBCheatsMenu", "Name": "CJB Cheats Menu", "Version": "1.12", "UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/4", - "UnofficialUpdateUrl": "http://community.playstarbound.com/threads/125031" + "UnofficialUpdateUrl": "http://community.playstarbound.com/threads/125031", + "ForceCompatibleVersion": "^1.12-EntoPatch" }, { "ID": "CJBItemSpawner", "Name": "CJB Item Spawner", "Version": "1.5", "UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/93", - "UnofficialUpdateUrl": "http://community.playstarbound.com/threads/125031" + "UnofficialUpdateUrl": "http://community.playstarbound.com/threads/125031", + "ForceCompatibleVersion": "^1.5-EntoPatch" } ] -- cgit From 1fdc0c0b3586bd02119a8d55baf103acf63e86d5 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 23 Dec 2016 11:20:06 -0500 Subject: catch errors when reading metadata file just in case (#192) --- src/StardewModdingAPI/Program.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'src/StardewModdingAPI/Program.cs') diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index 0c232b1d..a48fa716 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -316,9 +316,18 @@ namespace StardewModdingAPI AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => modAssemblyLoader.ResolveAssembly(e.Name); // get known incompatible mods - IDictionary incompatibleMods = File.Exists(Constants.ApiModMetadataPath) - ? JsonConvert.DeserializeObject(File.ReadAllText(Constants.ApiModMetadataPath)).ToDictionary(p => p.ID, p => p) - : new Dictionary(0); + IDictionary incompatibleMods; + try + { + incompatibleMods = File.Exists(Constants.ApiModMetadataPath) + ? JsonConvert.DeserializeObject(File.ReadAllText(Constants.ApiModMetadataPath)).ToDictionary(p => p.ID, p => p) + : new Dictionary(0); + } + catch (Exception ex) + { + incompatibleMods = new Dictionary(); + Program.Monitor.Log($"Couldn't read metadata file at {Constants.ApiModMetadataPath}. SMAPI will still run, but some features may be disabled.\n{ex}", LogLevel.Warn); + } // load mods foreach (string directory in Directory.GetDirectories(Program.ModPath)) -- cgit From 8416c9009e37def03ff894dc660dec34a05c0558 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 23 Dec 2016 12:36:03 -0500 Subject: increase deprecation levels for less-used deprecated code --- release-notes.md | 1 + src/StardewModdingAPI/Inheritance/SObject.cs | 2 +- src/StardewModdingAPI/LogWriter.cs | 2 +- src/StardewModdingAPI/Program.cs | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src/StardewModdingAPI/Program.cs') diff --git a/release-notes.md b/release-notes.md index 11f393bd..9eeae111 100644 --- a/release-notes.md +++ b/release-notes.md @@ -11,6 +11,7 @@ For players: For developers: * Deprecated `Version` in favour of `SemanticVersion`. _This new implementation is [semver 2.0](http://semver.org/)-compliant, introduces `NewerThan(version)` and `OlderThan(version)` convenience methods, adds support for parsing a version string into a `SemanticVersion`, and fixes various bugs with the former implementation._ + * Increased deprecation levels for `SObject`, `Extensions`, `LogWriter` (not `Log`), `SPlayer`, and `Mod.Entry(ModHelper)` (not `Mod.Entry(IModHelper)`). ## 1.4 See [log](https://github.com/Pathoschild/SMAPI/compare/1.3...1.4). diff --git a/src/StardewModdingAPI/Inheritance/SObject.cs b/src/StardewModdingAPI/Inheritance/SObject.cs index 4a218f33..eae5424d 100644 --- a/src/StardewModdingAPI/Inheritance/SObject.cs +++ b/src/StardewModdingAPI/Inheritance/SObject.cs @@ -49,7 +49,7 @@ namespace StardewModdingAPI.Inheritance *********/ public SObject() { - Program.DeprecationManager.Warn(nameof(SObject), "0.39.3", DeprecationLevel.Notice); + Program.DeprecationManager.Warn(nameof(SObject), "0.39.3", DeprecationLevel.Info); this.name = "Modded Item Name"; this.Description = "Modded Item Description"; diff --git a/src/StardewModdingAPI/LogWriter.cs b/src/StardewModdingAPI/LogWriter.cs index 11bcf5f3..058fa649 100644 --- a/src/StardewModdingAPI/LogWriter.cs +++ b/src/StardewModdingAPI/LogWriter.cs @@ -55,7 +55,7 @@ namespace StardewModdingAPI /// Raise a deprecation warning. private void WarnDeprecated() { - Program.DeprecationManager.Warn($"the {nameof(LogWriter)} class", "1.0", DeprecationLevel.Notice); + Program.DeprecationManager.Warn($"the {nameof(LogWriter)} class", "1.0", DeprecationLevel.Info); } } } \ No newline at end of file diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index a48fa716..090098ca 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -542,9 +542,9 @@ namespace StardewModdingAPI // raise deprecation warning for old Entry() methods if (Program.DeprecationManager.IsVirtualMethodImplemented(mod.GetType(), typeof(Mod), nameof(Mod.Entry), new[] { typeof(object[]) })) - Program.DeprecationManager.Warn(manifest.Name, $"an old version of {nameof(Mod)}.{nameof(Mod.Entry)}", "1.0", DeprecationLevel.Notice); + Program.DeprecationManager.Warn(manifest.Name, $"{nameof(Mod)}.{nameof(Mod.Entry)}(object[]) instead of {nameof(Mod)}.{nameof(Mod.Entry)}({nameof(IModHelper)})", "1.0", DeprecationLevel.Notice); if (Program.DeprecationManager.IsVirtualMethodImplemented(mod.GetType(), typeof(Mod), nameof(Mod.Entry), new[] { typeof(ModHelper) })) - Program.DeprecationManager.Warn(manifest.Name, $"an old version of {nameof(Mod)}.{nameof(Mod.Entry)}", "1.1", DeprecationLevel.Notice); + Program.DeprecationManager.Warn(manifest.Name, $"{nameof(Mod)}.{nameof(Mod.Entry)}({nameof(ModHelper)}) instead of {nameof(Mod)}.{nameof(Mod.Entry)}({nameof(IModHelper)})", "1.1", DeprecationLevel.Info); } catch (Exception ex) { -- cgit