Merge branch 'develop' of https://github.com/Pathoschild/SMAPI into develop
Conflicts: src/SMAPI/Framework/SCore.cs
This commit is contained in:
commit
f5eaf8d27a
|
@ -12,6 +12,7 @@
|
|||
* Added heuristic compatibility rewrites, which fix some mods previously incompatible with Android or newer game versions.
|
||||
* Tweaked the rules for showing update alerts (see _for SMAPI developers_ below for details).
|
||||
* Fixed crossplatform compatibility for mods which use the `[HarmonyPatch(type)]` attribute (thanks to spacechase0!).
|
||||
* Fixed map tile rotation broken when you return to the title screen and reload a save.
|
||||
* Fixed broken URL in update alerts for unofficial versions.
|
||||
* Fixed rare error when a mod adds/removes event handlers asynchronously.
|
||||
* Fixed rare issue where the console showed incorrect colors when mods wrote to it asynchronously.
|
||||
|
|
|
@ -25,22 +25,22 @@ namespace StardewModdingAPI.Toolkit
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The major version incremented for major API changes.</summary>
|
||||
/// <inheritdoc />
|
||||
public int MajorVersion { get; }
|
||||
|
||||
/// <summary>The minor version incremented for backwards-compatible changes.</summary>
|
||||
/// <inheritdoc />
|
||||
public int MinorVersion { get; }
|
||||
|
||||
/// <summary>The patch version for backwards-compatible bug fixes.</summary>
|
||||
/// <inheritdoc />
|
||||
public int PatchVersion { get; }
|
||||
|
||||
/// <summary>The platform release. This is a non-standard semver extension used by Stardew Valley on ported platforms to represent platform-specific patches to a ported version, represented as a fourth number in the version string.</summary>
|
||||
public int PlatformRelease { get; }
|
||||
|
||||
/// <summary>An optional prerelease tag.</summary>
|
||||
/// <inheritdoc />
|
||||
public string PrereleaseTag { get; }
|
||||
|
||||
/// <summary>Optional build metadata. This is ignored when determining version precedence.</summary>
|
||||
/// <inheritdoc />
|
||||
public string BuildMetadata { get; }
|
||||
|
||||
|
||||
|
@ -103,9 +103,7 @@ namespace StardewModdingAPI.Toolkit
|
|||
this.AssertValid();
|
||||
}
|
||||
|
||||
/// <summary>Get an integer indicating whether this version precedes (less than 0), supersedes (more than 0), or is equivalent to (0) the specified version.</summary>
|
||||
/// <param name="other">The version to compare with this instance.</param>
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="other"/> value is null.</exception>
|
||||
/// <inheritdoc />
|
||||
public int CompareTo(ISemanticVersion other)
|
||||
{
|
||||
if (other == null)
|
||||
|
@ -113,68 +111,55 @@ namespace StardewModdingAPI.Toolkit
|
|||
return this.CompareTo(other.MajorVersion, other.MinorVersion, other.PatchVersion, (other as SemanticVersion)?.PlatformRelease ?? 0, other.PrereleaseTag);
|
||||
}
|
||||
|
||||
/// <summary>Indicates whether the current object is equal to another object of the same type.</summary>
|
||||
/// <returns>true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false.</returns>
|
||||
/// <param name="other">An object to compare with this object.</param>
|
||||
/// <inheritdoc />
|
||||
public bool Equals(ISemanticVersion other)
|
||||
{
|
||||
return other != null && this.CompareTo(other) == 0;
|
||||
}
|
||||
|
||||
/// <summary>Whether this is a prerelease version.</summary>
|
||||
/// <inheritdoc />
|
||||
public bool IsPrerelease()
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(this.PrereleaseTag);
|
||||
}
|
||||
|
||||
/// <summary>Get whether this version is older than the specified version.</summary>
|
||||
/// <param name="other">The version to compare with this instance.</param>
|
||||
/// <inheritdoc />
|
||||
public bool IsOlderThan(ISemanticVersion other)
|
||||
{
|
||||
return this.CompareTo(other) < 0;
|
||||
}
|
||||
|
||||
/// <summary>Get whether this version is older than the specified version.</summary>
|
||||
/// <param name="other">The version to compare with this instance.</param>
|
||||
/// <exception cref="FormatException">The specified version is not a valid semantic version.</exception>
|
||||
/// <inheritdoc />
|
||||
public bool IsOlderThan(string other)
|
||||
{
|
||||
return this.IsOlderThan(new SemanticVersion(other, allowNonStandard: true));
|
||||
}
|
||||
|
||||
/// <summary>Get whether this version is newer than the specified version.</summary>
|
||||
/// <param name="other">The version to compare with this instance.</param>
|
||||
/// <inheritdoc />
|
||||
public bool IsNewerThan(ISemanticVersion other)
|
||||
{
|
||||
return this.CompareTo(other) > 0;
|
||||
}
|
||||
|
||||
/// <summary>Get whether this version is newer than the specified version.</summary>
|
||||
/// <param name="other">The version to compare with this instance.</param>
|
||||
/// <exception cref="FormatException">The specified version is not a valid semantic version.</exception>
|
||||
/// <inheritdoc />
|
||||
public bool IsNewerThan(string other)
|
||||
{
|
||||
return this.IsNewerThan(new SemanticVersion(other, allowNonStandard: true));
|
||||
}
|
||||
|
||||
/// <summary>Get whether this version is between two specified versions (inclusively).</summary>
|
||||
/// <param name="min">The minimum version.</param>
|
||||
/// <param name="max">The maximum version.</param>
|
||||
/// <inheritdoc />
|
||||
public bool IsBetween(ISemanticVersion min, ISemanticVersion max)
|
||||
{
|
||||
return this.CompareTo(min) >= 0 && this.CompareTo(max) <= 0;
|
||||
}
|
||||
|
||||
/// <summary>Get whether this version is between two specified versions (inclusively).</summary>
|
||||
/// <param name="min">The minimum version.</param>
|
||||
/// <param name="max">The maximum version.</param>
|
||||
/// <exception cref="FormatException">One of the specified versions is not a valid semantic version.</exception>
|
||||
/// <inheritdoc />
|
||||
public bool IsBetween(string min, string max)
|
||||
{
|
||||
return this.IsBetween(new SemanticVersion(min, allowNonStandard: true), new SemanticVersion(max, allowNonStandard: true));
|
||||
}
|
||||
|
||||
/// <summary>Get a string representation of the version.</summary>
|
||||
/// <inheritdoc cref="ISemanticVersion.ToString" />
|
||||
public override string ToString()
|
||||
{
|
||||
string version = $"{this.MajorVersion}.{this.MinorVersion}.{this.PatchVersion}";
|
||||
|
@ -187,7 +172,7 @@ namespace StardewModdingAPI.Toolkit
|
|||
return version;
|
||||
}
|
||||
|
||||
/// <summary>Whether the version uses non-standard extensions, like four-part game versions on some platforms.</summary>
|
||||
/// <inheritdoc />
|
||||
public bool IsNonStandard()
|
||||
{
|
||||
return this.PlatformRelease != 0;
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace StardewModdingAPI.Framework.Content
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The content data being read.</summary>
|
||||
/// <inheritdoc />
|
||||
public TValue Data { get; protected set; }
|
||||
|
||||
|
||||
|
@ -36,10 +36,7 @@ namespace StardewModdingAPI.Framework.Content
|
|||
this.OnDataReplaced = onDataReplaced;
|
||||
}
|
||||
|
||||
/// <summary>Replace the entire content value with the given value. This is generally not recommended, since it may break compatibility with other mods or different versions of the game.</summary>
|
||||
/// <param name="value">The new content value.</param>
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="value"/> is null.</exception>
|
||||
/// <exception cref="InvalidCastException">The <paramref name="value"/>'s type is not compatible with the loaded asset's type.</exception>
|
||||
/// <inheritdoc />
|
||||
public void ReplaceWith(TValue value)
|
||||
{
|
||||
if (value == null)
|
||||
|
|
|
@ -28,13 +28,7 @@ namespace StardewModdingAPI.Framework.Content
|
|||
public AssetDataForImage(string locale, string assetName, Texture2D data, Func<string, string> getNormalizedPath, Action<Texture2D> onDataReplaced)
|
||||
: base(locale, assetName, data, getNormalizedPath, onDataReplaced) { }
|
||||
|
||||
/// <summary>Overwrite part of the image.</summary>
|
||||
/// <param name="source">The image to patch into the content.</param>
|
||||
/// <param name="sourceArea">The part of the <paramref name="source"/> to copy (or <c>null</c> to take the whole texture). This must be within the bounds of the <paramref name="source"/> texture.</param>
|
||||
/// <param name="targetArea">The part of the content to patch (or <c>null</c> to patch the whole texture). The original content within this area will be erased. This must be within the bounds of the existing spritesheet.</param>
|
||||
/// <param name="patchMode">Indicates how an image should be patched.</param>
|
||||
/// <exception cref="ArgumentNullException">One of the arguments is null.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">The <paramref name="targetArea"/> is outside the bounds of the spritesheet.</exception>
|
||||
/// <inheritdoc />
|
||||
public void PatchImage(Texture2D source, Rectangle? sourceArea = null, Rectangle? targetArea = null, PatchMode patchMode = PatchMode.Replace)
|
||||
{
|
||||
// get texture
|
||||
|
@ -104,10 +98,7 @@ namespace StardewModdingAPI.Framework.Content
|
|||
target.SetData(0, targetArea, sourceData, 0, pixelCount);
|
||||
}
|
||||
|
||||
/// <summary>Extend the image if needed to fit the given size. Note that this is an expensive operation, creates a new texture instance, and that extending a spritesheet horizontally may cause game errors or bugs.</summary>
|
||||
/// <param name="minWidth">The minimum texture width.</param>
|
||||
/// <param name="minHeight">The minimum texture height.</param>
|
||||
/// <returns>Whether the texture was resized.</returns>
|
||||
/// <inheritdoc />
|
||||
public bool ExtendImage(int minWidth, int minHeight)
|
||||
{
|
||||
if (this.Data.Width >= minWidth && this.Data.Height >= minHeight)
|
||||
|
|
|
@ -24,10 +24,7 @@ namespace StardewModdingAPI.Framework.Content
|
|||
public AssetDataForMap(string locale, string assetName, Map data, Func<string, string> getNormalizedPath, Action<Map> onDataReplaced)
|
||||
: base(locale, assetName, data, getNormalizedPath, onDataReplaced) { }
|
||||
|
||||
/// <summary>Copy layers, tiles, and tilesheets from another map onto the asset.</summary>
|
||||
/// <param name="source">The map from which to copy.</param>
|
||||
/// <param name="sourceArea">The tile area within the source map to copy, or <c>null</c> for the entire source map size. This must be within the bounds of the <paramref name="source"/> map.</param>
|
||||
/// <param name="targetArea">The tile area within the target map to overwrite, or <c>null</c> to patch the whole map. The original content within this area will be erased. This must be within the bounds of the existing map.</param>
|
||||
/// <inheritdoc />
|
||||
/// <remarks>Derived from <see cref="StardewValley.GameLocation.ApplyMapOverride"/> with a few changes:
|
||||
/// - can be applied directly to the maps when loading, before the location is created;
|
||||
/// - added support for source/target areas;
|
||||
|
|
|
@ -26,32 +26,25 @@ namespace StardewModdingAPI.Framework.Content
|
|||
public AssetDataForObject(IAssetInfo info, object data, Func<string, string> getNormalizedPath)
|
||||
: this(info.Locale, info.AssetName, data, getNormalizedPath) { }
|
||||
|
||||
/// <summary>Get a helper to manipulate the data as a dictionary.</summary>
|
||||
/// <typeparam name="TKey">The expected dictionary key.</typeparam>
|
||||
/// <typeparam name="TValue">The expected dictionary balue.</typeparam>
|
||||
/// <exception cref="InvalidOperationException">The content being read isn't a dictionary.</exception>
|
||||
/// <inheritdoc />
|
||||
public IAssetDataForDictionary<TKey, TValue> AsDictionary<TKey, TValue>()
|
||||
{
|
||||
return new AssetDataForDictionary<TKey, TValue>(this.Locale, this.AssetName, this.GetData<IDictionary<TKey, TValue>>(), this.GetNormalizedPath, this.ReplaceWith);
|
||||
}
|
||||
|
||||
/// <summary>Get a helper to manipulate the data as an image.</summary>
|
||||
/// <exception cref="InvalidOperationException">The content being read isn't an image.</exception>
|
||||
/// <inheritdoc />
|
||||
public IAssetDataForImage AsImage()
|
||||
{
|
||||
return new AssetDataForImage(this.Locale, this.AssetName, this.GetData<Texture2D>(), this.GetNormalizedPath, this.ReplaceWith);
|
||||
}
|
||||
|
||||
/// <summary>Get a helper to manipulate the data as a map.</summary>
|
||||
/// <exception cref="InvalidOperationException">The content being read isn't a map.</exception>
|
||||
/// <inheritdoc />
|
||||
public IAssetDataForMap AsMap()
|
||||
{
|
||||
return new AssetDataForMap(this.Locale, this.AssetName, this.GetData<Map>(), this.GetNormalizedPath, this.ReplaceWith);
|
||||
}
|
||||
|
||||
/// <summary>Get the data as a given type.</summary>
|
||||
/// <typeparam name="TData">The expected data type.</typeparam>
|
||||
/// <exception cref="InvalidCastException">The data can't be converted to <typeparamref name="TData"/>.</exception>
|
||||
/// <inheritdoc />
|
||||
public TData GetData<TData>()
|
||||
{
|
||||
if (!(this.Data is TData))
|
||||
|
|
|
@ -16,13 +16,13 @@ namespace StardewModdingAPI.Framework.Content
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The content's locale code, if the content is localized.</summary>
|
||||
/// <inheritdoc />
|
||||
public string Locale { get; }
|
||||
|
||||
/// <summary>The normalized asset name being read. The format may change between platforms; see <see cref="AssetNameEquals"/> to compare with a known path.</summary>
|
||||
/// <inheritdoc />
|
||||
public string AssetName { get; }
|
||||
|
||||
/// <summary>The content data type.</summary>
|
||||
/// <inheritdoc />
|
||||
public Type DataType { get; }
|
||||
|
||||
|
||||
|
@ -42,8 +42,7 @@ namespace StardewModdingAPI.Framework.Content
|
|||
this.GetNormalizedPath = getNormalizedPath;
|
||||
}
|
||||
|
||||
/// <summary>Get whether the asset name being loaded matches a given name after normalization.</summary>
|
||||
/// <param name="path">The expected asset path, relative to the game's content folder and without the .xnb extension or locale suffix (like 'Data\ObjectInformation').</param>
|
||||
/// <inheritdoc />
|
||||
public bool AssetNameEquals(string path)
|
||||
{
|
||||
path = this.GetNormalizedPath(path);
|
||||
|
|
|
@ -24,13 +24,13 @@ namespace StardewModdingAPI.Framework
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The full path to the content pack's folder.</summary>
|
||||
/// <inheritdoc />
|
||||
public string DirectoryPath { get; }
|
||||
|
||||
/// <summary>The content pack's manifest.</summary>
|
||||
/// <inheritdoc />
|
||||
public IManifest Manifest { get; }
|
||||
|
||||
/// <summary>Provides translations stored in the content pack's <c>i18n</c> folder. See <see cref="IModHelper.Translation"/> for more info.</summary>
|
||||
/// <inheritdoc />
|
||||
public ITranslationHelper Translation { get; }
|
||||
|
||||
|
||||
|
@ -52,8 +52,7 @@ namespace StardewModdingAPI.Framework
|
|||
this.JsonHelper = jsonHelper;
|
||||
}
|
||||
|
||||
/// <summary>Get whether a given file exists in the content pack.</summary>
|
||||
/// <param name="path">The file path to check.</param>
|
||||
/// <inheritdoc />
|
||||
public bool HasFile(string path)
|
||||
{
|
||||
this.AssertRelativePath(path, nameof(this.HasFile));
|
||||
|
@ -61,11 +60,7 @@ namespace StardewModdingAPI.Framework
|
|||
return File.Exists(Path.Combine(this.DirectoryPath, path));
|
||||
}
|
||||
|
||||
/// <summary>Read a JSON file from the content pack folder.</summary>
|
||||
/// <typeparam name="TModel">The model type.</typeparam>
|
||||
/// <param name="path">The file path relative to the content directory.</param>
|
||||
/// <returns>Returns the deserialized model, or <c>null</c> if the file doesn't exist or is empty.</returns>
|
||||
/// <exception cref="InvalidOperationException">The <paramref name="path"/> is not relative or contains directory climbing (../).</exception>
|
||||
/// <inheritdoc />
|
||||
public TModel ReadJsonFile<TModel>(string path) where TModel : class
|
||||
{
|
||||
this.AssertRelativePath(path, nameof(this.ReadJsonFile));
|
||||
|
@ -76,11 +71,7 @@ namespace StardewModdingAPI.Framework
|
|||
: null;
|
||||
}
|
||||
|
||||
/// <summary>Save data to a JSON file in the content pack's folder.</summary>
|
||||
/// <typeparam name="TModel">The model type. This should be a plain class that has public properties for the data you want. The properties can be complex types.</typeparam>
|
||||
/// <param name="path">The file path relative to the mod folder.</param>
|
||||
/// <param name="data">The arbitrary data to save.</param>
|
||||
/// <exception cref="InvalidOperationException">The <paramref name="path"/> is not relative or contains directory climbing (../).</exception>
|
||||
/// <inheritdoc />
|
||||
public void WriteJsonFile<TModel>(string path, TModel data) where TModel : class
|
||||
{
|
||||
this.AssertRelativePath(path, nameof(this.WriteJsonFile));
|
||||
|
@ -89,19 +80,13 @@ namespace StardewModdingAPI.Framework
|
|||
this.JsonHelper.WriteJsonFile(path, data);
|
||||
}
|
||||
|
||||
/// <summary>Load content from the content pack folder (if not already cached), and return it. When loading a <c>.png</c> file, this must be called outside the game's draw loop.</summary>
|
||||
/// <typeparam name="T">The expected data type. The main supported types are <see cref="Map"/>, <see cref="Texture2D"/>, and dictionaries; other types may be supported by the game's content pipeline.</typeparam>
|
||||
/// <param name="key">The local path to a content file relative to the content pack folder.</param>
|
||||
/// <exception cref="ArgumentException">The <paramref name="key"/> is empty or contains invalid characters.</exception>
|
||||
/// <exception cref="ContentLoadException">The content asset couldn't be loaded (e.g. because it doesn't exist).</exception>
|
||||
/// <inheritdoc />
|
||||
public T LoadAsset<T>(string key)
|
||||
{
|
||||
return this.Content.Load<T>(key, ContentSource.ModFolder);
|
||||
}
|
||||
|
||||
/// <summary>Get the underlying key in the game's content cache for an asset. This can be used to load custom map tilesheets, but should be avoided when you can use the content API instead. This does not validate whether the asset exists.</summary>
|
||||
/// <param name="key">The the local path to a content file relative to the content pack folder.</param>
|
||||
/// <exception cref="ArgumentException">The <paramref name="key"/> is empty or contains invalid characters.</exception>
|
||||
/// <inheritdoc />
|
||||
public string GetActualAssetKey(string key)
|
||||
{
|
||||
return this.Content.GetActualAssetKey(key, ContentSource.ModFolder);
|
||||
|
|
|
@ -8,16 +8,16 @@ namespace StardewModdingAPI.Framework
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The pixel position relative to the top-left corner of the in-game map, adjusted for pixel zoom.</summary>
|
||||
/// <inheritdoc />
|
||||
public Vector2 AbsolutePixels { get; }
|
||||
|
||||
/// <summary>The pixel position relative to the top-left corner of the visible screen, adjusted for pixel zoom.</summary>
|
||||
/// <inheritdoc />
|
||||
public Vector2 ScreenPixels { get; }
|
||||
|
||||
/// <summary>The tile position under the cursor relative to the top-left corner of the map.</summary>
|
||||
/// <inheritdoc />
|
||||
public Vector2 Tile { get; }
|
||||
|
||||
/// <summary>The tile position that the game considers under the cursor for purposes of clicking actions. This may be different than <see cref="Tile"/> if that's too far from the player.</summary>
|
||||
/// <inheritdoc />
|
||||
public Vector2 GrabTile { get; }
|
||||
|
||||
|
||||
|
@ -37,8 +37,7 @@ namespace StardewModdingAPI.Framework
|
|||
this.GrabTile = grabTile;
|
||||
}
|
||||
|
||||
/// <summary>Get whether the current object is equal to another object of the same type.</summary>
|
||||
/// <param name="other">An object to compare with this object.</param>
|
||||
/// <inheritdoc />
|
||||
public bool Equals(ICursorPosition other)
|
||||
{
|
||||
return other != null && this.AbsolutePixels == other.AbsolutePixels;
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace StardewModdingAPI.Framework
|
|||
public GameVersion(string version)
|
||||
: base(GameVersion.GetSemanticVersionString(version), allowNonStandard: true) { }
|
||||
|
||||
/// <summary>Get a string representation of the version.</summary>
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return GameVersion.GetGameVersionString(base.ToString());
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace StardewModdingAPI.Framework.ModHelpers
|
||||
namespace StardewModdingAPI.Framework.ModHelpers
|
||||
{
|
||||
/// <summary>The common base class for mod helpers.</summary>
|
||||
internal abstract class BaseHelper : IModLinked
|
||||
|
@ -6,7 +6,7 @@
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The unique ID of the mod for which the helper was created.</summary>
|
||||
/// <inheritdoc />
|
||||
public string ModID { get; }
|
||||
|
||||
|
||||
|
|
|
@ -28,23 +28,14 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
this.CommandManager = commandManager;
|
||||
}
|
||||
|
||||
/// <summary>Add a console command.</summary>
|
||||
/// <param name="name">The command name, which the user must type to trigger it.</param>
|
||||
/// <param name="documentation">The human-readable documentation shown when the player runs the built-in 'help' command.</param>
|
||||
/// <param name="callback">The method to invoke when the command is triggered. This method is passed the command name and arguments submitted by the user.</param>
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="name"/> or <paramref name="callback"/> is null or empty.</exception>
|
||||
/// <exception cref="FormatException">The <paramref name="name"/> is not a valid format.</exception>
|
||||
/// <exception cref="ArgumentException">There's already a command with that name.</exception>
|
||||
/// <inheritdoc />
|
||||
public ICommandHelper Add(string name, string documentation, Action<string, string[]> callback)
|
||||
{
|
||||
this.CommandManager.Add(this.Mod, name, documentation, callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Trigger a command.</summary>
|
||||
/// <param name="name">The command name.</param>
|
||||
/// <param name="arguments">The command arguments.</param>
|
||||
/// <returns>Returns whether a matching command was triggered.</returns>
|
||||
/// <inheritdoc />
|
||||
public bool Trigger(string name, string[] arguments)
|
||||
{
|
||||
return this.CommandManager.Trigger(name, arguments);
|
||||
|
|
|
@ -40,10 +40,10 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The game's current locale code (like <c>pt-BR</c>).</summary>
|
||||
/// <inheritdoc />
|
||||
public string CurrentLocale => this.GameContentManager.GetLocale();
|
||||
|
||||
/// <summary>The game's current locale as an enum value.</summary>
|
||||
/// <inheritdoc />
|
||||
public LocalizedContentManager.LanguageCode CurrentLocaleConstant => this.GameContentManager.Language;
|
||||
|
||||
/// <summary>The observable implementation of <see cref="AssetEditors"/>.</summary>
|
||||
|
@ -52,10 +52,10 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/// <summary>The observable implementation of <see cref="AssetLoaders"/>.</summary>
|
||||
internal ObservableCollection<IAssetLoader> ObservableAssetLoaders { get; } = new ObservableCollection<IAssetLoader>();
|
||||
|
||||
/// <summary>Interceptors which provide the initial versions of matching content assets.</summary>
|
||||
/// <inheritdoc />
|
||||
public IList<IAssetLoader> AssetLoaders => this.ObservableAssetLoaders;
|
||||
|
||||
/// <summary>Interceptors which edit matching content assets after they're loaded.</summary>
|
||||
/// <inheritdoc />
|
||||
public IList<IAssetEditor> AssetEditors => this.ObservableAssetEditors;
|
||||
|
||||
|
||||
|
@ -80,12 +80,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
this.Monitor = monitor;
|
||||
}
|
||||
|
||||
/// <summary>Load content from the game folder or mod folder (if not already cached), and return it. When loading a <c>.png</c> file, this must be called outside the game's draw loop.</summary>
|
||||
/// <typeparam name="T">The expected data type. The main supported types are <see cref="Map"/>, <see cref="Texture2D"/>, and dictionaries; other types may be supported by the game's content pipeline.</typeparam>
|
||||
/// <param name="key">The asset key to fetch (if the <paramref name="source"/> is <see cref="ContentSource.GameContent"/>), or the local path to a content file relative to the mod folder.</param>
|
||||
/// <param name="source">Where to search for a matching content asset.</param>
|
||||
/// <exception cref="ArgumentException">The <paramref name="key"/> is empty or contains invalid characters.</exception>
|
||||
/// <exception cref="ContentLoadException">The content asset couldn't be loaded (e.g. because it doesn't exist).</exception>
|
||||
/// <inheritdoc />
|
||||
public T Load<T>(string key, ContentSource source = ContentSource.ModFolder)
|
||||
{
|
||||
try
|
||||
|
@ -109,18 +104,14 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>Normalize an asset name so it's consistent with those generated by the game. This is mainly useful for string comparisons like <see cref="string.StartsWith(string)"/> on generated asset names, and isn't necessary when passing asset names into other content helper methods.</summary>
|
||||
/// <param name="assetName">The asset key.</param>
|
||||
/// <inheritdoc />
|
||||
[Pure]
|
||||
public string NormalizeAssetName(string assetName)
|
||||
{
|
||||
return this.ModContentManager.AssertAndNormalizeAssetName(assetName);
|
||||
}
|
||||
|
||||
/// <summary>Get the underlying key in the game's content cache for an asset. This can be used to load custom map tilesheets, but should be avoided when you can use the content API instead. This does not validate whether the asset exists.</summary>
|
||||
/// <param name="key">The asset key to fetch (if the <paramref name="source"/> is <see cref="ContentSource.GameContent"/>), or the local path to a content file relative to the mod folder.</param>
|
||||
/// <param name="source">Where to search for a matching content asset.</param>
|
||||
/// <exception cref="ArgumentException">The <paramref name="key"/> is empty or contains invalid characters.</exception>
|
||||
/// <inheritdoc />
|
||||
public string GetActualAssetKey(string key, ContentSource source = ContentSource.ModFolder)
|
||||
{
|
||||
switch (source)
|
||||
|
@ -136,10 +127,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>Remove an asset from the content cache so it's reloaded on the next request. This will reload core game assets if needed, but references to the former asset will still show the previous content.</summary>
|
||||
/// <param name="key">The asset key to invalidate in the content folder.</param>
|
||||
/// <exception cref="ArgumentException">The <paramref name="key"/> is empty or contains invalid characters.</exception>
|
||||
/// <returns>Returns whether the given asset key was cached.</returns>
|
||||
/// <inheritdoc />
|
||||
public bool InvalidateCache(string key)
|
||||
{
|
||||
string actualKey = this.GetActualAssetKey(key, ContentSource.GameContent);
|
||||
|
@ -147,28 +135,21 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
return this.ContentCore.InvalidateCache(asset => asset.AssetNameEquals(actualKey)).Any();
|
||||
}
|
||||
|
||||
/// <summary>Remove all assets of the given type from the cache so they're reloaded on the next request. <b>This can be a very expensive operation and should only be used in very specific cases.</b> This will reload core game assets if needed, but references to the former assets will still show the previous content.</summary>
|
||||
/// <typeparam name="T">The asset type to remove from the cache.</typeparam>
|
||||
/// <returns>Returns whether any assets were invalidated.</returns>
|
||||
/// <inheritdoc />
|
||||
public bool InvalidateCache<T>()
|
||||
{
|
||||
this.Monitor.Log($"Requested cache invalidation for all assets of type {typeof(T)}. This is an expensive operation and should be avoided if possible.", LogLevel.Trace);
|
||||
return this.ContentCore.InvalidateCache((key, type) => typeof(T).IsAssignableFrom(type)).Any();
|
||||
}
|
||||
|
||||
/// <summary>Remove matching assets from the content cache so they're reloaded on the next request. This will reload core game assets if needed, but references to the former asset will still show the previous content.</summary>
|
||||
/// <param name="predicate">A predicate matching the assets to invalidate.</param>
|
||||
/// <returns>Returns whether any cache entries were invalidated.</returns>
|
||||
/// <inheritdoc />
|
||||
public bool InvalidateCache(Func<IAssetInfo, bool> predicate)
|
||||
{
|
||||
this.Monitor.Log("Requested cache invalidation for all assets matching a predicate.", LogLevel.Trace);
|
||||
return this.ContentCore.InvalidateCache(predicate).Any();
|
||||
}
|
||||
|
||||
/// <summary>Get a patch helper for arbitrary data.</summary>
|
||||
/// <typeparam name="T">The data type.</typeparam>
|
||||
/// <param name="data">The asset data.</param>
|
||||
/// <param name="assetName">The asset name. This is only used for tracking purposes and has no effect on the patch helper.</param>
|
||||
/// <inheritdoc />
|
||||
public IAssetData GetPatchHelper<T>(T data, string assetName = null)
|
||||
{
|
||||
if (data == null)
|
||||
|
|
|
@ -32,27 +32,20 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
this.CreateContentPack = createContentPack;
|
||||
}
|
||||
|
||||
/// <summary>Get all content packs loaded for this mod.</summary>
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<IContentPack> GetOwned()
|
||||
{
|
||||
return this.ContentPacks.Value;
|
||||
}
|
||||
|
||||
/// <summary>Create a temporary content pack to read files from a directory, using randomized manifest fields. This will generate fake manifest data; any <c>manifest.json</c> in the directory will be ignored. Temporary content packs will not appear in the SMAPI log and update checks will not be performed.</summary>
|
||||
/// <param name="directoryPath">The absolute directory path containing the content pack files.</param>
|
||||
/// <inheritdoc />
|
||||
public IContentPack CreateFake(string directoryPath)
|
||||
{
|
||||
string id = Guid.NewGuid().ToString("N");
|
||||
return this.CreateTemporary(directoryPath, id, id, id, id, new SemanticVersion(1, 0, 0));
|
||||
}
|
||||
|
||||
/// <summary>Create a temporary content pack to read files from a directory. Temporary content packs will not appear in the SMAPI log and update checks will not be performed.</summary>
|
||||
/// <param name="directoryPath">The absolute directory path containing the content pack files.</param>
|
||||
/// <param name="id">The content pack's unique ID.</param>
|
||||
/// <param name="name">The content pack name.</param>
|
||||
/// <param name="description">The content pack description.</param>
|
||||
/// <param name="author">The content pack author's name.</param>
|
||||
/// <param name="version">The content pack version.</param>
|
||||
/// <inheritdoc />
|
||||
public IContentPack CreateTemporary(string directoryPath, string id, string name, string description, string author, ISemanticVersion version)
|
||||
{
|
||||
// validate
|
||||
|
|
|
@ -39,11 +39,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/****
|
||||
** JSON file
|
||||
****/
|
||||
/// <summary>Read data from a JSON file in the mod's folder.</summary>
|
||||
/// <typeparam name="TModel">The model type. This should be a plain class that has public properties for the data you want. The properties can be complex types.</typeparam>
|
||||
/// <param name="path">The file path relative to the mod folder.</param>
|
||||
/// <returns>Returns the deserialized model, or <c>null</c> if the file doesn't exist or is empty.</returns>
|
||||
/// <exception cref="InvalidOperationException">The <paramref name="path"/> is not relative or contains directory climbing (../).</exception>
|
||||
/// <inheritdoc />
|
||||
public TModel ReadJsonFile<TModel>(string path) where TModel : class
|
||||
{
|
||||
if (!PathUtilities.IsSafeRelativePath(path))
|
||||
|
@ -55,11 +51,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
: null;
|
||||
}
|
||||
|
||||
/// <summary>Save data to a JSON file in the mod's folder.</summary>
|
||||
/// <typeparam name="TModel">The model type. This should be a plain class that has public properties for the data you want. The properties can be complex types.</typeparam>
|
||||
/// <param name="path">The file path relative to the mod folder.</param>
|
||||
/// <param name="data">The arbitrary data to save.</param>
|
||||
/// <exception cref="InvalidOperationException">The <paramref name="path"/> is not relative or contains directory climbing (../).</exception>
|
||||
/// <inheritdoc />
|
||||
public void WriteJsonFile<TModel>(string path, TModel data) where TModel : class
|
||||
{
|
||||
if (!PathUtilities.IsSafeRelativePath(path))
|
||||
|
@ -72,11 +64,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/****
|
||||
** Save file
|
||||
****/
|
||||
/// <summary>Read arbitrary data stored in the current save slot. This is only possible if a save has been loaded.</summary>
|
||||
/// <typeparam name="TModel">The model type. This should be a plain class that has public properties for the data you want. The properties can be complex types.</typeparam>
|
||||
/// <param name="key">The unique key identifying the data.</param>
|
||||
/// <returns>Returns the parsed data, or <c>null</c> if the entry doesn't exist or is empty.</returns>
|
||||
/// <exception cref="InvalidOperationException">The player hasn't loaded a save file yet or isn't the main player.</exception>
|
||||
/// <inheritdoc />
|
||||
public TModel ReadSaveData<TModel>(string key) where TModel : class
|
||||
{
|
||||
if (Context.LoadStage == LoadStage.None)
|
||||
|
@ -94,11 +82,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>Save arbitrary data to the current save slot. This is only possible if a save has been loaded, and the data will be lost if the player exits without saving the current day.</summary>
|
||||
/// <typeparam name="TModel">The model type. This should be a plain class that has public properties for the data you want. The properties can be complex types.</typeparam>
|
||||
/// <param name="key">The unique key identifying the data.</param>
|
||||
/// <param name="model">The arbitrary data to save.</param>
|
||||
/// <exception cref="InvalidOperationException">The player hasn't loaded a save file yet or isn't the main player.</exception>
|
||||
/// <inheritdoc />
|
||||
public void WriteSaveData<TModel>(string key, TModel model) where TModel : class
|
||||
{
|
||||
if (Context.LoadStage == LoadStage.None)
|
||||
|
@ -123,10 +107,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/****
|
||||
** Global app data
|
||||
****/
|
||||
/// <summary>Read arbitrary data stored on the local computer, synchronised by GOG/Steam if applicable.</summary>
|
||||
/// <typeparam name="TModel">The model type. This should be a plain class that has public properties for the data you want. The properties can be complex types.</typeparam>
|
||||
/// <param name="key">The unique key identifying the data.</param>
|
||||
/// <returns>Returns the parsed data, or <c>null</c> if the entry doesn't exist or is empty.</returns>
|
||||
/// <inheritdoc />
|
||||
public TModel ReadGlobalData<TModel>(string key) where TModel : class
|
||||
{
|
||||
string path = this.GetGlobalDataPath(key);
|
||||
|
@ -135,10 +116,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
: null;
|
||||
}
|
||||
|
||||
/// <summary>Save arbitrary data to the local computer, synchronised by GOG/Steam if applicable.</summary>
|
||||
/// <typeparam name="TModel">The model type. This should be a plain class that has public properties for the data you want. The properties can be complex types.</typeparam>
|
||||
/// <param name="key">The unique key identifying the data.</param>
|
||||
/// <param name="data">The arbitrary data to save.</param>
|
||||
/// <inheritdoc />
|
||||
public void WriteGlobalData<TModel>(string key, TModel data) where TModel : class
|
||||
{
|
||||
string path = this.GetGlobalDataPath(key);
|
||||
|
|
|
@ -24,35 +24,31 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
this.InputState = inputState;
|
||||
}
|
||||
|
||||
/// <summary>Get the current cursor position.</summary>
|
||||
/// <inheritdoc />
|
||||
public ICursorPosition GetCursorPosition()
|
||||
{
|
||||
return this.InputState.CursorPosition;
|
||||
}
|
||||
|
||||
/// <summary>Get whether a button is currently pressed.</summary>
|
||||
/// <param name="button">The button.</param>
|
||||
/// <inheritdoc />
|
||||
public bool IsDown(SButton button)
|
||||
{
|
||||
return this.InputState.IsDown(button);
|
||||
}
|
||||
|
||||
/// <summary>Get whether a button is currently suppressed, so the game won't see it.</summary>
|
||||
/// <param name="button">The button.</param>
|
||||
/// <inheritdoc />
|
||||
public bool IsSuppressed(SButton button)
|
||||
{
|
||||
return this.InputState.IsSuppressed(button);
|
||||
}
|
||||
|
||||
/// <summary>Prevent the game from handling a button press. This doesn't prevent other mods from receiving the event.</summary>
|
||||
/// <param name="button">The button to suppress.</param>
|
||||
/// <inheritdoc />
|
||||
public void Suppress(SButton button)
|
||||
{
|
||||
this.InputState.OverrideButton(button, setDown: false);
|
||||
}
|
||||
|
||||
/// <summary>Get the state of a button.</summary>
|
||||
/// <param name="button">The button to check.</param>
|
||||
/// <inheritdoc />
|
||||
public SButtonState GetState(SButton button)
|
||||
{
|
||||
return this.InputState.GetState(button);
|
||||
|
|
|
@ -11,37 +11,37 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The full path to the mod's folder.</summary>
|
||||
/// <inheritdoc />
|
||||
public string DirectoryPath { get; }
|
||||
|
||||
/// <summary>Manages access to events raised by SMAPI, which let your mod react when something happens in the game.</summary>
|
||||
/// <inheritdoc />
|
||||
public IModEvents Events { get; }
|
||||
|
||||
/// <summary>An API for loading content assets.</summary>
|
||||
/// <inheritdoc />
|
||||
public IContentHelper Content { get; }
|
||||
|
||||
/// <summary>An API for managing content packs.</summary>
|
||||
/// <inheritdoc />
|
||||
public IContentPackHelper ContentPacks { get; }
|
||||
|
||||
/// <summary>An API for reading and writing persistent mod data.</summary>
|
||||
/// <inheritdoc />
|
||||
public IDataHelper Data { get; }
|
||||
|
||||
/// <summary>An API for checking and changing input state.</summary>
|
||||
/// <inheritdoc />
|
||||
public IInputHelper Input { get; }
|
||||
|
||||
/// <summary>An API for accessing private game code.</summary>
|
||||
/// <inheritdoc />
|
||||
public IReflectionHelper Reflection { get; }
|
||||
|
||||
/// <summary>an API for fetching metadata about loaded mods.</summary>
|
||||
/// <inheritdoc />
|
||||
public IModRegistry ModRegistry { get; }
|
||||
|
||||
/// <summary>An API for managing console commands.</summary>
|
||||
/// <inheritdoc />
|
||||
public ICommandHelper ConsoleCommands { get; }
|
||||
|
||||
/// <summary>Provides multiplayer utilities.</summary>
|
||||
/// <inheritdoc />
|
||||
public IMultiplayerHelper Multiplayer { get; }
|
||||
|
||||
/// <summary>An API for reading translations stored in the mod's <c>i18n</c> folder, with one file per locale (like <c>en.json</c>) containing a flat key => value structure. Translations are fetched with locale fallback, so missing translations are filled in from broader locales (like <c>pt-BR.json</c> < <c>pt.json</c> < <c>default.json</c>).</summary>
|
||||
/// <inheritdoc />
|
||||
public ITranslationHelper Translation { get; }
|
||||
|
||||
|
||||
|
@ -89,8 +89,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/****
|
||||
** Mod config file
|
||||
****/
|
||||
/// <summary>Read the mod's configuration file (and create it if needed).</summary>
|
||||
/// <typeparam name="TConfig">The config class type. This should be a plain class that has public properties for the settings you want. These can be complex types.</typeparam>
|
||||
/// <inheritdoc />
|
||||
public TConfig ReadConfig<TConfig>()
|
||||
where TConfig : class, new()
|
||||
{
|
||||
|
@ -99,9 +98,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
return config;
|
||||
}
|
||||
|
||||
/// <summary>Save to the mod's configuration file.</summary>
|
||||
/// <typeparam name="TConfig">The config class type.</typeparam>
|
||||
/// <param name="config">The config settings to save.</param>
|
||||
/// <inheritdoc />
|
||||
public void WriteConfig<TConfig>(TConfig config)
|
||||
where TConfig : class, new()
|
||||
{
|
||||
|
@ -111,7 +108,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/****
|
||||
** Disposal
|
||||
****/
|
||||
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
// nothing to dispose yet
|
||||
|
|
|
@ -38,28 +38,25 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
this.Monitor = monitor;
|
||||
}
|
||||
|
||||
/// <summary>Get metadata for all loaded mods.</summary>
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<IModInfo> GetAll()
|
||||
{
|
||||
return this.Registry.GetAll();
|
||||
}
|
||||
|
||||
/// <summary>Get metadata for a loaded mod.</summary>
|
||||
/// <param name="uniqueID">The mod's unique ID.</param>
|
||||
/// <returns>Returns the matching mod's metadata, or <c>null</c> if not found.</returns>
|
||||
/// <inheritdoc />
|
||||
public IModInfo Get(string uniqueID)
|
||||
{
|
||||
return this.Registry.Get(uniqueID);
|
||||
}
|
||||
|
||||
/// <summary>Get whether a mod has been loaded.</summary>
|
||||
/// <param name="uniqueID">The mod's unique ID.</param>
|
||||
/// <inheritdoc />
|
||||
public bool IsLoaded(string uniqueID)
|
||||
{
|
||||
return this.Registry.Get(uniqueID) != null;
|
||||
}
|
||||
|
||||
/// <summary>Get the API provided by a mod, or <c>null</c> if it has none. This signature requires using the <see cref="IModHelper.Reflection"/> API to access the API's properties and methods.</summary>
|
||||
/// <inheritdoc />
|
||||
public object GetApi(string uniqueID)
|
||||
{
|
||||
// validate ready
|
||||
|
@ -76,9 +73,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
return mod?.Api;
|
||||
}
|
||||
|
||||
/// <summary>Get the API provided by a mod, mapped to a given interface which specifies the expected properties and methods. If the mod has no API or it's not compatible with the given interface, get <c>null</c>.</summary>
|
||||
/// <typeparam name="TInterface">The interface which matches the properties and methods you intend to access.</typeparam>
|
||||
/// <param name="uniqueID">The mod's unique ID.</param>
|
||||
/// <inheritdoc />
|
||||
public TInterface GetApi<TInterface>(string uniqueID) where TInterface : class
|
||||
{
|
||||
// get raw API
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using StardewModdingAPI.Framework.Networking;
|
||||
using StardewValley;
|
||||
|
@ -27,21 +26,19 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
this.Multiplayer = multiplayer;
|
||||
}
|
||||
|
||||
/// <summary>Get a new multiplayer ID.</summary>
|
||||
/// <inheritdoc />
|
||||
public long GetNewID()
|
||||
{
|
||||
return this.Multiplayer.getNewID();
|
||||
}
|
||||
|
||||
/// <summary>Get the locations which are being actively synced from the host.</summary>
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<GameLocation> GetActiveLocations()
|
||||
{
|
||||
return this.Multiplayer.activeLocations();
|
||||
}
|
||||
|
||||
/// <summary>Get a connected player.</summary>
|
||||
/// <param name="id">The player's unique ID.</param>
|
||||
/// <returns>Returns the connected player, or <c>null</c> if no such player is connected.</returns>
|
||||
/// <inheritdoc />
|
||||
public IMultiplayerPeer GetConnectedPlayer(long id)
|
||||
{
|
||||
return this.Multiplayer.Peers.TryGetValue(id, out MultiplayerPeer peer)
|
||||
|
@ -49,19 +46,13 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
: null;
|
||||
}
|
||||
|
||||
/// <summary>Get all connected players.</summary>
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<IMultiplayerPeer> GetConnectedPlayers()
|
||||
{
|
||||
return this.Multiplayer.Peers.Values;
|
||||
}
|
||||
|
||||
/// <summary>Send a message to mods installed by connected players.</summary>
|
||||
/// <typeparam name="TMessage">The data type. This can be a class with a default constructor, or a value type.</typeparam>
|
||||
/// <param name="message">The data to send over the network.</param>
|
||||
/// <param name="messageType">A message type which receiving mods can use to decide whether it's the one they want to handle, like <c>SetPlayerLocation</c>. This doesn't need to be globally unique, since mods should check the originating mod ID.</param>
|
||||
/// <param name="modIDs">The mod IDs which should receive the message on the destination computers, or <c>null</c> for all mods. Specifying mod IDs is recommended to improve performance, unless it's a general-purpose broadcast.</param>
|
||||
/// <param name="playerIDs">The <see cref="Farmer.UniqueMultiplayerID" /> values for the players who should receive the message, or <c>null</c> for all players. If you don't need to broadcast to all players, specifying player IDs is recommended to reduce latency.</param>
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="message"/> or <paramref name="messageType" /> is null.</exception>
|
||||
/// <inheritdoc />
|
||||
public void SendMessage<TMessage>(TMessage message, string messageType, string[] modIDs = null, long[] playerIDs = null)
|
||||
{
|
||||
this.Multiplayer.BroadcastModMessage(
|
||||
|
|
|
@ -32,11 +32,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
this.Reflector = reflector;
|
||||
}
|
||||
|
||||
/// <summary>Get an instance field.</summary>
|
||||
/// <typeparam name="TValue">The field type.</typeparam>
|
||||
/// <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 field is not found.</param>
|
||||
/// <inheritdoc />
|
||||
public IReflectedField<TValue> GetField<TValue>(object obj, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
|
@ -44,11 +40,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>Get a static field.</summary>
|
||||
/// <typeparam name="TValue">The field type.</typeparam>
|
||||
/// <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 field is not found.</param>
|
||||
/// <inheritdoc />
|
||||
public IReflectedField<TValue> GetField<TValue>(Type type, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
|
@ -56,11 +48,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>Get an instance property.</summary>
|
||||
/// <typeparam name="TValue">The property type.</typeparam>
|
||||
/// <param name="obj">The object which has the property.</param>
|
||||
/// <param name="name">The property name.</param>
|
||||
/// <param name="required">Whether to throw an exception if the property is not found.</param>
|
||||
/// <inheritdoc />
|
||||
public IReflectedProperty<TValue> GetProperty<TValue>(object obj, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
|
@ -68,11 +56,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>Get a static property.</summary>
|
||||
/// <typeparam name="TValue">The property type.</typeparam>
|
||||
/// <param name="type">The type which has the property.</param>
|
||||
/// <param name="name">The property name.</param>
|
||||
/// <param name="required">Whether to throw an exception if the property is not found.</param>
|
||||
/// <inheritdoc />
|
||||
public IReflectedProperty<TValue> GetProperty<TValue>(Type type, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
|
@ -80,10 +64,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>Get an instance method.</summary>
|
||||
/// <param name="obj">The object which has the method.</param>
|
||||
/// <param name="name">The field name.</param>
|
||||
/// <param name="required">Whether to throw an exception if the field is not found.</param>
|
||||
/// <inheritdoc />
|
||||
public IReflectedMethod GetMethod(object obj, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
|
@ -91,10 +72,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>Get a static method.</summary>
|
||||
/// <param name="type">The type which has the method.</param>
|
||||
/// <param name="name">The field name.</param>
|
||||
/// <param name="required">Whether to throw an exception if the field is not found.</param>
|
||||
/// <inheritdoc />
|
||||
public IReflectedMethod GetMethod(Type type, string name, bool required = true)
|
||||
{
|
||||
return this.AssertAccessAllowed(
|
||||
|
|
|
@ -16,10 +16,10 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The current locale.</summary>
|
||||
/// <inheritdoc />
|
||||
public string Locale => this.Translator.Locale;
|
||||
|
||||
/// <summary>The game's current language code.</summary>
|
||||
/// <inheritdoc />
|
||||
public LocalizedContentManager.LanguageCode LocaleEnum => this.Translator.LocaleEnum;
|
||||
|
||||
|
||||
|
@ -37,22 +37,19 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
this.Translator.SetLocale(locale, languageCode);
|
||||
}
|
||||
|
||||
/// <summary>Get all translations for the current locale.</summary>
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<Translation> GetTranslations()
|
||||
{
|
||||
return this.Translator.GetTranslations();
|
||||
}
|
||||
|
||||
/// <summary>Get a translation for the current locale.</summary>
|
||||
/// <param name="key">The translation key.</param>
|
||||
/// <inheritdoc />
|
||||
public Translation Get(string key)
|
||||
{
|
||||
return this.Translator.Get(key);
|
||||
}
|
||||
|
||||
/// <summary>Get a translation for the current locale.</summary>
|
||||
/// <param name="key">The translation key.</param>
|
||||
/// <param name="tokens">An object containing token key/value pairs. This can be an anonymous object (like <c>new { value = 42, name = "Cranberries" }</c>), a dictionary, or a class instance.</param>
|
||||
/// <inheritdoc />
|
||||
public Translation Get(string key, object tokens)
|
||||
{
|
||||
return this.Translator.Get(key, tokens);
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace StardewModdingAPI.Framework
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>Whether verbose logging is enabled. This enables more detailed diagnostic messages than are normally needed.</summary>
|
||||
/// <inheritdoc />
|
||||
public bool IsVerbose { get; }
|
||||
|
||||
/// <summary>Whether to show the full log stamps (with time/level/logger) in the console. If false, shows a simplified stamp with only the logger.</summary>
|
||||
|
@ -70,25 +70,20 @@ namespace StardewModdingAPI.Framework
|
|||
this.IsVerbose = isVerbose;
|
||||
}
|
||||
|
||||
/// <summary>Log a message for the player or developer.</summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="level">The log severity level.</param>
|
||||
/// <inheritdoc />
|
||||
public void Log(string message, LogLevel level = LogLevel.Trace)
|
||||
{
|
||||
this.LogImpl(this.Source, message, (ConsoleLogLevel)level);
|
||||
}
|
||||
|
||||
/// <summary>Log a message for the player or developer, but only if it hasn't already been logged since the last game launch.</summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <param name="level">The log severity level.</param>
|
||||
/// <inheritdoc />
|
||||
public void LogOnce(string message, LogLevel level = LogLevel.Trace)
|
||||
{
|
||||
if (this.LogOnceCache.Add($"{message}|{level}"))
|
||||
this.LogImpl(this.Source, message, (ConsoleLogLevel)level);
|
||||
}
|
||||
|
||||
/// <summary>Log a message that only appears when <see cref="IMonitor.IsVerbose"/> is enabled.</summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
/// <inheritdoc />
|
||||
public void VerboseLog(string message)
|
||||
{
|
||||
if (this.IsVerbose)
|
||||
|
|
|
@ -18,25 +18,25 @@ namespace StardewModdingAPI.Framework.Networking
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The player's unique ID.</summary>
|
||||
/// <inheritdoc />
|
||||
public long PlayerID { get; }
|
||||
|
||||
/// <summary>Whether this is a connection to the host player.</summary>
|
||||
/// <inheritdoc />
|
||||
public bool IsHost { get; }
|
||||
|
||||
/// <summary>Whether the player has SMAPI installed.</summary>
|
||||
/// <inheritdoc />
|
||||
public bool HasSmapi => this.ApiVersion != null;
|
||||
|
||||
/// <summary>The player's OS platform, if <see cref="HasSmapi"/> is true.</summary>
|
||||
/// <inheritdoc />
|
||||
public GamePlatform? Platform { get; }
|
||||
|
||||
/// <summary>The installed version of Stardew Valley, if <see cref="HasSmapi"/> is true.</summary>
|
||||
/// <inheritdoc />
|
||||
public ISemanticVersion GameVersion { get; }
|
||||
|
||||
/// <summary>The installed version of SMAPI, if <see cref="HasSmapi"/> is true.</summary>
|
||||
/// <inheritdoc />
|
||||
public ISemanticVersion ApiVersion { get; }
|
||||
|
||||
/// <summary>The installed mods, if <see cref="HasSmapi"/> is true.</summary>
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<IMultiplayerPeerMod> Mods { get; }
|
||||
|
||||
|
||||
|
@ -62,9 +62,7 @@ namespace StardewModdingAPI.Framework.Networking
|
|||
this.SendMessageImpl = sendMessage;
|
||||
}
|
||||
|
||||
/// <summary>Get metadata for a mod installed by the player.</summary>
|
||||
/// <param name="id">The unique mod ID.</param>
|
||||
/// <returns>Returns the mod info, or <c>null</c> if the player doesn't have that mod.</returns>
|
||||
/// <inheritdoc />
|
||||
public IMultiplayerPeerMod GetMod(string id)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(id) || this.Mods == null || !this.Mods.Any())
|
||||
|
|
|
@ -5,13 +5,13 @@ namespace StardewModdingAPI.Framework.Networking
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The mod's display name.</summary>
|
||||
/// <inheritdoc />
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>The unique mod ID.</summary>
|
||||
/// <inheritdoc />
|
||||
public string ID { get; }
|
||||
|
||||
/// <summary>The mod version.</summary>
|
||||
/// <inheritdoc />
|
||||
public ISemanticVersion Version { get; }
|
||||
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The reflection metadata.</summary>
|
||||
/// <inheritdoc />
|
||||
public FieldInfo FieldInfo { get; }
|
||||
|
||||
|
||||
|
@ -55,7 +55,7 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
this.FieldInfo = field;
|
||||
}
|
||||
|
||||
/// <summary>Get the field value.</summary>
|
||||
/// <inheritdoc />
|
||||
public TValue GetValue()
|
||||
{
|
||||
try
|
||||
|
@ -72,8 +72,7 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>Set the field value.</summary>
|
||||
//// <param name="value">The value to set.</param>
|
||||
/// <inheritdoc />
|
||||
public void SetValue(TValue value)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The reflection metadata.</summary>
|
||||
/// <inheritdoc />
|
||||
public MethodInfo MethodInfo { get; }
|
||||
|
||||
|
||||
|
@ -54,9 +54,7 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
this.MethodInfo = method;
|
||||
}
|
||||
|
||||
/// <summary>Invoke the method.</summary>
|
||||
/// <typeparam name="TValue">The return type.</typeparam>
|
||||
/// <param name="arguments">The method arguments to pass in.</param>
|
||||
/// <inheritdoc />
|
||||
public TValue Invoke<TValue>(params object[] arguments)
|
||||
{
|
||||
// invoke method
|
||||
|
@ -85,8 +83,7 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>Invoke the method.</summary>
|
||||
/// <param name="arguments">The method arguments to pass in.</param>
|
||||
/// <inheritdoc />
|
||||
public void Invoke(params object[] arguments)
|
||||
{
|
||||
// invoke method
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The reflection metadata.</summary>
|
||||
/// <inheritdoc />
|
||||
public PropertyInfo PropertyInfo { get; }
|
||||
|
||||
|
||||
|
@ -61,7 +61,7 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
this.SetMethod = (Action<TValue>)Delegate.CreateDelegate(typeof(Action<TValue>), obj, this.PropertyInfo.SetMethod);
|
||||
}
|
||||
|
||||
/// <summary>Get the property value.</summary>
|
||||
/// <inheritdoc />
|
||||
public TValue GetValue()
|
||||
{
|
||||
if (this.GetMethod == null)
|
||||
|
@ -81,8 +81,7 @@ namespace StardewModdingAPI.Framework.Reflection
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>Set the property value.</summary>
|
||||
//// <param name="value">The value to set.</param>
|
||||
/// <inheritdoc />
|
||||
public void SetValue(TValue value)
|
||||
{
|
||||
if (this.SetMethod == null)
|
||||
|
|
|
@ -153,6 +153,9 @@ namespace StardewModdingAPI.Framework
|
|||
/// <summary>Whether the game is creating the save file and SMAPI has already raised <see cref="IGameLoopEvents.SaveCreating"/>.</summary>
|
||||
private bool IsBetweenCreateEvents;
|
||||
|
||||
/// <summary>Whether the player just returned to the title screen.</summary>
|
||||
private bool JustReturnedToTitle;
|
||||
|
||||
/// <summary>Asset interceptors added or removed since the last tick.</summary>
|
||||
private readonly List<AssetInterceptorChange> ReloadAssetInterceptorsQueue = new List<AssetInterceptorChange>();
|
||||
|
||||
|
@ -306,10 +309,10 @@ namespace StardewModdingAPI.Framework
|
|||
}).Start();
|
||||
|
||||
// set window titles
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
this.Game.Window.Title = $"Stardew Valley {Constants.GameVersion} - running SMAPI {Constants.ApiVersion}";
|
||||
this.LogManager.SetConsoleTitle($"SMAPI {Constants.ApiVersion} - running Stardew Valley {Constants.GameVersion}");
|
||||
#endif
|
||||
this.SetWindowTitles(
|
||||
game: $"Stardew Valley {Constants.GameVersion} - running SMAPI {Constants.ApiVersion}",
|
||||
smapi: $"SMAPI {Constants.ApiVersion} - running Stardew Valley {Constants.GameVersion}"
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -324,9 +327,11 @@ namespace StardewModdingAPI.Framework
|
|||
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
// set window titles
|
||||
this.Game.Window.Title = $"Stardew Valley {Constants.GameVersion} - running SMAPI {Constants.ApiVersion}";
|
||||
this.LogManager.SetConsoleTitle($"SMAPI {Constants.ApiVersion} - running Stardew Valley {Constants.GameVersion}");
|
||||
#endif
|
||||
this.SetWindowTitles(
|
||||
game: $"Stardew Valley {Constants.GameVersion} - running SMAPI {Constants.ApiVersion}",
|
||||
smapi: $"SMAPI {Constants.ApiVersion} - running Stardew Valley {Constants.GameVersion}"
|
||||
);
|
||||
|
||||
// start game
|
||||
this.Monitor.Log("Starting game...", LogLevel.Debug);
|
||||
try
|
||||
|
@ -437,12 +442,13 @@ namespace StardewModdingAPI.Framework
|
|||
this.CheckForUpdatesAsync(mods);
|
||||
}
|
||||
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
// update window titles
|
||||
int modsLoaded = this.ModRegistry.GetAll().Count();
|
||||
this.Game.Window.Title = $"Stardew Valley {Constants.GameVersion} - running SMAPI {Constants.ApiVersion} with {modsLoaded} mods";
|
||||
this.LogManager.SetConsoleTitle($"SMAPI {Constants.ApiVersion} - running Stardew Valley {Constants.GameVersion} with {modsLoaded} mods");
|
||||
#else
|
||||
this.SetWindowTitles(
|
||||
game: $"Stardew Valley {Constants.GameVersion} - running SMAPI {Constants.ApiVersion} with {modsLoaded} mods",
|
||||
smapi: $"SMAPI {Constants.ApiVersion} - running Stardew Valley {Constants.GameVersion} with {modsLoaded} mods"
|
||||
);
|
||||
#if SMAPI_FOR_MOBILE
|
||||
SGameConsole.Instance.isVisible = false;
|
||||
this.Game.IsGameSuspended = false;
|
||||
}).Start();
|
||||
|
@ -512,6 +518,10 @@ namespace StardewModdingAPI.Framework
|
|||
SCore.DeprecationManager.PrintQueued();
|
||||
SCore.PerformanceMonitor.PrintQueuedAlerts();
|
||||
|
||||
// reapply overrides
|
||||
if (this.JustReturnedToTitle && !(Game1.mapDisplayDevice is SDisplayDevice))
|
||||
Game1.mapDisplayDevice = new SDisplayDevice(Game1.content, Game1.game1.GraphicsDevice);
|
||||
|
||||
/*********
|
||||
** First-tick initialization
|
||||
*********/
|
||||
|
@ -1170,8 +1180,7 @@ namespace StardewModdingAPI.Framework
|
|||
{
|
||||
// perform cleanup
|
||||
this.Multiplayer.CleanupOnMultiplayerExit();
|
||||
if (!(Game1.mapDisplayDevice is SDisplayDevice))
|
||||
Game1.mapDisplayDevice = new SDisplayDevice(Game1.content, Game1.game1.GraphicsDevice);
|
||||
this.JustReturnedToTitle = true;
|
||||
}
|
||||
|
||||
/// <summary>Raised before the game exits.</summary>
|
||||
|
@ -1279,6 +1288,17 @@ namespace StardewModdingAPI.Framework
|
|||
return !issuesFound;
|
||||
}
|
||||
|
||||
/// <summary>Set the window titles for the game and console windows.</summary>
|
||||
/// <param name="game">The game window text.</param>
|
||||
/// <param name="smapi">The SMAPI window text.</param>
|
||||
private void SetWindowTitles(string game, string smapi)
|
||||
{
|
||||
#if !SMAPI_FOR_MOBILE
|
||||
this.Game.Window.Title = game;
|
||||
this.LogManager.SetConsoleTitle(smapi);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>Asynchronously check for a new version of SMAPI and any installed mods, and print alerts to the console if an update is available.</summary>
|
||||
/// <param name="mods">The mods to include in the update check (if eligible).</param>
|
||||
private void CheckForUpdatesAsync(IModMetadata[] mods)
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace StardewModdingAPI.Patches
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>A unique name for this patch.</summary>
|
||||
/// <inheritdoc />
|
||||
public string Name => nameof(DialogueErrorPatch);
|
||||
|
||||
|
||||
|
@ -50,8 +50,7 @@ namespace StardewModdingAPI.Patches
|
|||
}
|
||||
|
||||
|
||||
/// <summary>Apply the Harmony patch.</summary>
|
||||
/// <param name="harmony">The Harmony instance.</param>
|
||||
/// <inheritdoc />
|
||||
#if HARMONY_2
|
||||
public void Apply(Harmony harmony)
|
||||
{
|
||||
|
@ -78,6 +77,7 @@ namespace StardewModdingAPI.Patches
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace StardewModdingAPI.Patches
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>A unique name for this patch.</summary>
|
||||
/// <inheritdoc />
|
||||
public string Name => nameof(EventErrorPatch);
|
||||
|
||||
|
||||
|
@ -41,8 +41,7 @@ namespace StardewModdingAPI.Patches
|
|||
EventErrorPatch.MonitorForGame = monitorForGame;
|
||||
}
|
||||
|
||||
/// <summary>Apply the Harmony patch.</summary>
|
||||
/// <param name="harmony">The Harmony instance.</param>
|
||||
/// <inheritdoc />
|
||||
#if HARMONY_2
|
||||
public void Apply(Harmony harmony)
|
||||
{
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace StardewModdingAPI.Patches
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>A unique name for this patch.</summary>
|
||||
/// <inheritdoc />
|
||||
public string Name => nameof(LoadContextPatch);
|
||||
|
||||
|
||||
|
@ -49,8 +49,7 @@ namespace StardewModdingAPI.Patches
|
|||
LoadContextPatch.OnStageChanged = onStageChanged;
|
||||
}
|
||||
|
||||
/// <summary>Apply the Harmony patch.</summary>
|
||||
/// <param name="harmony">The Harmony instance.</param>
|
||||
/// <inheritdoc />
|
||||
#if HARMONY_2
|
||||
public void Apply(Harmony harmony)
|
||||
#else
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace StardewModdingAPI.Patches
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>A unique name for this patch.</summary>
|
||||
/// <inheritdoc />
|
||||
public string Name => nameof(LoadErrorPatch);
|
||||
|
||||
|
||||
|
@ -51,8 +51,7 @@ namespace StardewModdingAPI.Patches
|
|||
}
|
||||
|
||||
|
||||
/// <summary>Apply the Harmony patch.</summary>
|
||||
/// <param name="harmony">The Harmony instance.</param>
|
||||
/// <inheritdoc />
|
||||
#if HARMONY_2
|
||||
public void Apply(Harmony harmony)
|
||||
#else
|
||||
|
|
|
@ -23,15 +23,14 @@ namespace StardewModdingAPI.Patches
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>A unique name for this patch.</summary>
|
||||
/// <inheritdoc />
|
||||
public string Name => nameof(ObjectErrorPatch);
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Apply the Harmony patch.</summary>
|
||||
/// <param name="harmony">The Harmony instance.</param>
|
||||
/// <inheritdoc />
|
||||
#if HARMONY_2
|
||||
public void Apply(Harmony harmony)
|
||||
#else
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace StardewModdingAPI.Patches
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>A unique name for this patch.</summary>
|
||||
/// <inheritdoc />
|
||||
public string Name => nameof(ScheduleErrorPatch);
|
||||
|
||||
|
||||
|
@ -43,8 +43,7 @@ namespace StardewModdingAPI.Patches
|
|||
ScheduleErrorPatch.MonitorForGame = monitorForGame;
|
||||
}
|
||||
|
||||
/// <summary>Apply the Harmony patch.</summary>
|
||||
/// <param name="harmony">The Harmony instance.</param>
|
||||
/// <inheritdoc />
|
||||
#if HARMONY_2
|
||||
public void Apply(Harmony harmony)
|
||||
#else
|
||||
|
|
|
@ -16,19 +16,19 @@ namespace StardewModdingAPI
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The major version incremented for major API changes.</summary>
|
||||
/// <inheritdoc />
|
||||
public int MajorVersion => this.Version.MajorVersion;
|
||||
|
||||
/// <summary>The minor version incremented for backwards-compatible changes.</summary>
|
||||
/// <inheritdoc />
|
||||
public int MinorVersion => this.Version.MinorVersion;
|
||||
|
||||
/// <summary>The patch version for backwards-compatible bug fixes.</summary>
|
||||
/// <inheritdoc />
|
||||
public int PatchVersion => this.Version.PatchVersion;
|
||||
|
||||
/// <summary>An optional prerelease tag.</summary>
|
||||
/// <inheritdoc />
|
||||
public string PrereleaseTag => this.Version.PrereleaseTag;
|
||||
|
||||
/// <summary>Optional build metadata. This is ignored when determining version precedence.</summary>
|
||||
/// <inheritdoc />
|
||||
public string BuildMetadata => this.Version.BuildMetadata;
|
||||
|
||||
|
||||
|
@ -83,83 +83,68 @@ namespace StardewModdingAPI
|
|||
this.Version = version;
|
||||
}
|
||||
|
||||
/// <summary>Whether this is a prerelease version.</summary>
|
||||
/// <inheritdoc />
|
||||
public bool IsPrerelease()
|
||||
{
|
||||
return this.Version.IsPrerelease();
|
||||
}
|
||||
|
||||
/// <summary>Get an integer indicating whether this version precedes (less than 0), supersedes (more than 0), or is equivalent to (0) the specified version.</summary>
|
||||
/// <param name="other">The version to compare with this instance.</param>
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="other"/> value is null.</exception>
|
||||
/// <inheritdoc />
|
||||
/// <remarks>The implementation is defined by Semantic Version 2.0 (https://semver.org/).</remarks>
|
||||
public int CompareTo(ISemanticVersion other)
|
||||
{
|
||||
return this.Version.CompareTo(other);
|
||||
}
|
||||
|
||||
/// <summary>Get whether this version is older than the specified version.</summary>
|
||||
/// <param name="other">The version to compare with this instance.</param>
|
||||
/// <inheritdoc />
|
||||
public bool IsOlderThan(ISemanticVersion other)
|
||||
{
|
||||
return this.Version.IsOlderThan(other);
|
||||
}
|
||||
|
||||
/// <summary>Get whether this version is older than the specified version.</summary>
|
||||
/// <param name="other">The version to compare with this instance.</param>
|
||||
/// <exception cref="FormatException">The specified version is not a valid semantic version.</exception>
|
||||
/// <inheritdoc />
|
||||
public bool IsOlderThan(string other)
|
||||
{
|
||||
return this.Version.IsOlderThan(other);
|
||||
}
|
||||
|
||||
/// <summary>Get whether this version is newer than the specified version.</summary>
|
||||
/// <param name="other">The version to compare with this instance.</param>
|
||||
/// <inheritdoc />
|
||||
public bool IsNewerThan(ISemanticVersion other)
|
||||
{
|
||||
return this.Version.IsNewerThan(other);
|
||||
}
|
||||
|
||||
/// <summary>Get whether this version is newer than the specified version.</summary>
|
||||
/// <param name="other">The version to compare with this instance.</param>
|
||||
/// <exception cref="FormatException">The specified version is not a valid semantic version.</exception>
|
||||
/// <inheritdoc />
|
||||
public bool IsNewerThan(string other)
|
||||
{
|
||||
return this.Version.IsNewerThan(other);
|
||||
}
|
||||
|
||||
/// <summary>Get whether this version is between two specified versions (inclusively).</summary>
|
||||
/// <param name="min">The minimum version.</param>
|
||||
/// <param name="max">The maximum version.</param>
|
||||
/// <inheritdoc />
|
||||
public bool IsBetween(ISemanticVersion min, ISemanticVersion max)
|
||||
{
|
||||
return this.Version.IsBetween(min, max);
|
||||
}
|
||||
|
||||
/// <summary>Get whether this version is between two specified versions (inclusively).</summary>
|
||||
/// <param name="min">The minimum version.</param>
|
||||
/// <param name="max">The maximum version.</param>
|
||||
/// <exception cref="FormatException">One of the specified versions is not a valid semantic version.</exception>
|
||||
/// <inheritdoc />
|
||||
public bool IsBetween(string min, string max)
|
||||
{
|
||||
return this.Version.IsBetween(min, max);
|
||||
}
|
||||
|
||||
/// <summary>Indicates whether the current object is equal to another object of the same type.</summary>
|
||||
/// <returns>true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false.</returns>
|
||||
/// <param name="other">An object to compare with this object.</param>
|
||||
/// <inheritdoc />
|
||||
public bool Equals(ISemanticVersion other)
|
||||
{
|
||||
return other != null && this.CompareTo(other) == 0;
|
||||
}
|
||||
|
||||
/// <summary>Get a string representation of the version.</summary>
|
||||
/// <inheritdoc cref="ISemanticVersion.ToString" />
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Version.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Whether the version uses non-standard extensions, like four-part game versions on some platforms.</summary>
|
||||
/// <inheritdoc />
|
||||
public bool IsNonStandard()
|
||||
{
|
||||
return this.Version.IsNonStandard();
|
||||
|
|
Loading…
Reference in New Issue