diff options
Diffstat (limited to 'src')
25 files changed, 245 insertions, 126 deletions
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs index c769b622..e9545575 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs @@ -16,7 +16,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World ** Fields *********/ /// <summary>The valid types that can be cleared.</summary> - private readonly string[] ValidTypes = { "debris", "fruit-trees", "grass", "trees", "everything" }; + private readonly string[] ValidTypes = { "crops", "debris", "fruit-trees", "grass", "trees", "everything" }; /// <summary>The resource clump IDs to consider debris.</summary> private readonly int[] DebrisClumps = { ResourceClump.stumpIndex, ResourceClump.hollowLogIndex, ResourceClump.meteoriteIndex, ResourceClump.boulderIndex }; @@ -32,7 +32,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World description: "Clears in-game entities in a given location.\n\n" + "Usage: world_clear <location> <object type>\n" + "- location: the location name for which to clear objects (like Farm), or 'current' for the current location.\n" - + " - object type: the type of object clear. You can specify 'debris' (stones/twigs/weeds and dead crops), 'grass', and 'trees' / 'fruit-trees'. You can also specify 'everything', which includes things not removed by the other types (like furniture or resource clumps)." + + " - object type: the type of object clear. You can specify 'crops', 'debris' (stones/twigs/weeds and dead crops), 'grass', and 'trees' / 'fruit-trees'. You can also specify 'everything', which includes things not removed by the other types (like furniture or resource clumps)." ) { } @@ -69,6 +69,15 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World // apply switch (type) { + case "crops": + { + int removed = + this.RemoveTerrainFeatures(location, p => p is HoeDirt) + + this.RemoveResourceClumps(location, p => p is GiantCrop); + monitor.Log($"Done! Removed {removed} entities from {location.Name}.", LogLevel.Info); + break; + } + case "debris": { int removed = 0; @@ -83,7 +92,14 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World } removed += - this.RemoveObjects(location, obj => obj.Name.ToLower().Contains("weed") || obj.Name == "Twig" || obj.Name == "Stone") + this.RemoveObjects(location, obj => + !(obj is Chest) + && ( + obj.Name == "Weeds" + || obj.Name == "Stone" + || (obj.ParentSheetIndex == 294 || obj.ParentSheetIndex == 295) + ) + ) + this.RemoveResourceClumps(location, clump => this.DebrisClumps.Contains(clump.parentSheetIndex.Value)); monitor.Log($"Done! Removed {removed} entities from {location.Name}.", LogLevel.Info); diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json index afefd733..1c4ea7d8 100644 --- a/src/SMAPI.Mods.ConsoleCommands/manifest.json +++ b/src/SMAPI.Mods.ConsoleCommands/manifest.json @@ -1,9 +1,9 @@ { "Name": "Console Commands", "Author": "SMAPI", - "Version": "2.11.0", + "Version": "2.11.1", "Description": "Adds SMAPI console commands that let you manipulate the game.", "UniqueID": "SMAPI.ConsoleCommands", "EntryDll": "ConsoleCommands.dll", - "MinimumApiVersion": "2.11.0" + "MinimumApiVersion": "2.11.1" } diff --git a/src/SMAPI.Mods.SaveBackup/manifest.json b/src/SMAPI.Mods.SaveBackup/manifest.json index a5841a65..cfffd9c1 100644 --- a/src/SMAPI.Mods.SaveBackup/manifest.json +++ b/src/SMAPI.Mods.SaveBackup/manifest.json @@ -1,9 +1,9 @@ { "Name": "Save Backup", "Author": "SMAPI", - "Version": "2.11.0", + "Version": "2.11.1", "Description": "Automatically backs up all your saves once per day into its folder.", "UniqueID": "SMAPI.SaveBackup", "EntryDll": "SaveBackup.dll", - "MinimumApiVersion": "2.11.0" + "MinimumApiVersion": "2.11.1" } diff --git a/src/SMAPI.Web/Framework/LogParsing/LogParser.cs b/src/SMAPI.Web/Framework/LogParsing/LogParser.cs index fdc19404..3f33c0c1 100644 --- a/src/SMAPI.Web/Framework/LogParsing/LogParser.cs +++ b/src/SMAPI.Web/Framework/LogParsing/LogParser.cs @@ -119,7 +119,11 @@ namespace StardewModdingAPI.Web.Framework.LogParsing // mod list if (!inModList && message.Level == LogLevel.Info && this.ModListStartPattern.IsMatch(message.Text)) + { inModList = true; + message.IsStartOfSection = true; + message.Section = LogSection.ModsList; + } else if (inModList) { Match match = this.ModListEntryPattern.Match(message.Text); @@ -128,11 +132,17 @@ namespace StardewModdingAPI.Web.Framework.LogParsing string author = match.Groups["author"].Value; string description = match.Groups["description"].Value; mods[name] = new LogModInfo { Name = name, Author = author, Version = version, Description = description, Loaded = true }; + + message.Section = LogSection.ModsList; } // content pack list else if (!inContentPackList && message.Level == LogLevel.Info && this.ContentPackListStartPattern.IsMatch(message.Text)) + { inContentPackList = true; + message.IsStartOfSection = true; + message.Section = LogSection.ContentPackList; + } else if (inContentPackList) { Match match = this.ContentPackListEntryPattern.Match(message.Text); @@ -142,11 +152,17 @@ namespace StardewModdingAPI.Web.Framework.LogParsing string description = match.Groups["description"].Value; string forMod = match.Groups["for"].Value; mods[name] = new LogModInfo { Name = name, Author = author, Version = version, Description = description, ContentPackFor = forMod, Loaded = true }; + + message.Section = LogSection.ContentPackList; } // mod update list else if (!inModUpdateList && message.Level == LogLevel.Alert && this.ModUpdateListStartPattern.IsMatch(message.Text)) + { inModUpdateList = true; + message.IsStartOfSection = true; + message.Section = LogSection.ModUpdateList; + } else if (inModUpdateList) { Match match = this.ModUpdateListEntryPattern.Match(message.Text); @@ -162,6 +178,8 @@ namespace StardewModdingAPI.Web.Framework.LogParsing { mods[name] = new LogModInfo { Name = name, UpdateVersion = version, UpdateLink = link, Loaded = false }; } + + message.Section = LogSection.ModUpdateList; } else if (message.Level == LogLevel.Alert && this.SMAPIUpdatePattern.IsMatch(message.Text)) diff --git a/src/SMAPI.Web/Framework/LogParsing/Models/LogMessage.cs b/src/SMAPI.Web/Framework/LogParsing/Models/LogMessage.cs index baeac83c..f7c99d02 100644 --- a/src/SMAPI.Web/Framework/LogParsing/Models/LogMessage.cs +++ b/src/SMAPI.Web/Framework/LogParsing/Models/LogMessage.cs @@ -20,5 +20,11 @@ namespace StardewModdingAPI.Web.Framework.LogParsing.Models /// <summary>The number of times this message was repeated consecutively.</summary> public int Repeated { get; set; } + + /// <summary>The section that this log message belongs to.</summary> + public LogSection? Section { get; set; } + + /// <summary>Whether this message is the first one of its section.</summary> + public bool IsStartOfSection { get; set; } } } diff --git a/src/SMAPI.Web/Framework/LogParsing/Models/LogSection.cs b/src/SMAPI.Web/Framework/LogParsing/Models/LogSection.cs new file mode 100644 index 00000000..218d546c --- /dev/null +++ b/src/SMAPI.Web/Framework/LogParsing/Models/LogSection.cs @@ -0,0 +1,15 @@ +namespace StardewModdingAPI.Web.Framework.LogParsing.Models +{ + /// <summary>The different sections of a log.</summary> + public enum LogSection + { + /// <summary>The list of mods the user has.</summary> + ModsList, + + /// <summary>The list of content packs the user has.</summary> + ContentPackList, + + /// <summary>The list of mod updates SMAPI has found.</summary> + ModUpdateList + } +} diff --git a/src/SMAPI.Web/Views/Index/Index.cshtml b/src/SMAPI.Web/Views/Index/Index.cshtml index ef092cc8..24b42e09 100644 --- a/src/SMAPI.Web/Views/Index/Index.cshtml +++ b/src/SMAPI.Web/Views/Index/Index.cshtml @@ -99,16 +99,15 @@ else <p> Special thanks to - AbroadKew, acerbicon, <a href="https://www.nexusmods.com/stardewvalley/users/31393530">ChefRude</a>, - cheesysteak, + <a href="https://github.com/dittusch">dittusch</a>, hawkfalcon, + <a href="https://twitter.com/iKeychain">iKeychain</a>, jwdred, <a href="https://www.nexusmods.com/users/12252523">Karmylla</a>, Pucklynn, Robby LaFarge, - Tarryn K., and a few anonymous users for their ongoing support; you're awesome! 🏅 </p> diff --git a/src/SMAPI.Web/Views/LogParser/Index.cshtml b/src/SMAPI.Web/Views/LogParser/Index.cshtml index 21adf35b..babd0bd3 100644 --- a/src/SMAPI.Web/Views/LogParser/Index.cshtml +++ b/src/SMAPI.Web/Views/LogParser/Index.cshtml @@ -17,16 +17,17 @@ { <meta name="robots" content="noindex" /> } - <link rel="stylesheet" href="~/Content/css/log-parser.css?r=20190221" /> + <link rel="stylesheet" href="~/Content/css/log-parser.css?r=20190314" /> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js" crossorigin="anonymous"></script> - <script src="~/Content/js/log-parser.js?r=20190221"></script> + <script src="~/Content/js/log-parser.js?r=20190310"></script> <script> $(function() { smapi.logParser({ logStarted: new Date(@Json.Serialize(Model.ParsedLog?.Timestamp)), showPopup: @Json.Serialize(Model.ParsedLog == null), showMods: @Json.Serialize(Model.ParsedLog?.Mods?.Select(p => Model.GetSlug(p.Name)).Distinct().ToDictionary(slug => slug, slug => true), noFormatting), + showSections: @Json.Serialize(Enum.GetNames(typeof(LogSection)).ToDictionary(section => section, section => false), noFormatting), showLevels: @Json.Serialize(defaultFilters, noFormatting), enableFilters: @Json.Serialize(!Model.ShowRaw) }, '@Model.SectionUrl'); @@ -261,16 +262,32 @@ else if (Model.ParsedLog?.IsValid == true) @foreach (var message in Model.ParsedLog.Messages) { string levelStr = message.Level.ToString().ToLower(); + string sectionStartClass = message.IsStartOfSection ? "section-start" : null; + string sectionFilter = message.Section != null && !message.IsStartOfSection ? $"&& sectionsAllow('{message.Section}')" : null; // filter the message by section if applicable - <tr class="@levelStr mod" v-show="filtersAllow('@Model.GetSlug(message.Mod)', '@levelStr')"> + <tr class="mod @levelStr @sectionStartClass" + @if (message.IsStartOfSection) + { + <text>v-on:click="toggleSection('@message.Section')"</text> + } + v-show="filtersAllow('@Model.GetSlug(message.Mod)', '@levelStr') @sectionFilter"> <td v-pre>@message.Time</td> <td v-pre>@message.Level.ToString().ToUpper()</td> <td v-pre data-title="@message.Mod">@message.Mod</td> - <td v-pre>@message.Text</td> + <td> + <span v-pre class="log-message-text">@message.Text</span> + @if (message.IsStartOfSection) + { + <span class="section-toggle-message"> + <template v-if="sectionsAllow('@message.Section')">This section is shown. Click here to hide it.</template> + <template v-else>This section is hidden. Click here to show it.</template> + </span> + } + </td> </tr> if (message.Repeated > 0) { - <tr class="@levelStr mod mod-repeat" v-show="filtersAllow('@Model.GetSlug(message.Mod)', '@levelStr')"> + <tr class="@levelStr mod mod-repeat" v-show="filtersAllow('@Model.GetSlug(message.Mod)', '@levelStr') @sectionFilter"> <td colspan="3"></td> <td v-pre><i>repeats [@message.Repeated] times.</i></td> </tr> diff --git a/src/SMAPI.Web/Views/Mods/Index.cshtml b/src/SMAPI.Web/Views/Mods/Index.cshtml index a30a0048..5592078c 100644 --- a/src/SMAPI.Web/Views/Mods/Index.cshtml +++ b/src/SMAPI.Web/Views/Mods/Index.cshtml @@ -1,14 +1,14 @@ @using Newtonsoft.Json @model StardewModdingAPI.Web.ViewModels.ModListModel @{ - ViewData["Title"] = "SMAPI mod compatibility"; + ViewData["Title"] = "Mod compatibility"; } @section Head { - <link rel="stylesheet" href="~/Content/css/mods.css?r=20190125" /> + <link rel="stylesheet" href="~/Content/css/mods.css?r=20190302" /> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/tablesorter@2.31.0/dist/js/jquery.tablesorter.combined.min.js" crossorigin="anonymous"></script> - <script src="~/Content/js/mods.js?r=20190125"></script> + <script src="~/Content/js/mods.js?r=20190302"></script> <script> $(function() { var data = @Json.Serialize(Model.Mods, new JsonSerializerSettings { Formatting = Formatting.None }); @@ -19,9 +19,9 @@ } <div id="intro"> - <p>This page lists all known SMAPI mods, whether they're compatible with the latest versions of Stardew Valley and SMAPI, and how to fix broken mods if possible. The list is updated every few days. (You can help <a href="https://stardewvalleywiki.com/Modding:SMAPI_compatibility">edit this list</a>!)</p> + <p>This page shows all known SMAPI mods and (incompatible) content packs, whether they work with the latest versions of Stardew Valley and SMAPI, and how to fix them if not. If a mod doesn't work after following the instructions below, check <a href="https://stardewvalleywiki.com/Modding:Player_Guide/Troubleshooting">the troubleshooting guide</a> or <a href="https://stardewvalleywiki.com/Modding:Player_Guide/Troubleshooting#Ask_for_help">ask for help</a>.</p> - <p>If a mod doesn't work after following the instructions below, check <a href="https://stardewvalleywiki.com/Modding:Player_Guide/Troubleshooting">the troubleshooting guide</a> or <a href="https://stardewvalleywiki.com/Modding:Player_Guide/Troubleshooting#Ask_for_help">ask for help</a>.</p> + <p>The list is updated every few days (you can help <a href="https://stardewvalleywiki.com/Modding:Mod_compatibility">update it</a>!). It doesn't include XNB mods (see <a href="https://stardewvalleywiki.com/Modding:Using_XNB_mods"><em>using XNB mods</em> on the wiki</a> instead) or compatible content packs.</p> @if (Model.BetaVersion != null) { @@ -61,7 +61,7 @@ <th>compatibility</th> <th v-show="showAdvanced">broke in</th> <th v-show="showAdvanced">code</th> - <th v-show="showAdvanced"><a href="http://smapi.io/3.0">3.0</a></th> + <th><small><a href="http://smapi.io/3.0">3.0 ready</a></small></th> <th> </th> </tr> </thead> @@ -93,10 +93,10 @@ <span v-if="mod.SourceUrl"><a v-bind:href="mod.SourceUrl">source</a></span> <span v-else class="mod-closed-source">no source</span> </td> - <td v-show="showAdvanced"> - <small v-if="mod.LatestCompatibility.Status == 'ok' || mod.LatestCompatibility.Status == 'unofficial' || mod.Smapi3Status == 'ok' || mod.Smapi3Status == 'soon' || mod.Smapi3Url"> - <a v-if="mod.Smapi3Url" v-bind:href="mod.Smapi3Url">{{mod.Smapi3DisplayText}}</a> - <template v-else>{{mod.Smapi3DisplayText}}</template> + <td class="smapi-3-col"> + <small v-if="mod.LatestCompatibility.Status == 'ok' || mod.LatestCompatibility.Status == 'unofficial' || mod.LatestCompatibility.Status == 'optional' || mod.Smapi3Status == 'ok' || mod.Smapi3Status == 'soon' || mod.Smapi3Url"> + <a v-if="mod.Smapi3Url" v-bind:href="mod.Smapi3Url" v-bind:title="mod.Smapi3Tooltip">{{mod.Smapi3DisplayText}}</a> + <span v-else v-bind:title="mod.Smapi3Tooltip">{{mod.Smapi3DisplayText}}</span> </small> </td> <td> diff --git a/src/SMAPI.Web/wwwroot/Content/css/log-parser.css b/src/SMAPI.Web/wwwroot/Content/css/log-parser.css index ea28cd7d..d5013207 100644 --- a/src/SMAPI.Web/wwwroot/Content/css/log-parser.css +++ b/src/SMAPI.Web/wwwroot/Content/css/log-parser.css @@ -219,6 +219,18 @@ table caption { font-weight: bold; } +#log .section-start { + cursor: pointer; +} + +#log .section-toggle-message { + color: blue; +} + +#log .log-message-text { + white-space: pre-wrap; +} + #log { border-spacing: 0; } @@ -233,7 +245,6 @@ table caption { border-bottom: 1px dotted #ccc; border-top: 2px solid #fff; vertical-align: top; - white-space: pre-wrap; } #log td:not(:last-child) { @@ -244,7 +255,6 @@ table caption { } #log td[data-title]:hover { - font-size: 1px; overflow: inherit; position: relative; } diff --git a/src/SMAPI.Web/wwwroot/Content/css/mods.css b/src/SMAPI.Web/wwwroot/Content/css/mods.css index f42800da..fc5fff47 100644 --- a/src/SMAPI.Web/wwwroot/Content/css/mods.css +++ b/src/SMAPI.Web/wwwroot/Content/css/mods.css @@ -6,7 +6,7 @@ } #intro { - width: 50em; + max-width: 60em; } #beta-blurb { @@ -135,3 +135,7 @@ table.wikitable > caption { #mod-list tr[data-status="workaround"] .mod-page-links { text-decoration: line-through; } + +#mod-list td.smapi-3-col span { + border-bottom: 1px dashed gray; +} diff --git a/src/SMAPI.Web/wwwroot/Content/js/log-parser.js b/src/SMAPI.Web/wwwroot/Content/js/log-parser.js index 0c654205..e87a1a5c 100644 --- a/src/SMAPI.Web/wwwroot/Content/js/log-parser.js +++ b/src/SMAPI.Web/wwwroot/Content/js/log-parser.js @@ -69,6 +69,13 @@ smapi.logParser = function (data, sectionUrl) { updateModFilters(); }, + toggleSection: function (name) { + if (!data.enableFilters) + return; + + this.showSections[name] = !this.showSections[name]; + }, + showAllMods: function () { if (!data.enableFilters) return; @@ -95,6 +102,10 @@ smapi.logParser = function (data, sectionUrl) { filtersAllow: function(modId, level) { return this.showMods[modId] !== false && this.showLevels[level] !== false; + }, + + sectionsAllow: function (section) { + return this.showSections[section] !== false; } } }); diff --git a/src/SMAPI.Web/wwwroot/Content/js/mods.js b/src/SMAPI.Web/wwwroot/Content/js/mods.js index 05114b00..874fbf25 100644 --- a/src/SMAPI.Web/wwwroot/Content/js/mods.js +++ b/src/SMAPI.Web/wwwroot/Content/js/mods.js @@ -102,15 +102,18 @@ smapi.modList = function (mods, enableBeta) { // set SMAPI 3.0 display text switch (mod.Smapi3Status) { case "ok": - mod.Smapi3DisplayText = "✓"; + mod.Smapi3DisplayText = "✓ yes"; + mod.Smapi3Tooltip = "The latest version of this mod is compatible with SMAPI 3.0."; break; case "broken": - mod.Smapi3DisplayText = "✖"; + mod.Smapi3DisplayText = "✖ no"; + mod.Smapi3Tooltip = "This mod will break in SMAPI 3.0; consider notifying the author."; break; default: mod.Smapi3DisplayText = "↻ " + mod.Smapi3Status; + mod.Smapi3Tooltip = "This mod has a pending update for SMAPI 3.0 which hasn't been released yet."; break; } diff --git a/src/SMAPI.Web/wwwroot/StardewModdingAPI.metadata.json b/src/SMAPI.Web/wwwroot/StardewModdingAPI.metadata.json index 818ff9fe..9de692fe 100644 --- a/src/SMAPI.Web/wwwroot/StardewModdingAPI.metadata.json +++ b/src/SMAPI.Web/wwwroot/StardewModdingAPI.metadata.json @@ -81,7 +81,8 @@ "JSON Assets": { "ID": "spacechase0.JsonAssets", - "Default | UpdateKey": "Nexus:1720" + "Default | UpdateKey": "Nexus:1720", + "1.3.1 | Status": "AssumeBroken" // causes runtime crashes }, "Mail Framework": { @@ -100,6 +101,12 @@ "Default | UpdateKey": "Nexus:1726" }, + "Rubydew": { + "ID": "bwdy.rubydew", + "SuppressWarnings": "UsesDynamic", // mod explicitly loads DLLs for Linux/Mac compatibility + "Default | UpdateKey": "Nexus:3656" + }, + "SpaceCore": { "ID": "spacechase0.SpaceCore", "Default | UpdateKey": "Nexus:1348" @@ -133,7 +140,7 @@ } }, - "Basic Sprinklers Improved": { + "Basic Sprinkler Improved": { "ID": "lrsk_sdvm_bsi.0117171308", "MapRemoteVersions": { "1.0.2": "1.0.1-release" } // manifest not updated }, @@ -143,27 +150,11 @@ "MapLocalVersions": { "1.0.1": "1.0.2" } }, - "Birthday Mail": { - "ID": "KathrynHazuka.BirthdayMail", - "FormerIDs": "005e02dc-d900-425c-9c68-1ff55c5a295d", // changed in 1.2.3-pathoschild-update - "MapRemoteVersions": { "1.3.1": "1.3" } // manifest not updated - }, - - "Casks Anywhere": { - "ID": "CasksAnywhere", - "MapLocalVersions": { "1.1-alpha": "1.1" } - }, - "Chefs Closet": { "ID": "Duder.ChefsCloset", "MapLocalVersions": { "1.3-1": "1.3" } }, - "Cobalt": { - "ID": "spacechase0.Cobalt", - "MapRemoteVersions": { "1.1.3": "1.1.2" } // not updated in manifest - }, - "Configurable Machines": { "ID": "21da6619-dc03-4660-9794-8e5b498f5b97", "MapLocalVersions": { "1.2-beta": "1.2" } @@ -174,11 +165,6 @@ "MapRemoteVersions": { "1.1": "1.0" } // not updated in manifest }, - "Customizable Cart Redux": { - "ID": "KoihimeNakamura.CCR", - "MapLocalVersions": { "1.1-20170917": "1.1" } - }, - "Custom Linens": { "ID": "Mevima.CustomLinens", "MapRemoteVersions": { "1.1": "1.0" } // manifest not updated @@ -194,41 +180,11 @@ "MapLocalVersions": { "1.1": "1.1.1" } }, - "Hunger Mod (skn)": { - "ID": "skn.HungerMod", - "MapRemoteVersions": { "1.2.1": "1.0" } // manifest not updated - }, - - "Idle Pause": { - "ID": "Veleek.IdlePause", - "MapRemoteVersions": { "1.2": "1.1" } // manifest not updated - }, - - "Item Auto Stacker": { - "ID": "cat.autostacker", - "MapRemoteVersions": { "1.0.1": "1.0" } // manifest not updated - }, - - "Move Faster": { - "ID": "shuaiz.MoveFasterMod", - "~1.0.1 | Status": "AssumeBroken" // doesn't do anything as of SDV 1.2.33 (bad Harmony patch?) - }, - "Multiple Sprites and Portraits On Rotation (File Loading)": { "ID": "FileLoading", "MapLocalVersions": { "1.1": "1.12" } }, - "Night Owl": { - "ID": "Omegasis.NightOwl", - "MapLocalVersions": { "2.1": "1.3" } // 1.3 had wrong version in manifest - }, - - "Point-and-Plant": { - "ID": "jwdred.PointAndPlant", - "MapRemoteVersions": { "1.0.3": "1.0.2" } // manifest not updated - }, - "Relationship Status": { "ID": "relationshipstatus", "MapRemoteVersions": { "1.0.5": "1.0.4" } // not updated in manifest @@ -239,12 +195,6 @@ "MapLocalVersions": { "1.1.2-release": "1.1.2" } }, - "Shop Expander": { - "ID": "Entoarox.ShopExpander", - "FormerIDs": "EntoaroxShopExpander", // changed in 1.5.2 - "MapRemoteVersions": { "1.6.0b": "1.6.0" } - }, - "Showcase Mod": { "ID": "Igorious.Showcase", "MapLocalVersions": { "0.9-500": "0.9" } @@ -256,16 +206,6 @@ "MapLocalVersions": { "0.0": "1.4" } }, - "Solar Eclipse Event": { - "ID": "KoihimeNakamura.SolarEclipseEvent", - "MapLocalVersions": { "1.3.1-20180131": "1.3.1" } - }, - - "Time Reminder": { - "ID": "KoihimeNakamura.TimeReminder", - "MapLocalVersions": { "1.0-20170314": "1.0.2" } - }, - /********* ** Obsolete @@ -294,6 +234,67 @@ "~ | StatusReasonPhrase": "debug mode was removed in SMAPI 1.0." }, + /********* + ** Broke in SDV 1.3.36 + *********/ + "2cute FarmCave": { + "ID": "taintedwheat.2CuteFarmCave", + "Default | UpdateKey": "Nexus:843", + "~2.0 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + }, + + "Ace's Expanded Caves - Default Cave": { + "ID": "Acerbicon.AECdefault", + "Default | UpdateKey": "Nexus:2131", + "~1.2.2 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + }, + + "Ace's Expanded Caves - Desert Cave": { + "ID": "Acerbicon.AECdesert", + "Default | UpdateKey": "Nexus:2131", + "~1.2.2 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + }, + + "Ace's Expanded Caves - Ice Cave": { + "ID": "Acerbicon.AECice", + "Default | UpdateKey": "Nexus:2131", + "~1.2.2 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + }, + + "Ace's Expanded Caves - Lava Cave": { + "ID": "Acerbicon.AEClava", + "Default | UpdateKey": "Nexus:2131", + "~1.2.2 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + }, + + "Ace's Expanded Caves - Slime Cave": { + "ID": "Acerbicon.AECslime", + "Default | UpdateKey": "Nexus:2131", + "~1.2.2 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + }, + + "Green Pastures Farm": { + "ID": "bugbuddy.GreenPasturesFarm", + "Default | UpdateKey": "Nexus:2326", + "~1.0 | Status": "AssumeBroken" // references deleted Content/weapons.xnb + }, + + "Immersive Farm 2": { + "ID": "zander.immersivefarm2", + "~2.0.1 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + }, + + "Karmylla's Immersive Map Edits": { + "ID": "Karmylla.ImmersiveMapEdits", + "Default | UpdateKey": "Nexus:1149", + "~2.4 | Status": "AssumeBroken" // references deleted Content/weapons.xnb + }, + + "Secret Gardens Greenhouse": { + "ID": "jessebot.secretgardens", + "Default | UpdateKey": "Nexus:3067", + "~2.0.1 | Status": "AssumeBroken" // references deleted Content/Mine.xnb + }, /********* ** Broke circa SDV 1.3 @@ -420,6 +421,14 @@ "Yet Another Harvest With Scythe Mod": { "ID": "bcmpinc.HarvestWithScythe", "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) + }, + + /********* + ** Broke circa SDV 1.2 + *********/ + "Move Faster": { + "ID": "shuaiz.MoveFasterMod", + "~1.0.1 | Status": "AssumeBroken" // doesn't do anything as of SDV 1.2.33 (bad Harmony patch?) } } } diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs index d90eecf7..ca541513 100644 --- a/src/SMAPI/Constants.cs +++ b/src/SMAPI/Constants.cs @@ -20,13 +20,13 @@ namespace StardewModdingAPI ** Public ****/ /// <summary>SMAPI's current semantic version.</summary> - public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("2.11.0"); + public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("2.11.1"); /// <summary>The minimum supported version of Stardew Valley.</summary> public static ISemanticVersion MinimumGameVersion { get; } = new GameVersion("1.3.36"); /// <summary>The maximum supported version of Stardew Valley.</summary> - public static ISemanticVersion MaximumGameVersion { get; } = null; + public static ISemanticVersion MaximumGameVersion { get; } = new GameVersion("1.3.36"); /// <summary>The target game platform.</summary> public static GamePlatform TargetPlatform => (GamePlatform)Constants.Platform; @@ -111,7 +111,7 @@ namespace StardewModdingAPI internal static string ModsPath { get; set; } /// <summary>The game's current semantic version.</summary> - internal static ISemanticVersion GameVersion { get; } = new GameVersion(Constants.GetGameVersion()); + internal static ISemanticVersion GameVersion { get; } = new GameVersion(Game1.version); /// <summary>The target game platform.</summary> internal static Platform Platform { get; } = EnvironmentUtility.DetectPlatform(); @@ -197,16 +197,6 @@ namespace StardewModdingAPI /********* ** Private methods *********/ - /// <summary>Get the game's current version string.</summary> - private static string GetGameVersion() - { - // we need reflection because it's a constant, so SMAPI's references to it are inlined at compile-time - FieldInfo field = typeof(Game1).GetField(nameof(Game1.version), BindingFlags.Public | BindingFlags.Static); - if (field == null) - throw new InvalidOperationException($"The {nameof(Game1)}.{nameof(Game1.version)} field could not be found."); - return (string)field.GetValue(null); - } - /// <summary>Get the name of the save folder, if any.</summary> internal static string GetSaveFolderName() { diff --git a/src/SMAPI/Framework/IModMetadata.cs b/src/SMAPI/Framework/IModMetadata.cs index 7ada7dea..38514959 100644 --- a/src/SMAPI/Framework/IModMetadata.cs +++ b/src/SMAPI/Framework/IModMetadata.cs @@ -98,5 +98,9 @@ namespace StardewModdingAPI.Framework /// <summary>Whether the mod has at least one valid update key set.</summary> bool HasValidUpdateKeys(); + + /// <summary>Get whether the mod has a given warning and it hasn't been suppressed in the <see cref="DataRecord"/>.</summary> + /// <param name="warning">The warning to check.</param> + bool HasUnsuppressWarning(ModWarning warning); } } diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs index 5e0571a0..878b3148 100644 --- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs +++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs @@ -8,6 +8,7 @@ using Mono.Cecil.Cil; using StardewModdingAPI.Framework.Exceptions; using StardewModdingAPI.Internal; using StardewModdingAPI.Metadata; +using StardewModdingAPI.Toolkit.Framework.ModData; namespace StardewModdingAPI.Framework.ModLoading { diff --git a/src/SMAPI/Framework/ModLoading/ModMetadata.cs b/src/SMAPI/Framework/ModLoading/ModMetadata.cs index 0cb62a75..4ff021b7 100644 --- a/src/SMAPI/Framework/ModLoading/ModMetadata.cs +++ b/src/SMAPI/Framework/ModLoading/ModMetadata.cs @@ -179,5 +179,14 @@ namespace StardewModdingAPI.Framework.ModLoading { return this.GetUpdateKeys(validOnly: true).Any(); } + + /// <summary>Get whether the mod has a given warning and it hasn't been suppressed in the <see cref="DataRecord"/>.</summary> + /// <param name="warning">The warning to check.</param> + public bool HasUnsuppressWarning(ModWarning warning) + { + return + this.Warnings.HasFlag(warning) + && (this.DataRecord?.DataRecord == null || !this.DataRecord.DataRecord.SuppressWarnings.HasFlag(warning)); + } } } diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index e0347eb2..9ffa46a5 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -1107,7 +1107,9 @@ namespace StardewModdingAPI.Framework // issue block format logic void LogWarningGroup(ModWarning warning, LogLevel logLevel, string heading, params string[] blurb) { - IModMetadata[] matches = modsWithWarnings.Where(p => p.Warnings.HasFlag(warning)).ToArray(); + IModMetadata[] matches = modsWithWarnings + .Where(mod => mod.HasUnsuppressWarning(warning)) + .ToArray(); if (!matches.Any()) return; diff --git a/src/SMAPI/StardewModdingAPI.csproj b/src/SMAPI/StardewModdingAPI.csproj index 6692bc02..b6562eca 100644 --- a/src/SMAPI/StardewModdingAPI.csproj +++ b/src/SMAPI/StardewModdingAPI.csproj @@ -228,7 +228,6 @@ <Compile Include="Framework\ModLoading\IInstructionHandler.cs" /> <Compile Include="Framework\ModLoading\IncompatibleInstructionException.cs" /> <Compile Include="Framework\ModLoading\InstructionHandleResult.cs" /> - <Compile Include="Framework\ModLoading\ModWarning.cs" /> <Compile Include="Framework\ModLoading\PlatformAssemblyMap.cs" /> <Compile Include="Framework\ModLoading\RewriteHelper.cs" /> <Compile Include="Framework\ModLoading\Rewriters\FieldReplaceRewriter.cs" /> diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs index d3a25845..ac279d88 100644 --- a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs +++ b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs @@ -39,7 +39,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki .WithArguments(new { action = "parse", - page = "Modding:SMAPI_compatibility", + page = "Modding:Mod_compatibility", format = "json" }) .As<ResponseModel>(); @@ -98,6 +98,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki string customSourceUrl = this.GetAttribute(node, "data-custom-source"); string customUrl = this.GetAttribute(node, "data-url"); string anchor = this.GetAttribute(node, "id"); + string contentPackFor = this.GetAttribute(node, "data-content-pack-for"); // parse stable compatibility WikiCompatibilityInfo compatibility = new WikiCompatibilityInfo @@ -142,6 +143,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki GitHubRepo = githubRepo, CustomSourceUrl = customSourceUrl, CustomUrl = customUrl, + ContentPackFor = contentPackFor, Compatibility = compatibility, BetaCompatibility = betaCompatibility, Smapi3Status = smapi3Status, diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs index b71269fe..35d43758 100644 --- a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs +++ b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs @@ -33,6 +33,9 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki /// <summary>The custom mod page URL (if applicable).</summary> public string CustomUrl { get; set; } + /// <summary>The name of the mod which loads this content pack, if applicable.</summary> + public string ContentPackFor { get; set; } + /// <summary>The mod's compatibility with the latest stable version of the game.</summary> public WikiCompatibilityInfo Compatibility { get; set; } diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataModel.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataModel.cs index e2b3ec1d..18039762 100644 --- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataModel.cs +++ b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataModel.cs @@ -20,13 +20,8 @@ namespace StardewModdingAPI.Toolkit.Framework.ModData /// <remarks> /// This uses a custom format which uniquely identifies a mod across multiple versions and /// supports matching other fields if no ID was specified. This doesn't include the latest - /// ID, if any. Format rules: - /// 1. If the mod's ID changed over time, multiple variants can be separated by the - /// <c>|</c> character. - /// 2. Each variant can take one of two forms: - /// - A simple string matching the mod's UniqueID value. - /// - A JSON structure containing any of four manifest fields (ID, Name, Author, and - /// EntryDll) to match. + /// ID, if any. If the mod's ID changed over time, multiple variants can be separated by the + /// <c>|</c> character. /// </remarks> public string FormerIDs { get; set; } @@ -36,6 +31,9 @@ namespace StardewModdingAPI.Toolkit.Framework.ModData /// <summary>Maps remote versions to a semantic version for update checks.</summary> public IDictionary<string, string> MapRemoteVersions { get; set; } = new Dictionary<string, string>(); + /// <summary>The mod warnings to suppress, even if they'd normally be shown.</summary> + public ModWarning SuppressWarnings { get; set; } + /// <summary>This field stores properties that aren't mapped to another field before they're parsed into <see cref="Fields"/>.</summary> [JsonExtensionData] public IDictionary<string, JToken> ExtensionData { get; set; } diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs index 3949f7dc..794ad2e4 100644 --- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs +++ b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecord.cs @@ -19,6 +19,9 @@ namespace StardewModdingAPI.Toolkit.Framework.ModData /// <summary>The former mod IDs (if any).</summary> public string[] FormerIDs { get; } + /// <summary>The mod warnings to suppress, even if they'd normally be shown.</summary> + public ModWarning SuppressWarnings { get; set; } + /// <summary>Maps local versions to a semantic version for update checks.</summary> public IDictionary<string, string> MapLocalVersions { get; } @@ -40,6 +43,7 @@ namespace StardewModdingAPI.Toolkit.Framework.ModData this.DisplayName = displayName; this.ID = model.ID; this.FormerIDs = model.GetFormerIDs().ToArray(); + this.SuppressWarnings = model.SuppressWarnings; this.MapLocalVersions = new Dictionary<string, string>(model.MapLocalVersions, StringComparer.InvariantCultureIgnoreCase); this.MapRemoteVersions = new Dictionary<string, string>(model.MapRemoteVersions, StringComparer.InvariantCultureIgnoreCase); this.Fields = model.GetFields().ToArray(); diff --git a/src/SMAPI/Framework/ModLoading/ModWarning.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModWarning.cs index e643cb05..d61c427f 100644 --- a/src/SMAPI/Framework/ModLoading/ModWarning.cs +++ b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModWarning.cs @@ -1,11 +1,10 @@ using System; -using StardewModdingAPI.Events; -namespace StardewModdingAPI.Framework.ModLoading +namespace StardewModdingAPI.Toolkit.Framework.ModData { /// <summary>Indicates a detected non-error mod issue.</summary> [Flags] - internal enum ModWarning + public enum ModWarning { /// <summary>No issues detected.</summary> None = 0, @@ -22,7 +21,7 @@ namespace StardewModdingAPI.Framework.ModLoading /// <summary>The mod uses the <c>dynamic</c> keyword which won't work on Linux/Mac.</summary> UsesDynamic = 8, - /// <summary>The mod references <see cref="ISpecialisedEvents.UnvalidatedUpdateTicking"/> or <see cref="ISpecialisedEvents.UnvalidatedUpdateTicked"/> which may impact stability.</summary> + /// <summary>The mod references specialised 'unvalided update tick' events which may impact stability.</summary> UsesUnvalidatedUpdateTick = 16, /// <summary>The mod has no update keys set.</summary> |