summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/GlobalAssemblyInfo.cs4
-rw-r--r--src/StardewModdingAPI.Installer/InteractiveInstaller.cs6
-rw-r--r--src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj6
-rw-r--r--src/StardewModdingAPI/Constants.cs14
-rw-r--r--src/StardewModdingAPI/Framework/AssemblyRewriting/CacheEntry.cs2
-rw-r--r--src/StardewModdingAPI/Framework/ModAssemblyLoader.cs4
-rw-r--r--src/StardewModdingAPI/Framework/ModRegistry.cs18
-rw-r--r--src/StardewModdingAPI/Framework/Models/GitRelease.cs (renamed from src/StardewModdingAPI/Framework/GitRelease.cs)2
-rw-r--r--src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs47
-rw-r--r--src/StardewModdingAPI/Framework/Models/UserSettings.cs15
-rw-r--r--src/StardewModdingAPI/Framework/Reflection/CacheEntry.cs30
-rw-r--r--src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs34
-rw-r--r--src/StardewModdingAPI/Framework/UpdateHelper.cs1
-rw-r--r--src/StardewModdingAPI/Framework/UserSettings.cs9
-rw-r--r--src/StardewModdingAPI/IManifest.cs27
-rw-r--r--src/StardewModdingAPI/IMod.cs26
-rw-r--r--src/StardewModdingAPI/ISemanticVersion.cs38
-rw-r--r--src/StardewModdingAPI/Inheritance/SGame.cs12
-rw-r--r--src/StardewModdingAPI/Inheritance/SObject.cs2
-rw-r--r--src/StardewModdingAPI/LogWriter.cs2
-rw-r--r--src/StardewModdingAPI/Manifest.cs60
-rw-r--r--src/StardewModdingAPI/Mod.cs17
-rw-r--r--src/StardewModdingAPI/Program.cs156
-rw-r--r--src/StardewModdingAPI/SemanticVersion.cs171
-rw-r--r--src/StardewModdingAPI/StardewModdingAPI-settings.json4
-rw-r--r--src/StardewModdingAPI/StardewModdingAPI.config.json4
-rw-r--r--src/StardewModdingAPI/StardewModdingAPI.csproj17
-rw-r--r--src/StardewModdingAPI/StardewModdingAPI.data.json41
-rw-r--r--src/StardewModdingAPI/Version.cs116
29 files changed, 700 insertions, 185 deletions
diff --git a/src/GlobalAssemblyInfo.cs b/src/GlobalAssemblyInfo.cs
index 0dfb42bb..7f1fa401 100644
--- a/src/GlobalAssemblyInfo.cs
+++ b/src/GlobalAssemblyInfo.cs
@@ -2,5 +2,5 @@
using System.Runtime.InteropServices;
[assembly: ComVisible(false)]
-[assembly: AssemblyVersion("1.4.0.0")]
-[assembly: AssemblyFileVersion("1.4.0.0")] \ No newline at end of file
+[assembly: AssemblyVersion("1.5.0.0")]
+[assembly: AssemblyFileVersion("1.5.0.0")] \ No newline at end of file
diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs
index 4cef1a12..5f89caf2 100644
--- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs
+++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs
@@ -55,7 +55,8 @@ namespace StardewModdingApi.Installer
{
// common
"StardewModdingAPI.exe",
- "StardewModdingAPI-settings.json",
+ "StardewModdingAPI.config.json",
+ "StardewModdingAPI.data.json",
"StardewModdingAPI.AssemblyRewriters.dll",
"steam_appid.txt",
@@ -72,7 +73,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..4e4872b6 100644
--- a/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj
+++ b/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj
@@ -73,7 +73,8 @@
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.exe" DestinationFolder="$(CompiledInstallerPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.exe.mdb" DestinationFolder="$(CompiledInstallerPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.AssemblyRewriters.dll" DestinationFolder="$(CompiledInstallerPath)\Mono" />
- <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI-settings.json" DestinationFolder="$(CompiledInstallerPath)\Mono" />
+ <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.config.json" DestinationFolder="$(CompiledInstallerPath)\Mono" />
+ <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.data.json" DestinationFolder="$(CompiledInstallerPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\System.Numerics.dll" DestinationFolder="$(CompiledInstallerPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\System.Runtime.Caching.dll" DestinationFolder="$(CompiledInstallerPath)\Mono" />
<Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\unix-launcher.sh" DestinationFiles="$(CompiledInstallerPath)\Mono\StardewModdingAPI" />
@@ -87,7 +88,8 @@
<Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.pdb" DestinationFolder="$(CompiledInstallerPath)\Windows" />
<Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.xml" DestinationFolder="$(CompiledInstallerPath)\Windows" />
<Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.AssemblyRewriters.dll" DestinationFolder="$(CompiledInstallerPath)\Windows" />
- <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI-settings.json" DestinationFolder="$(CompiledInstallerPath)\Windows" />
+ <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.config.json" DestinationFolder="$(CompiledInstallerPath)\Windows" />
+ <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.data.json" DestinationFolder="$(CompiledInstallerPath)\Windows" />
<Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\steam_appid.txt" DestinationFolder="$(CompiledInstallerPath)\Windows" />
<Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="@(CompiledMods)" DestinationFolder="$(CompiledInstallerPath)\Windows\Mods\%(RecursiveDir)" />
</Target>
diff --git a/src/StardewModdingAPI/Constants.cs b/src/StardewModdingAPI/Constants.cs
index f5b9e70a..a79fd382 100644
--- a/src/StardewModdingAPI/Constants.cs
+++ b/src/StardewModdingAPI/Constants.cs
@@ -26,7 +26,11 @@ namespace StardewModdingAPI
** Accessors
*********/
/// <summary>SMAPI's current semantic version.</summary>
- public static readonly Version Version = new Version(1, 4, 0, null);
+ [Obsolete("Use " + nameof(Constants) + "." + nameof(ApiVersion))]
+ public static readonly Version Version = (Version)Constants.ApiVersion;
+
+ /// <summary>SMAPI's current semantic version.</summary>
+ public static ISemanticVersion ApiVersion => new Version(1, 5, 0, null, suppressDeprecationWarning: true);
/// <summary>The minimum supported version of Stardew Valley.</summary>
public const string MinimumGameVersion = "1.1";
@@ -56,7 +60,7 @@ namespace StardewModdingAPI
public static string ExecutionPath => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
/// <summary>The title of the SMAPI console window.</summary>
- public static string ConsoleTitle => $"Stardew Modding API Console - Version {Constants.Version} - Mods Loaded: {Program.ModsLoaded}";
+ public static string ConsoleTitle => $"Stardew Modding API Console - Version {Constants.ApiVersion} - Mods Loaded: {Program.ModsLoaded}";
/// <summary>The directory path in which error logs should be stored.</summary>
public static string LogDir => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley", "ErrorLogs");
@@ -64,6 +68,12 @@ namespace StardewModdingAPI
/// <summary>The file path to the error log where the latest output should be saved.</summary>
public static string LogPath => Path.Combine(Constants.LogDir, "MODDED_ProgramLog.Log_LATEST.txt");
+ /// <summary>The file path for the SMAPI configuration file.</summary>
+ internal static string ApiConfigPath => Path.Combine(Constants.ExecutionPath, $"{typeof(Program).Assembly.GetName().Name}.config.json");
+
+ /// <summary>The file path for the SMAPI data file containing metadata about known mods.</summary>
+ internal static string ApiModMetadataPath => Path.Combine(Constants.ExecutionPath, $"{typeof(Program).Assembly.GetName().Name}.data.json");
+
/*********
** Protected methods
diff --git a/src/StardewModdingAPI/Framework/AssemblyRewriting/CacheEntry.cs b/src/StardewModdingAPI/Framework/AssemblyRewriting/CacheEntry.cs
index 3dfbc78c..a747eaa8 100644
--- a/src/StardewModdingAPI/Framework/AssemblyRewriting/CacheEntry.cs
+++ b/src/StardewModdingAPI/Framework/AssemblyRewriting/CacheEntry.cs
@@ -36,7 +36,7 @@ namespace StardewModdingAPI.Framework.AssemblyRewriting
/// <param name="paths">The paths for the cached assembly.</param>
/// <param name="hash">The MD5 hash of the original assembly.</param>
/// <param name="currentVersion">The current SMAPI version.</param>
- public bool IsUpToDate(CachePaths paths, string hash, Version currentVersion)
+ public bool IsUpToDate(CachePaths paths, string hash, ISemanticVersion currentVersion)
{
return hash == this.Hash
&& this.ApiVersion == currentVersion.ToString()
diff --git a/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs b/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs
index 1ceb8ad2..a2c4ac23 100644
--- a/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs
+++ b/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs
@@ -58,7 +58,7 @@ namespace StardewModdingAPI.Framework
CachePaths cachePaths = this.GetCachePaths(assemblyPath);
{
CacheEntry cacheEntry = File.Exists(cachePaths.Metadata) ? JsonConvert.DeserializeObject<CacheEntry>(File.ReadAllText(cachePaths.Metadata)) : null;
- if (cacheEntry != null && cacheEntry.IsUpToDate(cachePaths, hash, Constants.Version))
+ if (cacheEntry != null && cacheEntry.IsUpToDate(cachePaths, hash, Constants.ApiVersion))
return new RewriteResult(assemblyPath, cachePaths, assemblyBytes, cacheEntry.Hash, cacheEntry.UseCachedAssembly, isNewerThanCache: false); // no rewrite needed
}
this.Monitor.Log($"Preprocessing {Path.GetFileName(assemblyPath)} for compatibility...", LogLevel.Trace);
@@ -99,7 +99,7 @@ namespace StardewModdingAPI.Framework
// cache all results
foreach (RewriteResult result in results)
{
- CacheEntry cacheEntry = new CacheEntry(result.Hash, Constants.Version.ToString(), forceCacheAssemblies || result.UseCachedAssembly);
+ CacheEntry cacheEntry = new CacheEntry(result.Hash, Constants.ApiVersion.ToString(), forceCacheAssemblies || result.UseCachedAssembly);
File.WriteAllText(result.CachePaths.Metadata, JsonConvert.SerializeObject(cacheEntry));
if (forceCacheAssemblies || result.UseCachedAssembly)
File.WriteAllBytes(result.CachePaths.Assembly, result.AssemblyBytes);
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
*********/
+ /// <summary>The registered mod data.</summary>
+ private readonly List<IMod> Mods = new List<IMod>();
+
/// <summary>The friendly mod names treated as deprecation warning sources (assembly full name => mod name).</summary>
private readonly IDictionary<string, string> ModNamesByAssembly = new Dictionary<string, string>();
@@ -19,11 +23,17 @@ namespace StardewModdingAPI.Framework
** Public methods
*********/
/// <summary>Register a mod as a possible source of deprecation warnings.</summary>
- /// <param name="manifest">The mod manifest.</param>
- /// <param name="assembly">The mod assembly.</param>
- public void Add(Manifest manifest, Assembly assembly)
+ /// <param name="mod">The mod instance.</param>
+ public void Add(IMod mod)
+ {
+ this.Mods.Add(mod);
+ this.ModNamesByAssembly[mod.GetType().Assembly.FullName] = mod.ModManifest.Name;
+ }
+
+ /// <summary>Get all enabled mods.</summary>
+ public IEnumerable<IMod> GetMods()
{
- this.ModNamesByAssembly[assembly.FullName] = manifest.Name;
+ return (from mod in this.Mods select mod);
}
/// <summary>Get the friendly name for the closest assembly registered as a source of deprecation warnings.</summary>
diff --git a/src/StardewModdingAPI/Framework/GitRelease.cs b/src/StardewModdingAPI/Framework/Models/GitRelease.cs
index 0da57efd..bc53468f 100644
--- a/src/StardewModdingAPI/Framework/GitRelease.cs
+++ b/src/StardewModdingAPI/Framework/Models/GitRelease.cs
@@ -1,6 +1,6 @@
using Newtonsoft.Json;
-namespace StardewModdingAPI.Framework
+namespace StardewModdingAPI.Framework.Models
{
/// <summary>Metadata about a GitHub release tag.</summary>
internal class GitRelease
diff --git a/src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs b/src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs
new file mode 100644
index 00000000..9bf06552
--- /dev/null
+++ b/src/StardewModdingAPI/Framework/Models/IncompatibleMod.cs
@@ -0,0 +1,47 @@
+using System.Text.RegularExpressions;
+
+namespace StardewModdingAPI.Framework.Models
+{
+ /// <summary>Contains abstract metadata about an incompatible mod.</summary>
+ internal class IncompatibleMod
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The unique mod ID.</summary>
+ public string ID { get; set; }
+
+ /// <summary>The mod name.</summary>
+ public string Name { get; set; }
+
+ /// <summary>The most recent incompatible mod version.</summary>
+ public string Version { get; set; }
+
+ /// <summary>The URL the user can check for an official updated version.</summary>
+ public string UpdateUrl { get; set; }
+
+ /// <summary>The URL the user can check for an unofficial updated version.</summary>
+ public string UnofficialUpdateUrl { get; set; }
+
+ /// <summary>A regular expression matching version strings to consider compatible, even if they technically precede <see cref="Version"/>.</summary>
+ public string ForceCompatibleVersion { get; set; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Get whether the specified version is compatible according to this metadata.</summary>
+ /// <param name="version">The current version of the matching mod.</param>
+ 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/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
+{
+ /// <summary>Contains user settings from SMAPI's JSON configuration file.</summary>
+ internal class UserSettings
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>Whether to enable development features.</summary>
+ public bool DeveloperMode { get; set; }
+
+ /// <summary>Whether to check if a newer version of SMAPI is available on startup.</summary>
+ public bool CheckForUpdates { get; set; } = true;
+ }
+}
diff --git a/src/StardewModdingAPI/Framework/Reflection/CacheEntry.cs b/src/StardewModdingAPI/Framework/Reflection/CacheEntry.cs
new file mode 100644
index 00000000..30faca37
--- /dev/null
+++ b/src/StardewModdingAPI/Framework/Reflection/CacheEntry.cs
@@ -0,0 +1,30 @@
+using System.Reflection;
+
+namespace StardewModdingAPI.Framework.Reflection
+{
+ /// <summary>A cached member reflection result.</summary>
+ internal struct CacheEntry
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>Whether the lookup found a valid match.</summary>
+ public bool IsValid;
+
+ /// <summary>The reflection data for this member (or <c>null</c> if invalid).</summary>
+ public MemberInfo MemberInfo;
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="isValid">Whether the lookup found a valid match.</param>
+ /// <param name="memberInfo">The reflection data for this member (or <c>null</c> if invalid).</param>
+ public CacheEntry(bool isValid, MemberInfo memberInfo)
+ {
+ this.IsValid = isValid;
+ this.MemberInfo = memberInfo;
+ }
+ }
+}
diff --git a/src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs b/src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs
index 38b4e357..edf59b81 100644
--- a/src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs
+++ b/src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs
@@ -67,10 +67,17 @@ namespace StardewModdingAPI.Framework.Reflection
/// <param name="obj">The object which has the field.</param>
/// <param name="name">The field name.</param>
/// <param name="required">Whether to throw an exception if the private field is not found.</param>
- /// <remarks>This is a shortcut for <see cref="GetPrivateField{TValue}(object,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>.</remarks>
+ /// <returns>Returns the field value, or the default value for <typeparamref name="TValue"/> if the field wasn't found and <paramref name="required"/> is false.</returns>
+ /// <remarks>
+ /// This is a shortcut for <see cref="GetPrivateField{TValue}(object,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>.
+ /// When <paramref name="required" /> is false, this will return the default value if reflection fails. If you need to check whether the field exists, use <see cref="GetPrivateField{TValue}(object,string,bool)" /> instead.
+ /// </remarks>
public TValue GetPrivateValue<TValue>(object obj, string name, bool required = true)
{
- return this.GetPrivateField<TValue>(obj, name, required).GetValue();
+ IPrivateField<TValue> field = this.GetPrivateField<TValue>(obj, name, required);
+ return field != null
+ ? field.GetValue()
+ : default(TValue);
}
/// <summary>Get the value of a private static field.</summary>
@@ -78,10 +85,17 @@ namespace StardewModdingAPI.Framework.Reflection
/// <param name="type">The type which has the field.</param>
/// <param name="name">The field name.</param>
/// <param name="required">Whether to throw an exception if the private field is not found.</param>
- /// <remarks>This is a shortcut for <see cref="GetPrivateField{TValue}(Type,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>.</remarks>
+ /// <returns>Returns the field value, or the default value for <typeparamref name="TValue"/> if the field wasn't found and <paramref name="required"/> is false.</returns>
+ /// <remarks>
+ /// This is a shortcut for <see cref="GetPrivateField{TValue}(Type,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>.
+ /// When <paramref name="required" /> is false, this will return the default value if reflection fails. If you need to check whether the field exists, use <see cref="GetPrivateField{TValue}(Type,string,bool)" /> instead.
+ /// </remarks>
public TValue GetPrivateValue<TValue>(Type type, string name, bool required = true)
{
- return this.GetPrivateField<TValue>(type, name, required).GetValue();
+ IPrivateField<TValue> field = this.GetPrivateField<TValue>(type, name, required);
+ return field != null
+ ? field.GetValue()
+ : default(TValue);
}
/****
@@ -228,12 +242,18 @@ namespace StardewModdingAPI.Framework.Reflection
{
// get from cache
if (this.Cache.Contains(key))
- return (TMemberInfo)this.Cache[key];
+ {
+ CacheEntry entry = (CacheEntry)this.Cache[key];
+ return entry.IsValid
+ ? (TMemberInfo)entry.MemberInfo
+ : default(TMemberInfo);
+ }
// fetch & cache new value
TMemberInfo result = fetch();
- this.Cache.Add(key, result, new CacheItemPolicy { SlidingExpiration = this.SlidingCacheExpiry });
+ CacheEntry cacheEntry = new CacheEntry(result != null, result);
+ this.Cache.Add(key, cacheEntry, new CacheItemPolicy { SlidingExpiration = this.SlidingCacheExpiry });
return result;
}
}
-} \ No newline at end of file
+}
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 199d19b3..00000000
--- a/src/StardewModdingAPI/Framework/UserSettings.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace StardewModdingAPI.Framework
-{
- /// <summary>Contains user settings from SMAPI's JSON configuration file.</summary>
- internal class UserSettings
- {
- /// <summary>Whether to enable development features.</summary>
- public bool DeveloperMode { get; set; }
- }
-}
diff --git a/src/StardewModdingAPI/IManifest.cs b/src/StardewModdingAPI/IManifest.cs
new file mode 100644
index 00000000..3e4b7513
--- /dev/null
+++ b/src/StardewModdingAPI/IManifest.cs
@@ -0,0 +1,27 @@
+namespace StardewModdingAPI
+{
+ /// <summary>A manifest which describes a mod for SMAPI.</summary>
+ public interface IManifest
+ {
+ /// <summary>The mod name.</summary>
+ string Name { get; set; }
+
+ /// <summary>A brief description of the mod.</summary>
+ string Description { get; set; }
+
+ /// <summary>The mod author's name.</summary>
+ string Author { get; }
+
+ /// <summary>The mod version.</summary>
+ ISemanticVersion Version { get; set; }
+
+ /// <summary>The minimum SMAPI version required by this mod, if any.</summary>
+ string MinimumApiVersion { get; set; }
+
+ /// <summary>The unique mod ID.</summary>
+ string UniqueID { get; set; }
+
+ /// <summary>The name of the DLL in the directory that has the <see cref="Mod.Entry"/> method.</summary>
+ string EntryDll { get; set; }
+ }
+} \ No newline at end of file
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
+{
+ /// <summary>The implementation for a Stardew Valley mod.</summary>
+ public interface IMod
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>Provides simplified APIs for writing mods.</summary>
+ IModHelper Helper { get; }
+
+ /// <summary>Writes messages to the console and log file.</summary>
+ IMonitor Monitor { get; }
+
+ /// <summary>The mod's manifest.</summary>
+ IManifest ModManifest { get; }
+
+
+ /*********
+ ** 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>
+ void Entry(IModHelper helper);
+ }
+} \ No newline at end of file
diff --git a/src/StardewModdingAPI/ISemanticVersion.cs b/src/StardewModdingAPI/ISemanticVersion.cs
new file mode 100644
index 00000000..3b9bdb44
--- /dev/null
+++ b/src/StardewModdingAPI/ISemanticVersion.cs
@@ -0,0 +1,38 @@
+using System;
+
+namespace StardewModdingAPI
+{
+ /// <summary>A semantic version with an optional release tag.</summary>
+ public interface ISemanticVersion : IComparable<ISemanticVersion>
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The major version incremented for major API changes.</summary>
+ int MajorVersion { get; }
+
+ /// <summary>The minor version incremented for backwards-compatible changes.</summary>
+ int MinorVersion { get; }
+
+ /// <summary>The patch version for backwards-compatible bug fixes.</summary>
+ int PatchVersion { get; }
+
+ /// <summary>An optional build tag.</summary>
+ string Build { get; }
+
+
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>Get whether this version is older than the specified version.</summary>
+ /// <param name="other">The version to compare with this instance.</param>
+ bool IsOlderThan(ISemanticVersion other);
+
+ /// <summary>Get whether this version is newer than the specified version.</summary>
+ /// <param name="other">The version to compare with this instance.</param>
+ bool IsNewerThan(ISemanticVersion other);
+
+ /// <summary>Get a string representation of the version.</summary>
+ string ToString();
+ }
+} \ No newline at end of file
diff --git a/src/StardewModdingAPI/Inheritance/SGame.cs b/src/StardewModdingAPI/Inheritance/SGame.cs
index f70d0696..16803a73 100644
--- a/src/StardewModdingAPI/Inheritance/SGame.cs
+++ b/src/StardewModdingAPI/Inheritance/SGame.cs
@@ -913,11 +913,17 @@ namespace StardewModdingAPI.Inheritance
// raise menu changed
if (Game1.activeClickableMenu != this.PreviousActiveMenu)
{
+ // raise events
+ IClickableMenu previousMenu = this.PreviousActiveMenu;
+ IClickableMenu newMenu = Game1.activeClickableMenu;
if (Game1.activeClickableMenu != null)
- MenuEvents.InvokeMenuChanged(this.Monitor, this.PreviousActiveMenu, Game1.activeClickableMenu);
+ MenuEvents.InvokeMenuChanged(this.Monitor, previousMenu, newMenu);
else
- MenuEvents.InvokeMenuClosed(this.Monitor, this.PreviousActiveMenu);
- this.PreviousActiveMenu = Game1.activeClickableMenu;
+ MenuEvents.InvokeMenuClosed(this.Monitor, previousMenu);
+
+ // update previous menu
+ // (if the menu was changed in one of the handlers, deliberately defer detection until the next update so mods can be notified of the new menu change)
+ this.PreviousActiveMenu = newMenu;
}
// raise location list changed
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
/// <summary>Raise a deprecation warning.</summary>
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/Manifest.cs b/src/StardewModdingAPI/Manifest.cs
index bfc66c43..018b31ae 100644
--- a/src/StardewModdingAPI/Manifest.cs
+++ b/src/StardewModdingAPI/Manifest.cs
@@ -3,21 +3,52 @@ using Newtonsoft.Json;
namespace StardewModdingAPI
{
+ /// <summary>Wraps <see cref="Manifest"/> so it can implement <see cref="IManifest"/> without breaking backwards compatibility.</summary>
+ [Obsolete("Use " + nameof(IManifest) + " or " + nameof(Mod) + "." + nameof(Mod.ModManifest) + " instead")]
+ internal class ManifestImpl : Manifest, IManifest
+ {
+ /// <summary>The mod version.</summary>
+ public new ISemanticVersion Version
+ {
+ get { return base.Version; }
+ set { base.Version = (Version)value; }
+ }
+ }
+
/// <summary>A manifest which describes a mod for SMAPI.</summary>
public class Manifest
{
/*********
** Accessors
*********/
- /// <summary>Whether the manifest defined the deprecated <see cref="Authour"/> field.</summary>
- [JsonIgnore]
- internal bool UsedAuthourField { get; private set; }
-
/// <summary>The mod name.</summary>
- public virtual string Name { get; set; } = "";
+ public string Name { get; set; }
+
+ /// <summary>A brief description of the mod.</summary>
+ public string Description { get; set; }
/// <summary>The mod author's name.</summary>
- public virtual string Author { get; set; } = "";
+ public string Author { get; set; }
+
+ /// <summary>The mod version.</summary>
+ public Version Version { get; set; } = new Version(0, 0, 0, "", suppressDeprecationWarning: true);
+
+ /// <summary>The minimum SMAPI version required by this mod, if any.</summary