diff options
Diffstat (limited to 'src')
59 files changed, 2025 insertions, 445 deletions
diff --git a/src/SMAPI.Common/Models/ModSeachModel.cs b/src/SMAPI.Common/Models/ModSeachModel.cs index 13b05d2d..3c33d0b6 100644 --- a/src/SMAPI.Common/Models/ModSeachModel.cs +++ b/src/SMAPI.Common/Models/ModSeachModel.cs @@ -12,6 +12,9 @@ namespace StardewModdingAPI.Common.Models /// <summary>The namespaced mod keys to search.</summary> public string[] ModKeys { get; set; } + /// <summary>Whether to allow non-semantic versions, instead of returning an error for those.</summary> + public bool AllowInvalidVersions { get; set; } + /********* ** Public methods @@ -24,9 +27,11 @@ namespace StardewModdingAPI.Common.Models /// <summary>Construct an instance.</summary> /// <param name="modKeys">The namespaced mod keys to search.</param> - public ModSearchModel(IEnumerable<string> modKeys) + /// <param name="allowInvalidVersions">Whether to allow non-semantic versions, instead of returning an error for those.</param> + public ModSearchModel(IEnumerable<string> modKeys, bool allowInvalidVersions) { this.ModKeys = modKeys.ToArray(); + this.AllowInvalidVersions = allowInvalidVersions; } } } diff --git a/src/SMAPI.Common/SemanticVersionImpl.cs b/src/SMAPI.Common/SemanticVersionImpl.cs index 1c713b47..084f56a3 100644 --- a/src/SMAPI.Common/SemanticVersionImpl.cs +++ b/src/SMAPI.Common/SemanticVersionImpl.cs @@ -22,6 +22,9 @@ namespace StardewModdingAPI.Common /// <summary>An optional prerelease tag.</summary> public string Tag { get; } + /// <summary>A regex pattern matching a version within a larger string.</summary> + internal const string UnboundedVersionPattern = @"(?>(?<major>0|[1-9]\d*))\.(?>(?<minor>0|[1-9]\d*))(?>(?:\.(?<patch>0|[1-9]\d*))?)(?:-(?<prerelease>(?>[a-z0-9]+[\-\.]?)+))?"; + /// <summary>A regular expression matching a semantic version string.</summary> /// <remarks> /// This pattern is derived from the BNF documentation in the <a href="https://github.com/mojombo/semver">semver repo</a>, @@ -30,7 +33,7 @@ namespace StardewModdingAPI.Common /// - allows hyphens in prerelease tags as synonyms for dots (like "-unofficial-update.3"); /// - doesn't allow '+build' suffixes. /// </remarks> - internal static readonly Regex Regex = new Regex(@"^(?>(?<major>0|[1-9]\d*))\.(?>(?<minor>0|[1-9]\d*))(?>(?:\.(?<patch>0|[1-9]\d*))?)(?:-(?<prerelease>(?>[a-z0-9]+[\-\.]?)+))?$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture); + internal static readonly Regex Regex = new Regex($@"^{SemanticVersionImpl.UnboundedVersionPattern}$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture); /********* ** Public methods diff --git a/src/SMAPI.Installer/unix-launcher.sh b/src/SMAPI.Installer/unix-launcher.sh index 2542a286..6e796461 100644 --- a/src/SMAPI.Installer/unix-launcher.sh +++ b/src/SMAPI.Installer/unix-launcher.sh @@ -71,12 +71,12 @@ else else x-terminal-emulator -e "$LAUNCHER" fi + elif $COMMAND xterm 2>/dev/null; then + xterm -e "$LAUNCHER" elif $COMMAND xfce4-terminal 2>/dev/null; then xfce4-terminal -e "$LAUNCHER" elif $COMMAND gnome-terminal 2>/dev/null; then gnome-terminal -e "$LAUNCHER" - elif $COMMAND xterm 2>/dev/null; then - xterm -e "$LAUNCHER" elif $COMMAND konsole 2>/dev/null; then konsole -e "$LAUNCHER" elif $COMMAND terminal 2>/dev/null; then diff --git a/src/SMAPI.ModBuildConfig/build/smapi.targets b/src/SMAPI.ModBuildConfig/build/smapi.targets index 83f0dcbd..7e8bbfc3 100644 --- a/src/SMAPI.ModBuildConfig/build/smapi.targets +++ b/src/SMAPI.ModBuildConfig/build/smapi.targets @@ -67,6 +67,10 @@ <Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86"> <Private>false</Private> </Reference> + <Reference Include="Netcode" Condition="Exists('$(GamePath)\Netcode.dll')"> + <HintPath>$(GamePath)\Netcode.dll</HintPath> + <Private>False</Private> + </Reference> <Reference Include="Stardew Valley"> <HintPath>$(GamePath)\Stardew Valley.exe</HintPath> <Private>false</Private> diff --git a/src/SMAPI.ModBuildConfig/package.nuspec b/src/SMAPI.ModBuildConfig/package.nuspec index 91f38a29..8393ab61 100644 --- a/src/SMAPI.ModBuildConfig/package.nuspec +++ b/src/SMAPI.ModBuildConfig/package.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"> <metadata> <id>Pathoschild.Stardew.ModBuildConfig</id> - <version>2.0.2</version> + <version>2.0.3-alpha20180307</version> <title>Build package for SMAPI mods</title> <authors>Pathoschild</authors> <owners>Pathoschild</owners> @@ -26,6 +26,9 @@ 2.0.2: - Fixed compatibility issue on Linux. + + 2.0.3: + - Added support for Stardew Valley 1.3. </releaseNotes> </metadata> <files> diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs index 14a519fb..a6f42b98 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs @@ -54,7 +54,11 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player // apply quality if (match.Item is Object obj) +#if STARDEW_VALLEY_1_3 + obj.Quality = quality; +#else obj.quality = quality; +#endif else if (match.Item is Tool tool) tool.UpgradeLevel = quality; diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetColorCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetColorCommand.cs index 5d098593..aa4fd105 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetColorCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetColorCommand.cs @@ -1,4 +1,4 @@ -using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework; using StardewValley; namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player @@ -36,7 +36,11 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player switch (target) { case "hair": +#if STARDEW_VALLEY_1_3 + Game1.player.hairstyleColor.Value = color; +#else Game1.player.hairstyleColor = color; +#endif monitor.Log("OK, your hair color is updated.", LogLevel.Info); break; @@ -46,7 +50,11 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player break; case "pants": +#if STARDEW_VALLEY_1_3 + Game1.player.pantsColor.Value = color; +#else Game1.player.pantsColor = color; +#endif monitor.Log("OK, your pants color is updated.", LogLevel.Info); break; } diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetNameCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetNameCommand.cs index 5b1225e8..71e17f71 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetNameCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetNameCommand.cs @@ -1,4 +1,4 @@ -using StardewValley; +using StardewValley; namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player { @@ -39,7 +39,11 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player case "farm": if (!string.IsNullOrWhiteSpace(name)) { +#if STARDEW_VALLEY_1_3 + Game1.player.farmName.Value = args[1]; +#else Game1.player.farmName = args[1]; +#endif monitor.Log($"OK, your farm's name is now {Game1.player.farmName}.", LogLevel.Info); } else diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/DownMineLevelCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/DownMineLevelCommand.cs index da117006..c83c3b07 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/DownMineLevelCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/DownMineLevelCommand.cs @@ -1,4 +1,4 @@ -using StardewValley; +using StardewValley; using StardewValley.Locations; namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World @@ -21,7 +21,11 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World { int level = (Game1.currentLocation as MineShaft)?.mineLevel ?? 0; monitor.Log($"OK, warping you to mine level {level + 1}.", LogLevel.Info); +#if STARDEW_VALLEY_1_3 + Game1.enterMine(level + 1); +#else Game1.enterMine(false, level + 1, ""); +#endif } } } diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetMineLevelCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetMineLevelCommand.cs index 1024b7b6..5947af1a 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetMineLevelCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetMineLevelCommand.cs @@ -1,4 +1,4 @@ -using System; +using System; using StardewValley; namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World @@ -26,7 +26,11 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World // handle level = Math.Max(1, level); monitor.Log($"OK, warping you to mine level {level}.", LogLevel.Info); +#if STARDEW_VALLEY_1_3 + Game1.enterMine(level); +#else Game1.enterMine(true, level, ""); +#endif } } } diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs index b5fe9f2f..9c0981c4 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Microsoft.Xna.Framework; using StardewModdingAPI.Mods.ConsoleCommands.Framework.ItemData; using StardewValley; @@ -95,39 +95,90 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework // fruit products if (item.category == SObject.FruitsCategory) { - yield return new SearchableItem(ItemType.Object, this.CustomIDOffset + id, new SObject(348, 1) + // wine +#if STARDEW_VALLEY_1_3 + SObject wine = + new SObject(348, 1) + { + Name = $"{item.Name} Wine", + Price = item.price * 3 + }; + wine.preserve.Value = SObject.PreserveType.Wine; + wine.preservedParentSheetIndex.Value = item.parentSheetIndex; +#else + SObject wine = new SObject(348, 1) { name = $"{item.Name} Wine", price = item.price * 3, preserve = SObject.PreserveType.Wine, preservedParentSheetIndex = item.parentSheetIndex - }); - yield return new SearchableItem(ItemType.Object, this.CustomIDOffset * 2 + id, new SObject(344, 1) + }; +#endif + yield return new SearchableItem(ItemType.Object, this.CustomIDOffset + id, wine); + + // jelly +#if STARDEW_VALLEY_1_3 + SObject jelly = new SObject(344, 1) + { + Name = $"{item.Name} Jelly", + Price = 50 + item.Price * 2 + }; + jelly.preserve.Value = SObject.PreserveType.Jelly; + jelly.preservedParentSheetIndex.Value = item.parentSheetIndex; +#else + SObject jelly = new SObject(344, 1) { name = $"{item.Name} Jelly", price = 50 + item.Price * 2, preserve = SObject.PreserveType.Jelly, preservedParentSheetIndex = item.parentSheetIndex - }); + }; +#endif + yield return new SearchableItem(ItemType.Object, this.CustomIDOffset * 2 + id, jelly); } // vegetable products else if (item.category == SObject.VegetableCategory) { - yield return new SearchableItem(ItemType.Object, this.CustomIDOffset * 3 + id, new SObject(350, 1) + // juice +#if STARDEW_VALLEY_1_3 + SObject juice = new SObject(350, 1) + { + Name = $"{item.Name} Juice", + Price = (int)(item.price * 2.25d) + }; + juice.preserve.Value = SObject.PreserveType.Juice; + juice.preservedParentSheetIndex.Value = item.parentSheetIndex; +#else + SObject juice = new SObject(350, 1) { name = $"{item.Name} Juice", price = (int)(item.price * 2.25d), preserve = SObject.PreserveType.Juice, preservedParentSheetIndex = item.parentSheetIndex - }); - yield return new SearchableItem(ItemType.Object, this.CustomIDOffset * 4 + id, new SObject(342, 1) + }; +#endif + yield return new SearchableItem(ItemType.Object, this.CustomIDOffset * 3 + id, juice); + + // pickled +#if STARDEW_VALLEY_1_3 + SObject pickled = new SObject(342, 1) + { + Name = $"Pickled {item.Name}", + Price = 50 + item.Price * 2 + }; + pickled.preserve.Value = SObject.PreserveType.Pickle; + pickled.preservedParentSheetIndex.Value = item.parentSheetIndex; +#else + SObject pickled = new SObject(342, 1) { name = $"Pickled {item.Name}", price = 50 + item.Price * 2, preserve = SObject.PreserveType.Pickle, preservedParentSheetIndex = item.parentSheetIndex - }); + }; +#endif + yield return new SearchableItem(ItemType.Object, this.CustomIDOffset * 4 + id, pickled); } // flower honey @@ -160,6 +211,19 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework // yield honey if (type != null) { +#if STARDEW_VALLEY_1_3 + SObject honey = new SObject(Vector2.Zero, 340, item.Name + " Honey", false, true, false, false) + { + Name = "Wild Honey" + }; + honey.honeyType.Value = type; + + if (type != SObject.HoneyType.Wild) + { + honey.Name = $"{item.Name} Honey"; + honey.Price += item.Price * 2; + } +#else SObject honey = new SObject(Vector2.Zero, 340, item.Name + " Honey", false, true, false, false) { name = "Wild Honey", @@ -170,6 +234,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework honey.name = $"{item.Name} Honey"; honey.price += item.price * 2; } +#endif yield return new SearchableItem(ItemType.Object, this.CustomIDOffset * 5 + id, honey); } } diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json index f4b3884d..785af01a 100644 --- a/src/SMAPI.Mods.ConsoleCommands/manifest.json +++ b/src/SMAPI.Mods.ConsoleCommands/manifest.json @@ -1,7 +1,7 @@ { "Name": "Console Commands", "Author": "SMAPI", - "Version": "2.5.2", + "Version": "2.5.3", "Description": "Adds SMAPI console commands that let you manipulate the game.", "UniqueID": "SMAPI.ConsoleCommands", "EntryDll": "ConsoleCommands.dll" diff --git a/src/SMAPI.Web/Controllers/ModsApiController.cs b/src/SMAPI.Web/Controllers/ModsApiController.cs index dcb4ec52..abae7db7 100644 --- a/src/SMAPI.Web/Controllers/ModsApiController.cs +++ b/src/SMAPI.Web/Controllers/ModsApiController.cs @@ -64,14 +64,15 @@ namespace StardewModdingAPI.Web.Controllers /// <summary>Fetch version metadata for the given mods.</summary> /// <param name="modKeys">The namespaced mod keys to search as a comma-delimited array.</param> + /// <param name="allowInvalidVersions">Whether to allow non-semantic versions, instead of returning an error for those.</param> [HttpGet] - public async Task<IDictionary<string, ModInfoModel>> GetAsync(string modKeys) + public async Task<IDictionary<string, ModInfoModel>> GetAsync(string modKeys, bool allowInvalidVersions = false) { string[] modKeysArray = modKeys?.Split(',').ToArray(); if (modKeysArray == null || !modKeysArray.Any()) return new Dictionary<string, ModInfoModel>(); - return await this.PostAsync(new ModSearchModel(modKeysArray)); + return await this.PostAsync(new ModSearchModel(modKeysArray, allowInvalidVersions)); } /// <summary>Fetch version metadata for the given mods.</summary> @@ -79,7 +80,8 @@ namespace StardewModdingAPI.Web.Controllers [HttpPost] public async Task<IDictionary<string, ModInfoModel>> PostAsync([FromBody] ModSearchModel search) { - // sort & filter keys + // parse model + bool allowInvalidVersions = search?.AllowInvalidVersions ?? false; string[] modKeys = (search?.ModKeys?.ToArray() ?? new string[0]) .Distinct(StringComparer.CurrentCultureIgnoreCase) .OrderBy(p => p, StringComparer.CurrentCultureIgnoreCase) @@ -106,12 +108,20 @@ namespace StardewModdingAPI.Web.Controllers // fetch mod info result[modKey] = await this.Cache.GetOrCreateAsync($"{repository.VendorKey}:{modID}".ToLower(), async entry => { - entry.AbsoluteExpiration = DateTimeOffset.UtcNow.AddMinutes(this.CacheMinutes); - + // fetch info ModInfoModel info = await repository.GetModInfoAsync(modID); - if (info.Error == null && (info.Version == null || !Regex.IsMatch(info.Version, this.VersionRegex, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase))) - info = new ModInfoModel(info.Name, info.Version, info.Url, info.Version == null ? "Mod has no version number." : $"Mod has invalid semantic version '{info.Version}'."); + // validate + if (info.Error == null) + { + if (info.Version == null) + info = new ModInfoModel(info.Name, info.Version, info.Url, "Mod has no version number."); + if (!allowInvalidVersions && !Regex.IsMatch(info.Version, this.VersionRegex, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) + info = new ModInfoModel(info.Name, info.Version, info.Url, $"Mod has invalid semantic version '{info.Version}'."); + } + + // cache & return + entry.AbsoluteExpiration = DateTimeOffset.UtcNow.AddMinutes(this.CacheMinutes); return info; }); } diff --git a/src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishClient.cs b/src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishClient.cs ind |
