diff options
| author | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2019-02-08 18:20:03 -0500 |
|---|---|---|
| committer | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2019-02-08 18:20:03 -0500 |
| commit | 84b9f4336d5b0c7f269a7bfbb94042360574bbaa (patch) | |
| tree | 0a4d138f88522ca101bff739c8ade1f62c74fbfe /src | |
| parent | 79c616600576acf16f70daad68cc60a22cbbbf74 (diff) | |
| parent | 41f77f51c0203fa36c1e47cf67409244ed3c2ff2 (diff) | |
| download | SMAPI-84b9f4336d5b0c7f269a7bfbb94042360574bbaa.tar.gz SMAPI-84b9f4336d5b0c7f269a7bfbb94042360574bbaa.tar.bz2 SMAPI-84b9f4336d5b0c7f269a7bfbb94042360574bbaa.zip | |
Merge branch 'develop' into stable
Diffstat (limited to 'src')
23 files changed, 418 insertions, 186 deletions
diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json index 0341c390..b5fd0424 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.10.1", + "Version": "2.10.2", "Description": "Adds SMAPI console commands that let you manipulate the game.", "UniqueID": "SMAPI.ConsoleCommands", "EntryDll": "ConsoleCommands.dll", - "MinimumApiVersion": "2.10.1" + "MinimumApiVersion": "2.10.2" } diff --git a/src/SMAPI.Mods.SaveBackup/ModEntry.cs b/src/SMAPI.Mods.SaveBackup/ModEntry.cs index 56a86cd9..d10131b3 100644 --- a/src/SMAPI.Mods.SaveBackup/ModEntry.cs +++ b/src/SMAPI.Mods.SaveBackup/ModEntry.cs @@ -20,8 +20,11 @@ namespace StardewModdingAPI.Mods.SaveBackup /// <summary>The absolute path to the folder in which to store save backups.</summary> private readonly string BackupFolder = Path.Combine(Constants.ExecutionPath, "save-backups"); + /// <summary>A unique label for the save backup to create.</summary> + private readonly string BackupLabel = $"{DateTime.UtcNow:yyyy-MM-dd} - SMAPI {Constants.ApiVersion} with Stardew Valley {Game1.version}"; + /// <summary>The name of the save archive to create.</summary> - private readonly string FileName = $"{DateTime.UtcNow:yyyy-MM-dd} - SMAPI {Constants.ApiVersion} with Stardew Valley {Game1.version}.zip"; + private string FileName => $"{this.BackupLabel}.zip"; /********* @@ -59,8 +62,9 @@ namespace StardewModdingAPI.Mods.SaveBackup { // get target path FileInfo targetFile = new FileInfo(Path.Combine(backupFolder.FullName, this.FileName)); - if (targetFile.Exists) - targetFile.Delete(); //return; + DirectoryInfo fallbackDir = new DirectoryInfo(Path.Combine(backupFolder.FullName, this.BackupLabel)); + if (targetFile.Exists || fallbackDir.Exists) + return; // create zip // due to limitations with the bundled Mono on Mac, we can't reference System.IO.Compression. @@ -70,12 +74,23 @@ namespace StardewModdingAPI.Mods.SaveBackup case GamePlatform.Linux: case GamePlatform.Windows: { - Assembly coreAssembly = Assembly.Load("System.IO.Compression, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") ?? throw new InvalidOperationException("Can't load System.IO.Compression assembly."); - Assembly fsAssembly = Assembly.Load("System.IO.Compression.FileSystem, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") ?? throw new InvalidOperationException("Can't load System.IO.Compression assembly."); - Type compressionLevelType = coreAssembly.GetType("System.IO.Compression.CompressionLevel") ?? throw new InvalidOperationException("Can't load CompressionLevel type."); - Type zipFileType = fsAssembly.GetType("System.IO.Compression.ZipFile") ?? throw new InvalidOperationException("Can't load ZipFile type."); - MethodInfo createMethod = zipFileType.GetMethod("CreateFromDirectory", new[] { typeof(string), typeof(string), compressionLevelType, typeof(bool) }) ?? throw new InvalidOperationException("Can't load ZipFile.CreateFromDirectory method."); - createMethod.Invoke(null, new object[] { Constants.SavesPath, targetFile.FullName, CompressionLevel.Fastest, false }); + try + { + // create compressed backup + Assembly coreAssembly = Assembly.Load("System.IO.Compression, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") ?? throw new InvalidOperationException("Can't load System.IO.Compression assembly."); + Assembly fsAssembly = Assembly.Load("System.IO.Compression.FileSystem, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") ?? throw new InvalidOperationException("Can't load System.IO.Compression assembly."); + Type compressionLevelType = coreAssembly.GetType("System.IO.Compression.CompressionLevel") ?? throw new InvalidOperationException("Can't load CompressionLevel type."); + Type zipFileType = fsAssembly.GetType("System.IO.Compression.ZipFile") ?? throw new InvalidOperationException("Can't load ZipFile type."); + MethodInfo createMethod = zipFileType.GetMethod("CreateFromDirectory", new[] { typeof(string), typeof(string), compressionLevelType, typeof(bool) }) ?? throw new InvalidOperationException("Can't load ZipFile.CreateFromDirectory method."); + createMethod.Invoke(null, new object[] { Constants.SavesPath, targetFile.FullName, CompressionLevel.Fastest, false }); + } + catch (Exception ex) when (ex is TypeLoadException || ex.InnerException is TypeLoadException) + { + // create uncompressed backup if compression fails + this.Monitor.Log("Couldn't zip the save backup, creating uncompressed backup instead."); + this.Monitor.Log(ex.ToString(), LogLevel.Trace); + this.RecursiveCopy(new DirectoryInfo(Constants.SavesPath), fallbackDir, copyRoot: false); + } } break; @@ -132,5 +147,32 @@ namespace StardewModdingAPI.Mods.SaveBackup this.Monitor.Log(ex.ToString(), LogLevel.Trace); } } + + /// <summary>Recursively copy a directory or file.</summary> + /// <param name="source">The file or folder to copy.</param> + /// <param name="targetFolder">The folder to copy into.</param> + /// <param name="copyRoot">Whether to copy the root folder itself, or <c>false</c> to only copy its contents.</param> + /// <remarks>Derived from the SMAPI installer code.</remarks> + private void RecursiveCopy(FileSystemInfo source, DirectoryInfo targetFolder, bool copyRoot = true) + { + if (!targetFolder.Exists) + targetFolder.Create(); + + switch (source) + { + case FileInfo sourceFile: + sourceFile.CopyTo(Path.Combine(targetFolder.FullName, sourceFile.Name)); + break; + + case DirectoryInfo sourceDir: + DirectoryInfo targetSubfolder = copyRoot ? new DirectoryInfo(Path.Combine(targetFolder.FullName, sourceDir.Name)) : targetFolder; + foreach (var entry in sourceDir.EnumerateFileSystemInfos()) + this.RecursiveCopy(entry, targetSubfolder); + break; + + default: + throw new NotSupportedException($"Unknown filesystem info type '{source.GetType().FullName}'."); + } + } } } diff --git a/src/SMAPI.Mods.SaveBackup/manifest.json b/src/SMAPI.Mods.SaveBackup/manifest.json index b2b9ad4b..7ac537ca 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.10.1", + "Version": "2.10.2", "Description": "Automatically backs up all your saves once per day into its folder.", "UniqueID": "SMAPI.SaveBackup", "EntryDll": "SaveBackup.dll", - "MinimumApiVersion": "2.10.1" + "MinimumApiVersion": "2.10.2" } diff --git a/src/SMAPI.Web/Startup.cs b/src/SMAPI.Web/Startup.cs index 91553513..a2e47482 100644 --- a/src/SMAPI.Web/Startup.cs +++ b/src/SMAPI.Web/Startup.cs @@ -161,12 +161,13 @@ namespace StardewModdingAPI.Web )); // shortcut redirects + redirects.Add(new RedirectToUrlRule(@"^/3\.0\.?$", "https://stardewvalleywiki.com/Modding:Migrate_to_SMAPI_3.0")); redirects.Add(new RedirectToUrlRule(@"^/buildmsg(?:/?(.*))$", "https://github.com/Pathoschild/SMAPI/blob/develop/docs/mod-build-config.md#$1")); redirects.Add(new RedirectToUrlRule(@"^/compat\.?$", "https://mods.smapi.io")); - redirects.Add(new RedirectToUrlRule(@"^/3\.0\.?$", "https://stardewvalleywiki.com/Modding:Migrate_to_SMAPI_3.0")); redirects.Add(new RedirectToUrlRule(@"^/docs\.?$", "https://stardewvalleywiki.com/Modding:Index")); redirects.Add(new RedirectToUrlRule(@"^/install\.?$", "https://stardewvalleywiki.com/Modding:Player_Guide/Getting_Started#Install_SMAPI")); redirects.Add(new RedirectToUrlRule(@"^/troubleshoot(.*)$", "https://stardewvalleywiki.com/Modding:Player_Guide/Troubleshooting$1")); + redirects.Add(new RedirectToUrlRule(@"^/xnb\.?$", "https://stardewvalleywiki.com/Modding:Using_XNB_mods")); // redirect legacy canimod.com URLs var wikiRedirects = new Dictionary<string, string[]> diff --git a/src/SMAPI.Web/ViewModels/ModModel.cs b/src/SMAPI.Web/ViewModels/ModModel.cs index f1a52f98..ae81acf5 100644 --- a/src/SMAPI.Web/ViewModels/ModModel.cs +++ b/src/SMAPI.Web/ViewModels/ModModel.cs @@ -107,7 +107,7 @@ namespace StardewModdingAPI.Web.ViewModels if (entry.ModDropID.HasValue) { anyFound = true; - yield return new ModLinkModel($"https://www.moddrop.com/sdv/mod/467243/{entry.ModDropID}", "ModDrop"); + yield return new ModLinkModel($"https://www.moddrop.com/sdv/mod/{entry.ModDropID}", "ModDrop"); } // fallback diff --git a/src/SMAPI.Web/Views/Mods/Index.cshtml b/src/SMAPI.Web/Views/Mods/Index.cshtml index a6c94cf1..a30a0048 100644 --- a/src/SMAPI.Web/Views/Mods/Index.cshtml +++ b/src/SMAPI.Web/Views/Mods/Index.cshtml @@ -4,15 +4,16 @@ ViewData["Title"] = "SMAPI mod compatibility"; } @section Head { - <link rel="stylesheet" href="~/Content/css/mods.css?r=20181122" /> + <link rel="stylesheet" href="~/Content/css/mods.css?r=20190125" /> <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=20181122"></script> + <script src="~/Content/js/mods.js?r=20190125"></script> <script> $(function() { var data = @Json.Serialize(Model.Mods, new JsonSerializerSettings { Formatting = Formatting.None }); - smapi.modList(data); + var enableBeta = @Json.Serialize(Model.BetaVersion != null); + smapi.modList(data, enableBeta); }); </script> } @@ -39,7 +40,7 @@ <label for="show-advanced">show advanced info and options</label> <div id="filters" v-show="showAdvanced"> <div v-for="(filterGroup, key) in filters"> - {{key}}: <span v-for="filter in filterGroup" v-bind:class="{ active: filter.value }"><input type="checkbox" v-bind:id="filter.id" v-model="filter.value" v-on:change="applyFilters" /> <label v-bind:for="filter.id">{{filter.label}}</label></span> + {{filterGroup.label}}: <span v-for="filter in filterGroup.value" v-bind:class="{ active: filter.value }"><input type="checkbox" v-bind:id="filter.id" v-model="filter.value" v-on:change="applyFilters" /> <label v-bind:for="filter.id">{{filter.label}}</label></span> </div> </div> </div> @@ -93,12 +94,10 @@ <span v-else class="mod-closed-source">no source</span> </td> <td v-show="showAdvanced"> - <template v-if="mod.LatestCompatibility.Status == 'ok' || mod.LatestCompatibility.Status == 'unofficial' || mod.Smapi3Status == 'ok' || mod.Smapi3Status == 'soon'"> - <small v-if="mod.Smapi3Status == 'ok'">✓</small> - <small v-else-if="mod.Smapi3Status == 'broken'">✖</small> - <small v-else-if="mod.Smapi3Status == 'soon' && mod.Smapi3Url"><a v-bind:href="mod.Smapi3Url">↻ soon</a></small> - <small v-else>↻ {{mod.Smapi3Status}}</small> - </template> + <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> + </small> </td> <td> <small><a v-bind:href="'#' + mod.Slug">#</a></small> diff --git a/src/SMAPI.Web/wwwroot/Content/js/mods.js b/src/SMAPI.Web/wwwroot/Content/js/mods.js index 28992908..05114b00 100644 --- a/src/SMAPI.Web/wwwroot/Content/js/mods.js +++ b/src/SMAPI.Web/wwwroot/Content/js/mods.js @@ -2,7 +2,7 @@ var smapi = smapi || {}; var app; -smapi.modList = function (mods) { +smapi.modList = function (mods, enableBeta) { // init data var defaultStats = { total: 0, @@ -23,101 +23,73 @@ smapi.modList = function (mods) { visibleStats: $.extend({}, defaultStats), filters: { source: { - open: { - label: "open", - id: "show-open-source", - value: true - }, - closed: { - label: "closed", - id: "show-closed-source", - value: true + value: { + open: { value: true }, + closed: { value: true } } }, status: { - ok: { - label: "ok", - id: "show-status-ok", - value: true - }, - optional: { - label: "optional", - id: "show-status-optional", - value: true - }, - unofficial: { - label: "unofficial", - id: "show-status-unofficial", - value: true - }, - workaround: { - label: "workaround", - id: "show-status-workaround", - value: true - }, - broken: { - label: "broken", - id: "show-status-broken", - value: true - }, - abandoned: { - label: "abandoned", - id: "show-status-abandoned", - value: true - }, - obsolete: { - label: "obsolete", - id: "show-status-obsolete", - value: true + label: enableBeta ? "main status" : "status", + value: { + // note: keys must match status returned by the API + ok: { value: true }, + optional: { value: true }, + unofficial: { value: true }, + workaround: { value: true }, + broken: { value: true }, + abandoned: { value: true }, + obsolete: { value: true } } }, + betaStatus: { + label: "beta status", + value: {} // cloned from status field if needed + }, download: { - chucklefish: { - label: "Chucklefish", - id: "show-chucklefish", - value: true - }, - moddrop: { - label: "ModDrop", - id: "show-moddrop", - value: true - }, - nexus: { - label: "Nexus", - id: "show-nexus", - value: true - }, - custom: { - label: "custom", - id: "show-custom", - value: true + value: { + chucklefish: { value: true, label: "Chucklefish" }, + moddrop: { value: true, label: "ModDrop" }, + nexus: { value: true, label: "Nexus" }, + custom: { value: true } } }, - "SMAPI 3.0": { - ok: { - label: "ready", - id: "show-smapi-3-ready", - value: true - }, - soon: { - label: "soon", - id: "show-smapi-3-soon", - value: true - }, - broken: { - label: "broken", - id: "show-smapi-3-broken", - value: true - }, - unknown: { - label: "unknown", - id: "show-smapi-3-unknown", - value: true + smapi3: { + label: "SMAPI 3.0", + value: { + // note: keys must match status returned by the API + ok: { value: true, label: "ready" }, + soon: { value: true }, + broken: { value: true }, + unknown: { value: true } } } }, search: "" }; + + // init filters + Object.entries(data.filters).forEach(([groupKey, filterGroup]) => { + filterGroup.label = filterGroup.label || groupKey; + Object.entries(filterGroup.value).forEach(([filterKey, filter]) => { + filter.id = ("filter_" + groupKey + "_" + filterKey).replace(/[^a-zA-Z0-9]/g, "_"); + filter.label = filter.label || filterKey; + }); + }); + + // init beta filters + if (enableBeta) { + var filterGroup = data.filters.betaStatus; + $.extend(true, filterGroup.value, data.filters.status.value); + Object.entries(filterGroup.value).forEach(([filterKey, filter]) => { + filter.id = "beta_" + filter.id; + }); + } + else + delete data.filters.betaStatus; + + window.boop = data.filters; + + // init mods for (var i = 0; i < data.mods.length; i++) { var mod = mods[i]; @@ -127,6 +99,21 @@ smapi.modList = function (mods) { // set overall compatibility mod.LatestCompatibility = mod.BetaCompatibility || mod.Compatibility; + // set SMAPI 3.0 display text + switch (mod.Smapi3Status) { + case "ok": + mod.Smapi3DisplayText = "✓"; + break; + + case "broken": + mod.Smapi3DisplayText = "✖"; + break; + + default: + mod.Smapi3DisplayText = "↻ " + mod.Smapi3Status; + break; + } + // concatenate searchable text mod.SearchableText = [mod.Name, mod.AlternateNames, mod.Author, mod.AlternateAuthors, mod.Compatibility.Summary, mod.BrokeIn]; if (mod.Compatibility.UnofficialVersion) @@ -199,30 +186,37 @@ smapi.modList = function (mods) { var filters = data.filters; // check source - if (!filters.source.open.value && mod.SourceUrl) + if (!filters.source.value.open.value && mod.SourceUrl) return false; - if (!filters.source.closed.value && !mod.SourceUrl) + if (!filters.source.value.closed.value && !mod.SourceUrl) return false; // check status - var status = mod.LatestCompatibility.Status; - if (filters.status[status] && !filters.status[status].value) + var mainStatus = mod.Compatibility.Status; + if (filters.status.value[mainStatus] && !filters.status.value[mainStatus].value) return false; + // check beta status + if (enableBeta) { + var betaStatus = mod.LatestCompatibility.Status; + if (filters.betaStatus.value[betaStatus] && !filters.betaStatus.value[betaStatus].value) + return false; + } + // check SMAPI 3.0 compatibility - if (filters["SMAPI 3.0"][mod.Smapi3Status] && !filters["SMAPI 3.0"][mod.Smapi3Status].value) + if (filters.smapi3.value[mod.Smapi3Status] && !filters.smapi3.value[mod.Smapi3Status].value) return false; // check download sites var ignoreSites = []; - if (!filters.download.chucklefish.value) + if (!filters.download.value.chucklefish.value) ignoreSites.push("Chucklefish"); - if (!filters.download.moddrop.value) + if (!filters.download.value.moddrop.value) ignoreSites.push("ModDrop"); - if (!filters.download.nexus.value) + if (!filters.download.value.nexus.value) ignoreSites.push("Nexus"); - if (!filters.download.custom.value) + if (!filters.download.value.custom.value) ignoreSites.push("custom"); if (ignoreSites.length) { diff --git a/src/SMAPI.Web/wwwroot/StardewModdingAPI.metadata.json b/src/SMAPI.Web/wwwroot/StardewModdingAPI.metadata.json index b16cb99f..45a4959d 100644 --- a/src/SMAPI.Web/wwwroot/StardewModdingAPI.metadata.json +++ b/src/SMAPI.Web/wwwroot/StardewModdingAPI.metadata.json @@ -52,6 +52,70 @@ */ "ModData": { /********* + ** Common dependencies for friendly errors + *********/ + "Advanced Location Loader": { + "ID": "Entoarox.AdvancedLocationLoader", + "Default | UpdateKey": "Nexus:2270" + }, + + "Content Patcher": { + "ID": "Pathoschild.ContentPatcher", + "Default | UpdateKey": "Nexus:1915" + }, + + "Custom Farming Redux": { + "ID": "Platonymous.CustomFarming", + "Default | UpdateKey": "Nexus:991" + }, + + "Custom Shirts": { + "ID": "Platonymous.CustomShirts", + "Default | UpdateKey": "Nexus:2416" + }, + + "Entoarox Framework": { + "ID": "Entoarox.EntoaroxFramework", + "Default | UpdateKey": "Nexus:2269" + }, + + "JSON Assets": { + "ID": "spacechase0.JsonAssets", + "Default | UpdateKey": "Nexus:1720" + }, + + "Mail Framework": { + "ID": "DIGUS.MailFrameworkMod", + "Default | UpdateKey": "Nexus:1536" + }, + + "MTN": { + "ID": "SgtPickles.MTN", + "Default | UpdateKey": "Nexus:2256", + "~1.2.6 | Status": "AssumeBroken" // replaces Game1.multiplayer, which breaks SMAPI's multiplayer API. + }, + + "PyTK": { + "ID": "Platonymous.Toolkit", + "Default | UpdateKey": "Nexus:1726" + }, + + "SpaceCore": { + "ID": "spacechase0.SpaceCore", + "Default | UpdateKey": "Nexus:1348" + }, + + "Stardust Core": { + "ID": "Omegasis.StardustCore", + "Default | UpdateKey": "Nexus:2341" + }, + + "TMX Loader": { + "ID": "Platonymous.TMXLoader", + "Default | UpdateKey": "Nexus:1820" + }, + + /********* ** Content packs *********/ "Canon-Friendly Dialogue Expansion": { @@ -82,6 +146,11 @@ } }, + "Always Scroll Map": { + "ID": "bcmpinc.AlwaysScrollMap", + "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) + }, + "Animal Mood Fix": { "ID": "GPeters-AnimalMoodFix", "~ | Status": "Obsolete", @@ -151,6 +220,11 @@ "MapLocalVersions": { "1.2-beta": "1.2" } }, + "Craft Counter": { + "ID": "bcmpinc.CraftCounter", + "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) + }, + "Crafting Counter": { "ID": "lolpcgaming.CraftingCounter", "MapRemoteVersions": { "1.1": "1.0" } // not updated in manifest @@ -172,11 +246,6 @@ "MapRemoteVersions": { "1.1": "1.0" } // manifest not updated }, - "Custom Shirts": { - "ID": "Platonymous.CustomShirts", - "Default | UpdateKey": "Nexus:2416" // keep for dependencies - }, - "Dynamic Horses": { "ID": "Bpendragon-DynamicHorses", "MapRemoteVersions": { "1.2": "1.1-release" } // manifest not updated @@ -207,6 +276,11 @@ "~1.1 | Status": "AssumeBroken" // runtime errors with Harmony 1.2.0.1 in SMAPI 2.8+ }, + "Fix Animal Tools": { + "ID": "bcmpinc.FixAnimalTools", + "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) + }, + "Fix Scythe Exp": { "ID": "bcmpinc.FixScytheExp", "~0.3 | Status": "AssumeBroken" // broke in 1.3: Exception from HarmonyInstance "bcmpinc.FixScytheExp" [...] Bad label content in ILGenerator. @@ -219,7 +293,7 @@ "Grass Growth": { "ID": "bcmpinc.GrassGrowth", - "~0.3 | Status": "AssumeBroken" // broke in 1.3.29 (runtime errors: System.IndexOutOfRangeException: Could not find instruction sequence) + "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) }, "Hunger Mod (skn)": { @@ -258,9 +332,9 @@ "~1.0.1 | Status": "AssumeBroken" // doesn't do anything as of SDV 1.2.33 (bad Harmony patch?) }, - "MTN": { - "ID": "SgtPickles.MTN", - "~1.2.5 | Status": "AssumeBroken" // replaces Game1.multiplayer, which breaks SMAPI's multiplayer API. + "Movement Speed": { + "ID": "bcmpinc.MovementSpeed", + "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) }, "Multiple Sprites and Portraits On Rotation (File Loading)": { @@ -290,11 +364,6 @@ "Default | UpdateKey": "GitHub:lambui/StardewValleyMod_OmniFarm" }, - "PyTK - Platonymous Toolkit": { - "ID": "Platonymous.Toolkit", - "Default | UpdateKey": "Nexus:1726" - }, - "Point-and-Plant": { "ID": "jwdred.PointAndPlant", "MapRemoteVersions": { "1.0.3": "1.0.2" } // manifest not updated @@ -364,6 +433,11 @@ "~3.0.1 | Status": "AssumeBroken" // broke in SMAPI 2.6-beta.16 due to reflection into SMAPI internals }, + "Stardew Hack": { + "ID": "bcmpinc.StardewHack", + "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) + }, + "Stardew Notification": { "ID": "stardewnotification", "Default | UpdateKey": "GitHub:monopandora/StardewNotification" @@ -381,6 +455,11 @@ "~1.0.2 | Status": "AssumeBroken" // broke in SDV 1.3 (runtime errors) }, + "Tilled Soil Decay": { + "ID": "bcmpinc.TilledSoilDecay", + "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) + }, + "Time Reminder": { "ID": "KoihimeNakamura.TimeReminder", "MapLocalVersions": { "1.0-20170314": "1.0.2" } @@ -391,11 +470,21 @@ "Default | UpdateKey": "GitHub:mralbobo/stardew-tool-charging" }, + "Tree Spread": { + "ID": "bcmpinc.TreeSpread", + "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) + }, + "Variable Grass": { "ID": "dantheman999.VariableGrass", "Default | UpdateKey": "GitHub:dantheman999301/StardewMods" }, + "Yet Another Harvest With Scythe Mod": { + "ID": "bcmpinc.HarvestWithScythe", + "~0.6 | Status": "AssumeBroken" // breaks newer versions of bcmpinc mods (per bcmpinc's request) + }, + "Zoom Out Extreme": { "ID": "RockinMods.ZoomMod", "FormerIDs": "ZoomMod", // changed circa 1.2.1 diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs index a0ba67ab..51c15269 100644 --- a/src/SMAPI/Constants.cs +++ b/src/SMAPI/Constants.cs @@ -2,6 +2,7 @@ using System; using System.IO; using System.Linq; using System.Reflection; +using StardewModdingAPI.Enums; using StardewModdingAPI.Framework; using StardewModdingAPI.Framework.ModLoading; using StardewModdingAPI.Internal; @@ -13,29 +14,19 @@ namespace StardewModdingAPI public static class Constants { /********* - ** Fields - *********/ - /// <summary>The directory path containing the current save's data (if a save is loaded).</summary> - private static string RawSavePath => Context.IsSaveLoaded ? Path.Combine(Constants.SavesPath, Constants.GetSaveFolderName()) : null; - - /// <summary>Whether the directory containing the current save's data exists on disk.</summary> - private static bool SavePathReady => Context.IsSaveLoaded && Directory.Exists(Constants.RawSavePath); - - - /********* ** Accessors *********/ /**** ** Public ****/ /// <summary>SMAPI's current semantic version.</summary> - public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("2.10.1"); + public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("2.10.2"); /// <summary>The minimum supported version of Stardew Valley.</summary> public static ISemanticVersion MinimumGameVersion { get; } = new GameVersion("1.3.32"); /// <summary>The maximum supported version of Stardew Valley.</summary> - public static ISemanticVersion MaximumGameVersion { get; } = null; + public static ISemanticVersion MaximumGameVersion { get; } = new GameVersion("1.3.33"); /// <summary>The target game platform.</summary> public static GamePlatform TargetPlatform => (GamePlatform)Constants.Platform; @@ -52,11 +43,33 @@ namespace StardewModdingAPI /// <summary>The directory path where all saves are stored.</summary> public static string SavesPath { get; } = Path.Combine(Constants.DataPath, "Saves"); - /// <summary>The directory name containing the current save's data (if a save is loaded and the directory exists).</summary> |
