using System; using System.Diagnostics.CodeAnalysis; using StardewModdingAPI.Toolkit; namespace StardewModdingAPI.Web.Framework.LogParsing.Models { /// Metadata about a mod or content pack in the log. public class LogModInfo { /********* ** Private fields *********/ /// The parsed mod version, if valid. private Lazy ParsedVersionImpl; /********* ** Accessors *********/ /// The mod name. public string Name { get; } /// The mod author. public string Author { get; } /// The mod version. public string Version { get; private set; } /// The mod description. public string Description { get; } /// The update version. public string? UpdateVersion { get; private set; } /// The update link. public string? UpdateLink { get; private set; } /// The name of the mod for which this is a content pack (if applicable). public string? ContentPackFor { get; } /// The number of errors logged by this mod. public int Errors { get; set; } /// Whether the mod was loaded into the game. public bool Loaded { get; } /// Whether the mod has an update available. [MemberNotNullWhen(true, nameof(LogModInfo.UpdateVersion), nameof(LogModInfo.UpdateLink))] public bool HasUpdate => this.UpdateVersion != null && this.Version != this.UpdateVersion; /// Whether this is an actual mod (rather than a special entry for SMAPI or the game itself). public bool IsMod { get; } /// Whether this is a C# code mod. public bool IsCodeMod { get; } /// Whether this is a content pack for another mod. [MemberNotNullWhen(true, nameof(LogModInfo.ContentPackFor))] public bool IsContentPack { get; } /********* ** Public methods *********/ /// Construct an instance. /// The mod name. /// The mod author. /// The mod version. /// The mod description. /// The update version. /// The update link. /// The name of the mod for which this is a content pack (if applicable). /// The number of errors logged by this mod. /// Whether the mod was loaded into the game. /// Whether this is an actual mod (instead of a special entry for SMAPI or the game). public LogModInfo(string name, string author, string version, string description, string? updateVersion = null, string? updateLink = null, string? contentPackFor = null, int errors = 0, bool loaded = true, bool isMod = true) { this.Name = name; this.Author = author; this.Description = description; this.UpdateVersion = updateVersion; this.UpdateLink = updateLink; this.ContentPackFor = contentPackFor; this.Errors = errors; this.Loaded = loaded; if (isMod) { this.IsMod = true; this.IsContentPack = !string.IsNullOrWhiteSpace(this.ContentPackFor); this.IsCodeMod = !this.IsContentPack; } this.OverrideVersion(version); } /// Add an update alert for this mod. /// The update version. /// The update link. public void SetUpdate(string updateVersion, string updateLink) { this.UpdateVersion = updateVersion; this.UpdateLink = updateLink; } /// Override the version number, for cases like SMAPI itself where the version is only known later during parsing. /// The new mod version. [MemberNotNull(nameof(LogModInfo.Version), nameof(LogModInfo.ParsedVersionImpl))] public void OverrideVersion(string version) { this.Version = version; this.ParsedVersionImpl = new Lazy(this.ParseVersion); } /// Get the semantic version for this mod, if it's valid. public ISemanticVersion? GetParsedVersion() { return this.ParsedVersionImpl.Value; } /********* ** Private methods *********/ /// Get the semantic version for this mod, if it's valid. public ISemanticVersion? ParseVersion() { return !string.IsNullOrWhiteSpace(this.Version) && SemanticVersion.TryParse(this.Version, out ISemanticVersion? version) ? version : null; } } }