diff options
Diffstat (limited to 'src/SMAPI')
-rw-r--r-- | src/SMAPI/Constants.cs | 2 | ||||
-rw-r--r-- | src/SMAPI/Framework/ContentManagers/ModContentManager.cs | 2 | ||||
-rw-r--r-- | src/SMAPI/Framework/DeprecationManager.cs | 2 | ||||
-rw-r--r-- | src/SMAPI/Framework/Monitor.cs | 2 | ||||
-rw-r--r-- | src/SMAPI/Framework/SCore.cs | 13 | ||||
-rw-r--r-- | src/SMAPI/Framework/SGame.cs | 4 | ||||
-rw-r--r-- | src/SMAPI/IMonitor.cs | 2 | ||||
-rw-r--r-- | src/SMAPI/Patches/DialogueErrorPatch.cs | 49 | ||||
-rw-r--r-- | src/SMAPI/Patches/EventErrorPatch.cs | 84 | ||||
-rw-r--r-- | src/SMAPI/Patches/LoadContextPatch.cs (renamed from src/SMAPI/Patches/LoadForNewGamePatch.cs) | 49 | ||||
-rw-r--r-- | src/SMAPI/Patches/ObjectErrorPatch.cs | 32 | ||||
-rw-r--r-- | src/SMAPI/Program.cs | 16 | ||||
-rw-r--r-- | src/SMAPI/StardewModdingAPI.config.json | 114 | ||||
-rw-r--r-- | src/SMAPI/StardewModdingAPI.csproj | 380 |
14 files changed, 285 insertions, 466 deletions
diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs index cb3aa26e..9d686e2f 100644 --- a/src/SMAPI/Constants.cs +++ b/src/SMAPI/Constants.cs @@ -20,7 +20,7 @@ namespace StardewModdingAPI ** Public ****/ /// <summary>SMAPI's current semantic version.</summary> - public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("2.11.2"); + public static ISemanticVersion ApiVersion { get; } = new Toolkit.SemanticVersion("2.11.3"); /// <summary>The minimum supported version of Stardew Valley.</summary> public static ISemanticVersion MinimumGameVersion { get; } = new GameVersion("1.3.36"); diff --git a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs index 6485b3d4..2c50ec04 100644 --- a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs @@ -136,7 +136,7 @@ namespace StardewModdingAPI.Framework.ContentManagers throw GetContentError($"can't read unpacked map file directly from the underlying content manager. It must be loaded through the mod's {typeof(IModHelper)}.{nameof(IModHelper.Content)} helper."); default: - throw GetContentError($"unknown file extension '{file.Extension}'; must be one of '.png', '.tbin', or '.xnb'."); + throw GetContentError($"unknown file extension '{file.Extension}'; must be one of '.json', '.png', '.tbin', or '.xnb'."); } } catch (Exception ex) when (!(ex is SContentLoadException)) diff --git a/src/SMAPI/Framework/DeprecationManager.cs b/src/SMAPI/Framework/DeprecationManager.cs index 3153bbb4..984bb487 100644 --- a/src/SMAPI/Framework/DeprecationManager.cs +++ b/src/SMAPI/Framework/DeprecationManager.cs @@ -132,7 +132,7 @@ namespace StardewModdingAPI.Framework else { this.Monitor.Log(message, level); - this.Monitor.Log(warning.StackTrace); + this.Monitor.Log(warning.StackTrace, LogLevel.Debug); } } } diff --git a/src/SMAPI/Framework/Monitor.cs b/src/SMAPI/Framework/Monitor.cs index 47ebc2d7..617bfd85 100644 --- a/src/SMAPI/Framework/Monitor.cs +++ b/src/SMAPI/Framework/Monitor.cs @@ -78,7 +78,7 @@ namespace StardewModdingAPI.Framework /// <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> - public void Log(string message, LogLevel level = LogLevel.Debug) + public void Log(string message, LogLevel level = LogLevel.Trace) { this.LogImpl(this.Source, message, (ConsoleLogLevel)level); } diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 9ffa46a5..5dd52992 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -160,7 +160,7 @@ namespace StardewModdingAPI.Framework // init logging this.Monitor.Log($"SMAPI {Constants.ApiVersion} with Stardew Valley {Constants.GameVersion} on {EnvironmentUtility.GetFriendlyPlatformName(Constants.Platform)}", LogLevel.Info); - this.Monitor.Log($"Mods go here: {modsPath}"); + this.Monitor.Log($"Mods go here: {modsPath}", LogLevel.Info); if (modsPath != Constants.DefaultModsPath) this.Monitor.Log("(Using custom --mods-path argument.)", LogLevel.Trace); this.Monitor.Log($"Log started at {DateTime.UtcNow:s} UTC", LogLevel.Trace); @@ -233,9 +233,10 @@ namespace StardewModdingAPI.Framework // apply game patches new GamePatcher(this.Monitor).Apply( + new EventErrorPatch(this.MonitorForGame), new DialogueErrorPatch(this.MonitorForGame, this.Reflection), new ObjectErrorPatch(), - new LoadForNewGamePatch(this.Reflection, this.GameInstance.OnLoadStageChanged) + new LoadContextPatch(this.Reflection, this.GameInstance.OnLoadStageChanged) ); // add exit handler @@ -251,7 +252,7 @@ namespace StardewModdingAPI.Framework } catch (Exception ex) { - this.Monitor.Log($"SMAPI failed trying to track the crash details: {ex.GetLogSummary()}"); + this.Monitor.Log($"SMAPI failed trying to track the crash details: {ex.GetLogSummary()}", LogLevel.Error); } this.GameInstance.Exit(); @@ -576,7 +577,7 @@ namespace StardewModdingAPI.Framework if (latestStable == null && response.Errors.Any()) { this.Monitor.Log("Couldn't check for a new version of SMAPI. This won't affect your game, but you may not be notified of new versions if this keeps happening.", LogLevel.Warn); - this.Monitor.Log($"Error: {string.Join("\n", response.Errors)}"); + this.Monitor.Log($"Error: {string.Join("\n", response.Errors)}", LogLevel.Trace); } else if (this.IsValidUpdate(Constants.ApiVersion, latestBeta, this.Settings.UseBetaChannel)) { @@ -596,7 +597,7 @@ namespace StardewModdingAPI.Framework this.Monitor.Log("Couldn't check for a new version of SMAPI. This won't affect your game, but you won't be notified of new versions if this keeps happening.", LogLevel.Warn); this.Monitor.Log(ex is WebException && ex.InnerException == null ? $"Error: {ex.Message}" - : $"Error: {ex.GetLogSummary()}" + : $"Error: {ex.GetLogSummary()}", LogLevel.Trace ); } @@ -689,7 +690,7 @@ namespace StardewModdingAPI.Framework this.Monitor.Log("Couldn't check for new mod versions. This won't affect your game, but you won't be notified of mod updates if this keeps happening.", LogLevel.Warn); this.Monitor.Log(ex is WebException && ex.InnerException == null ? ex.Message - : ex.ToString() + : ex.ToString(), LogLevel.Trace ); } } diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs index 9818314a..704eb6bc 100644 --- a/src/SMAPI/Framework/SGame.cs +++ b/src/SMAPI/Framework/SGame.cs @@ -705,8 +705,8 @@ namespace StardewModdingAPI.Framework if (this.Monitor.IsVerbose) { - string addedText = this.Watchers.LocationsWatcher.Added.Any() ? string.Join(", ", added.Select(p => p.Name)) : "none"; - string removedText = this.Watchers.LocationsWatcher.Removed.Any() ? string.Join(", ", removed.Select(p => p.Name)) : "none"; + string addedText = added.Any() ? string.Join(", ", added.Select(p => p.Name)) : "none"; + string removedText = removed.Any() ? string.Join(", ", removed.Select(p => p.Name)) : "none"; this.Monitor.Log($"Context: location list changed (added {addedText}; removed {removedText}).", LogLevel.Trace); } diff --git a/src/SMAPI/IMonitor.cs b/src/SMAPI/IMonitor.cs index 0f153e10..943c1c59 100644 --- a/src/SMAPI/IMonitor.cs +++ b/src/SMAPI/IMonitor.cs @@ -19,7 +19,7 @@ namespace StardewModdingAPI /// <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> - void Log(string message, LogLevel level = LogLevel.Debug); + void Log(string message, LogLevel level = LogLevel.Trace); /// <summary>Log a message that only appears when <see cref="IsVerbose"/> is enabled.</summary> /// <param name="message">The message to log.</param> diff --git a/src/SMAPI/Patches/DialogueErrorPatch.cs b/src/SMAPI/Patches/DialogueErrorPatch.cs index d8905fd1..f1c25c05 100644 --- a/src/SMAPI/Patches/DialogueErrorPatch.cs +++ b/src/SMAPI/Patches/DialogueErrorPatch.cs @@ -13,7 +13,7 @@ namespace StardewModdingAPI.Patches internal class DialogueErrorPatch : IHarmonyPatch { /********* - ** Private methods + ** Fields *********/ /// <summary>Writes messages to the console and log file on behalf of the game.</summary> private static IMonitor MonitorForGame; @@ -21,6 +21,9 @@ namespace StardewModdingAPI.Patches /// <summary>Simplifies access to private code.</summary> private static Reflector Reflection; + /// <summary>Whether the <see cref="NPC.CurrentDialogue"/> getter is currently being intercepted.</summary> + private static bool IsInterceptingCurrentDialogue; + /********* ** Accessors @@ -46,10 +49,14 @@ namespace StardewModdingAPI.Patches /// <param name="harmony">The Harmony instance.</param> public void Apply(HarmonyInstance harmony) { - ConstructorInfo constructor = AccessTools.Constructor(typeof(Dialogue), new[] { typeof(string), typeof(NPC) }); - MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(DialogueErrorPatch.Prefix)); - - harmony.Patch(constructor, new HarmonyMethod(prefix), null); + harmony.Patch( + original: AccessTools.Constructor(typeof(Dialogue), new[] { typeof(string), typeof(NPC) }), + prefix: new HarmonyMethod(this.GetType(), nameof(DialogueErrorPatch.Before_Dialogue_Constructor)) + ); + harmony.Patch( + original: AccessTools.Property(typeof(NPC), nameof(NPC.CurrentDialogue)).GetMethod, + prefix: new HarmonyMethod(this.GetType(), nameof(DialogueErrorPatch.Before_NPC_CurrentDialogue)) + ); } @@ -63,7 +70,7 @@ namespace StardewModdingAPI.Patches /// <returns>Returns whether to execute the original method.</returns> /// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks> [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")] - private static bool Prefix(Dialogue __instance, string masterDialogue, NPC speaker) + private static bool Before_Dialogue_Constructor(Dialogue __instance, string masterDialogue, NPC speaker) { // get private members bool nameArraysTranslated = DialogueErrorPatch.Reflection.GetField<bool>(typeof(Dialogue), "nameArraysTranslated").GetValue(); @@ -96,5 +103,35 @@ namespace StardewModdingAPI.Patches return false; } + + /// <summary>The method to call instead of <see cref="NPC.CurrentDialogue"/>.</summary> + /// <param name="__instance">The instance being patched.</param> + /// <param name="__result">The return value of the original method.</param> + /// <param name="__originalMethod">The method being wrapped.</param> + /// <returns>Returns whether to execute the original method.</returns> + /// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks> + [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")] + private static bool Before_NPC_CurrentDialogue(NPC __instance, ref Stack<Dialogue> __result, MethodInfo __originalMethod) + { + if (DialogueErrorPatch.IsInterceptingCurrentDialogue) + return true; + + try + { + DialogueErrorPatch.IsInterceptingCurrentDialogue = true; + __result = (Stack<Dialogue>)__originalMethod.Invoke(__instance, new object[0]); + return false; + } + catch (TargetInvocationException ex) + { + DialogueErrorPatch.MonitorForGame.Log($"Failed loading current dialogue for NPC {__instance.Name}:\n{ex.InnerException ?? ex}", LogLevel.Error); + __result = new Stack<Dialogue>(); + return false; + } + finally + { + DialogueErrorPatch.IsInterceptingCurrentDialogue = false; + } + } } } diff --git a/src/SMAPI/Patches/EventErrorPatch.cs b/src/SMAPI/Patches/EventErrorPatch.cs new file mode 100644 index 00000000..cd530616 --- /dev/null +++ b/src/SMAPI/Patches/EventErrorPatch.cs @@ -0,0 +1,84 @@ +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using Harmony; +using StardewModdingAPI.Framework.Patching; +using StardewValley; + +namespace StardewModdingAPI.Patches +{ + /// <summary>A Harmony patch for the <see cref="Dialogue"/> constructor which intercepts invalid dialogue lines and logs an error instead of crashing.</summary> + internal class EventErrorPatch : IHarmonyPatch + { + /********* + ** Fields + *********/ + /// <summary>Writes messages to the console and log file on behalf of the game.</summary> + private static IMonitor MonitorForGame; + + /// <summary>Whether the method is currently being intercepted.</summary> + private static bool IsIntercepted; + + + /********* + ** Accessors + *********/ + /// <summary>A unique name for this patch.</summary> + public string Name => $"{nameof(EventErrorPatch)}"; + + + /********* + ** Public methods + *********/ + /// <summary>Construct an instance.</summary> + /// <param name="monitorForGame">Writes messages to the console and log file on behalf of the game.</param> + public EventErrorPatch(IMonitor monitorForGame) + { + EventErrorPatch.MonitorForGame = monitorForGame; + } + + /// <summary>Apply the Harmony patch.</summary> + /// <param name="harmony">The Harmony instance.</param> + public void Apply(HarmonyInstance harmony) + { + harmony.Patch( + original: AccessTools.Method(typeof(GameLocation), "checkEventPrecondition"), + prefix: new HarmonyMethod(this.GetType(), nameof(EventErrorPatch.Before_GameLocation_CheckEventPrecondition)) + ); + } + + + /********* + ** Private methods + *********/ + /// <summary>The method to call instead of the GameLocation.CheckEventPrecondition.</summary> + /// <param name="__instance">The instance being patched.</param> + /// <param name="__result">The return value of the original method.</param> + /// <param name="precondition">The precondition to be parsed.</param> + /// <param name="__originalMethod">The method being wrapped.</param> + /// <returns>Returns whether to execute the original method.</returns> + /// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks> + [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")] + private static bool Before_GameLocation_CheckEventPrecondition(GameLocation __instance, ref int __result, string precondition, MethodInfo __originalMethod) + { + if (EventErrorPatch.IsIntercepted) + return true; + + try + { + EventErrorPatch.IsIntercepted = true; + __result = (int)__originalMethod.Invoke(__instance, new object[] { precondition }); + return false; + } + catch (TargetInvocationException ex) + { + __result = -1; + EventErrorPatch.MonitorForGame.Log($"Failed parsing event precondition ({precondition}):\n{ex.InnerException}", LogLevel.Error); + return false; + } + finally + { + EventErrorPatch.IsIntercepted = false; + } + } + } +} diff --git a/src/SMAPI/Patches/LoadForNewGamePatch.cs b/src/SMAPI/Patches/LoadContextPatch.cs index 9e788e84..3f86c9a9 100644 --- a/src/SMAPI/Patches/LoadForNewGamePatch.cs +++ b/src/SMAPI/Patches/LoadContextPatch.cs @@ -1,7 +1,6 @@ using System; using System.Collections.ObjectModel; using System.Collections.Specialized; -using System.Reflection; using Harmony; using StardewModdingAPI.Enums; using StardewModdingAPI.Framework.Patching; @@ -13,10 +12,10 @@ namespace StardewModdingAPI.Patches { /// <summary>A Harmony patch for <see cref="Game1.loadForNewGame"/> which notifies SMAPI for save creation load stages.</summary> /// <remarks>This patch hooks into <see cref="Game1.loadForNewGame"/>, checks if <c>TitleMenu.transitioningCharacterCreationMenu</c> is true (which means the player is creating a new save file), then raises <see cref="LoadStage.CreatedBasicInfo"/> after the location list is cleared twice (the second clear happens right before locations are created), and <see cref="LoadStage.CreatedLocations"/> when the method ends.</remarks> - internal class LoadForNewGamePatch : IHarmonyPatch + internal class LoadContextPatch : IHarmonyPatch { /********* - ** Accessors + ** Fields *********/ /// <summary>Simplifies access to private code.</summary> private static Reflector Reflection; @@ -28,14 +27,14 @@ namespace StardewModdingAPI.Patches private static bool IsCreating; /// <summary>The number of times that <see cref="Game1.locations"/> has been cleared since <see cref="Game1.loadForNewGame"/> started.</summary> - private static int TimesLocationsCleared = 0; + private static int TimesLocationsCleared; /********* ** Accessors *********/ /// <summary>A unique name for this patch.</summary> - public string Name => $"{nameof(LoadForNewGamePatch)}"; + public string Name => $"{nameof(LoadContextPatch)}"; /********* @@ -44,21 +43,21 @@ namespace StardewModdingAPI.Patches /// <summary>Construct an instance.</summary> /// <param name="reflection">Simplifies access to private code.</param> /// <param name="onStageChanged">A callback to invoke when the load stage changes.</param> - public LoadForNewGamePatch(Reflector reflection, Action<LoadStage> onStageChanged) + public LoadContextPatch(Reflector reflection, Action<LoadStage> onStageChanged) { - LoadForNewGamePatch.Reflection = reflection; - LoadForNewGamePatch.OnStageChanged = onStageChanged; + LoadContextPatch.Reflection = reflection; + LoadContextPatch.OnStageChanged = onStageChanged; } /// <summary>Apply the Harmony patch.</summary> /// <param name="harmony">The Harmony instance.</param> public void Apply(HarmonyInstance harmony) { - MethodInfo method = AccessTools.Method(typeof(Game1), nameof(Game1.loadForNewGame)); - MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(LoadForNewGamePatch.Prefix)); - MethodInfo postfix = AccessTools.Method(this.GetType(), nameof(LoadForNewGamePatch.Postfix)); - - harmony.Patch(method, new HarmonyMethod(prefix), new HarmonyMethod(postfix)); + harmony.Patch( + original: AccessTools.Method(typeof(Game1), nameof(Game1.loadForNewGame)), + prefix: new HarmonyMethod(this.GetType(), nameof(LoadContextPatch.Before_Game1_LoadForNewGame)), + postfix: new HarmonyMethod(this.GetType(), nameof(LoadContextPatch.After_Game1_LoadForNewGame)) + ); } @@ -68,15 +67,15 @@ namespace StardewModdingAPI.Patches /// <summary>The method to call instead of <see cref="Game1.loadForNewGame"/>.</summary> /// <returns>Returns whether to execute the original method.</returns> /// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks> - private static bool Prefix() + private static bool Before_Game1_LoadForNewGame() { - LoadForNewGamePatch.IsCreating = Game1.activeClickableMenu is TitleMenu menu && LoadForNewGamePatch.Reflection.GetField<bool>(menu, "transitioningCharacterCreationMenu").GetValue(); - LoadForNewGamePatch.TimesLocationsCleared = 0; - if (LoadForNewGamePatch.IsCreating) + LoadContextPatch.IsCreating = Game1.activeClickableMenu is TitleMenu menu && LoadContextPatch.Reflection.GetField<bool>(menu, "transitioningCharacterCreationMenu").GetValue(); + LoadContextPatch.TimesLocationsCleared = 0; + if (LoadContextPatch.IsCreating) { // raise CreatedBasicInfo after locations are cleared twice ObservableCollection<GameLocation> locations = (ObservableCollection<GameLocation>)Game1.locations; - locations.CollectionChanged += LoadForNewGamePatch.OnLocationListChanged; + locations.CollectionChanged += LoadContextPatch.OnLocationListChanged; } return true; @@ -84,16 +83,16 @@ namespace StardewModdingAPI.Patches /// <summary>The method to call instead after <see cref="Game1.loadForNewGame"/>.</summary> /// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks> - private static void Postfix() + private static void After_Game1_LoadForNewGame() { - if (LoadForNewGamePatch.IsCreating) + if (LoadContextPatch.IsCreating) { // clean up - ObservableCollection<GameLocation> locations = (ObservableCollection<GameLocation>) Game1.locations; - locations.CollectionChanged -= LoadForNewGamePatch.OnLocationListChanged; + ObservableCollection<GameLocation> locations = (ObservableCollection<GameLocation>)Game1.locations; + locations.CollectionChanged -= LoadContextPatch.OnLocationListChanged; // raise stage changed - LoadForNewGamePatch.OnStageChanged(LoadStage.CreatedLocations); + LoadContextPatch.OnStageChanged(LoadStage.CreatedLocations); } } @@ -102,8 +101,8 @@ namespace StardewModdingAPI.Patches /// <param name="e">The event arguments.</param> private static void OnLocationListChanged(object sender, NotifyCollectionChangedEventArgs e) { - if (++LoadForNewGamePatch.TimesLocationsCleared == 2) - LoadForNewGamePatch.OnStageChanged(LoadStage.CreatedBasicInfo); + if (++LoadContextPatch.TimesLocationsCleared == 2) + LoadContextPatch.OnStageChanged(LoadStage.CreatedBasicInfo); } } } diff --git a/src/SMAPI/Patches/ObjectErrorPatch.cs b/src/SMAPI/Patches/ObjectErrorPatch.cs index 0481259d..5b918d39 100644 --- a/src/SMAPI/Patches/ObjectErrorPatch.cs +++ b/src/SMAPI/Patches/ObjectErrorPatch.cs @@ -1,8 +1,8 @@ using System.Diagnostics.CodeAnalysis; -using System.Reflection; using Harmony; using StardewModdingAPI.Framework.Patching; using StardewValley; +using StardewValley.Menus; using SObject = StardewValley.Object; namespace StardewModdingAPI.Patches @@ -24,10 +24,17 @@ namespace StardewModdingAPI.Patches /// <param name="harmony">The Harmony instance.</param> public void Apply(HarmonyInstance harmony) { - MethodInfo method = AccessTools.Method(typeof(SObject), nameof(SObject.getDescription)); - MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(ObjectErrorPatch.Prefix)); + // object.getDescription + harmony.Patch( + original: AccessTools.Method(typeof(SObject), nameof(SObject.getDescription)), + prefix: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.Before_Object_GetDescription)) + ); - harmony.Patch(method, new HarmonyMethod(prefix), null); + // IClickableMenu.drawToolTip + harmony.Patch( + original: AccessTools.Method(typeof(IClickableMenu), nameof(IClickableMenu.drawToolTip)), + prefix: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.Before_IClickableMenu_DrawTooltip)) + ); } @@ -40,7 +47,7 @@ namespace StardewModdingAPI.Patches /// <returns>Returns whether to execute the original method.</returns> /// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks> [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")] - private static bool Prefix(SObject __instance, ref string __result) + private static bool Before_Object_GetDescription(SObject __instance, ref string __result) { // invalid bigcraftables crash instead of showing '???' like invalid non-bigcraftables if (!__instance.IsRecipe && __instance.bigCraftable.Value && !Game1.bigCraftablesInformation.ContainsKey(__instance.ParentSheetIndex)) @@ -51,5 +58,20 @@ namespace StardewModdingAPI.Patches return true; } + + /// <summary>The method to call instead of <see cref="IClickableMenu.drawToolTip"/>.</summary> + /// <param name="__instance">The instance being patched.</param> + /// <param name="hoveredItem">The item for which to draw a tooltip.</param> + /// <returns>Returns whether to execute the original method.</returns> + /// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks> + [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")] + private static bool Before_IClickableMenu_DrawTooltip(IClickableMenu __instance, Item hoveredItem) + { + // invalid edible item cause crash when drawing tooltips + if (hoveredItem is SObject obj && obj.Edibility != -300 && !Game1.objectInformation.ContainsKey(obj.ParentSheetIndex)) + return false; + + return true; + } } } diff --git a/src/SMAPI/Program.cs b/src/SMAPI/Program.cs index 2eec371c..3a34872a 100644 --- a/src/SMAPI/Program.cs +++ b/src/SMAPI/Program.cs @@ -30,10 +30,18 @@ namespace StardewModdingAPI /// <param name="args">The command-line arguments.</param> public static void Main(string[] args) { - AppDomain.CurrentDomain.AssemblyResolve += Program.CurrentDomain_AssemblyResolve; - Program.AssertGamePresent(); - Program.AssertGameVersion(); - Program.Start(args); + try + { + AppDomain.CurrentDomain.AssemblyResolve += Program.CurrentDomain_AssemblyResolve; + Program.AssertGamePresent(); + Program.AssertGameVersion(); + Program.Start(args); + } + catch (Exception ex) + { + Console.WriteLine($"SMAPI failed to initialise: {ex}"); + Program.PressAnyKeyToExit(true); + } } diff --git a/src/SMAPI/StardewModdingAPI.config.json b/src/SMAPI/StardewModdingAPI.config.json index ad908fc0..c04cceee 100644 --- a/src/SMAPI/StardewModdingAPI.config.json +++ b/src/SMAPI/StardewModdingAPI.config.json @@ -8,70 +8,70 @@ This file contains advanced configuration for SMAPI. You generally shouldn't cha */ { - /** - * The console color theme to use. The possible values are: - * - AutoDetect: SMAPI will assume a light background on Mac, and detect the background color automatically on Linux or Windows. - * - LightBackground: use darker text colors that look better on a white or light background. - * - DarkBackground: use lighter text colors that look better on a black or dark background. - */ - "ColorScheme": "AutoDetect", + /** + * The console color theme to use. The possible values are: + * - AutoDetect: SMAPI will assume a light background on Mac, and detect the background color automatically on Linux or Windows. + * - LightBackground: use darker text colors that look better on a white or light background. + * - DarkBackground: use lighter text colors that look better on a black or dark background. + */ + "ColorScheme": "AutoDetect", - /** - * Whether SMAPI should check for newer versions of SMAPI and mods when you load the game. If new - * versions are available, an alert will be shown in the console. This doesn't affect the load - * time even if your connection is offline or slow, because it happens in the background. - */ - "CheckForUpdates": true, + /** + * Whether SMAPI should check for newer versions of SMAPI and mods when you load the game. If new + * versions are available, an alert will be shown in the console. This doesn't affect the load + * time even if your connection is offline or slow, because it happens in the background. + */ + "CheckForUpdates": true, - /** - * Whether to enable features intended for mod developers. Currently this only makes TRACE-level - * messages appear in the console. - */ - "DeveloperMode": true, + /** + * Whether to enable features intended for mod developers. Currently this only makes TRACE-level + * messages appear in the console. + */ + "DeveloperMode": true, - /** - * Whether to add a section to the 'mod issues' list for mods which directly use potentially - * sensitive .NET APIs like file or shell access. Note that many mods do this legitimately as - * part of their normal functionality, so these warnings are meaningless without further - * investigation. When this is commented out, it'll be true for local debug builds and false - * otherwise. - */ - //"ParanoidWarnings": true, + /** + * Whether to add a section to the 'mod issues' list for mods which directly use potentially + * sensitive .NET APIs like file or shell access. Note that many mods do this legitimately as + * part of their normal functionality, so these warnings are meaningless without further + * investigation. When this is commented out, it'll be true for local debug builds and false + * otherwise. + */ + //"ParanoidWarnings": true, - /** - * Whether SMAPI should show newer beta versions as an available update. When this is commented - * out, it'll be true if the current SMAPI version is beta, and false otherwise. - */ - //"UseBetaChannel": true, + /** + * Whether SMAPI should show newer beta versions as an available update. When this is commented + * out, it'll be true if the current SMAPI version is beta, and false otherwise. + */ + //"UseBetaChannel": true, - /** - * SMAPI's GitHub project name, used to perform update checks. - */ - "GitHubProjectName": "Pathoschild/SMAPI", + /** + * SMAPI's GitHub project name, used to perform update checks. + */ + "GitHubProjectName": "Pathoschild/SMAPI", - /** - * The base URL for SMAPI's web API, used to perform update checks. - * Note: the protocol will be changed to http:// on Linux/Mac due to OpenSSL issues with the - * game's bundled Mono. - */ - "WebApiBaseUrl": "https://api.smapi.io", + /** + * The base URL for SMAPI's web API, used to perform update checks. + * Note: the protocol will be changed to http:// on Linux/Mac due to OpenSSL issues with the + * game's bundled Mono. + */ + "WebApiBaseUrl": "https://api.smapi.io", - /** - * Whether SMAPI should log more information about the game context. - */ - "VerboseLogging": false, + /** + * Whether SMAPI should log more information about the game context. + */ + "VerboseLogging": false, - /** - * Whether to generate a 'SMAPI-latest.metadata-dump.json' file in the logs folder with the full mod - * metadata for detected mods. This is only needed when troubleshooting some cases. - */ - "DumpMetadata": false, + /** + * Whether to generate a 'SMAPI-latest.metadata-dump.json' file in the logs folder with the full mod + * metadata for detected mods. This is only needed when troubleshooting some cases. + */ + "DumpMetadata": false, - /** - * The mod IDs SMAPI should ignore when performing update checks or validating update keys. - */ - "SuppressUpdateChecks": [ - "SMAPI.ConsoleCommands", - "SMAPI.SaveBackup" - ] + /** + * The mod IDs SMAPI should ignore when performing update checks or validating update keys. + */ + "SuppressUpdateChecks": [ + "SMAPI.ConsoleCommands", + "SMAPI.SaveBackup" + ] } diff --git a/src/SMAPI/StardewModdingAPI.csproj b/src/SMAPI/StardewModdingAPI.csproj index b6562eca..eda53025 100644 --- a/src/SMAPI/StardewModdingAPI.csproj +++ b/src/SMAPI/StardewModdingAPI.csproj @@ -1,69 +1,28 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">x86</Platform> - <ProjectGuid>{F1A573B0-F436-472C-AE29-0B91EA6B9F8F}</ProjectGuid> - <OutputType>Exe</OutputType> - <AppDesignerFolder>Properties</AppDesignerFolder> <RootNamespace>StardewModdingAPI</RootNamespace> <AssemblyName>StardewModdingAPI</AssemblyName> - <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> - <FileAlignment>512</FileAlignment> - <IsWebBootstrapper>false</IsWebBootstrapper> - <TargetFrameworkProfile /> - <PublishUrl>publish\</PublishUrl> - <Install>true</Install> - <InstallFrom>Disk</InstallFrom> - <UpdateEnabled>false</UpdateEnabled> - <UpdateMode>Foreground</UpdateMode> - <UpdateInterval>7</UpdateInterval> - <UpdateIntervalUnits>Days</UpdateIntervalUnits> - <UpdatePeriodically>false</UpdatePeriodically> - <UpdateRequired>false</UpdateRequired> - <MapFileExtensions>true</MapFileExtensions> - <ApplicationRevision>0</ApplicationRevision> - <ApplicationVersion>1.0.0.%2a</ApplicationVersion> - <UseApplicationTrust>false</UseApplicationTrust> - <BootstrapperEnabled>true</BootstrapperEnabled> + <TargetFramework>net45</TargetFramework> + <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <LangVersion>latest</LangVersion> - <LargeAddressAware Condition="'$(OS)' == 'Windows_NT'">true</LargeAddressAware> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> - <PlatformTarget>x86</PlatformTarget> - <Prefer32Bit>false</Prefer32Bit> - <DefineConstants>DEBUG;TRACE</DefineConstants> - <UseVSHostingProcess>true</UseVSHostingProcess> - <Optimize>false</Optimize> - <OutputPath>$(SolutionDir)\..\bin\Debug\SMAPI</OutputPath> - <DocumentationFile>$(SolutionDir)\..\bin\Debug\SMAPI\StardewModdingAPI.xml</DocumentationFile> - <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> <PlatformTarget>x86</PlatformTarget> - <Prefer32Bit>false</Prefer32Bit> - <OutputPath>$(SolutionDir)\..\bin\Release\SMAPI</OutputPath> - <DocumentationFile>$(SolutionDir)\..\bin\Release\SMAPI\StardewModdingAPI.xml</DocumentationFile> - <DefineConstants>TRACE</DefineConstants> - <Optimize>true</Optimize> - <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow> - <DebugType>pdbonly</DebugType> - <DebugSymbols>true</DebugSymbols> - </PropertyGroup> - <PropertyGroup> + <OutputType>Exe</OutputType> + <OutputPath>$(SolutionDir)\..\bin\$(Configuration)\SMAPI</OutputPath> + <DocumentationFile>$(SolutionDir)\..\bin\$(Configuration)\SMAPI\StardewModdingAPI.xml</DocumentationFile> + <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> + <LargeAddressAware Condition="'$(OS)' == 'Windows_NT'">true</LargeAddressAware> <ApplicationIcon>icon.ico</ApplicationIcon> </PropertyGroup> + <ItemGroup> <PackageReference Include="LargeAddressAware" Version="1.0.3" /> <PackageReference Include="Lib.Harmony" Version="1.2.0.1" /> <PackageReference Include="Mono.Cecil" Version="0.10.1" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> </ItemGroup> + <ItemGroup> - <Reference Include="System" /> - <Reference Include="System.Core" /> - <Reference Include="System.Drawing" /> <Reference Include="System.Numerics"> <Private>True</Private> </Reference> @@ -71,281 +30,17 @@ <Private>True</Private> </Reference> <Reference Include="System.Windows.Forms" Condition="$(OS) == 'Windows_NT'" /> - <Reference Include="System.Xml" /> </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\SMAPI.Toolkit.CoreInterfaces\StardewModdingAPI.Toolkit.CoreInterfaces.csproj" /> + <ProjectReference Include="..\SMAPI.Toolkit\StardewModdingAPI.Toolkit.csproj" /> + </ItemGroup> + <ItemGroup> - <Compile Include="..\..\build\GlobalAssemblyInfo.cs"> - <Link>Properties\GlobalAssemblyInfo.cs</Link> - </Compile> - <Compile Include="Enums\LoadStage.cs" /> - <Compile Include="Enums\SkillType.cs" /> - <Compile Include="Events\BuildingListChangedEventArgs.cs" /> - <Compile Include="Events\ButtonPressedEventArgs.cs" /> - <Compile Include="Events\ButtonReleasedEventArgs.cs" /> - <Compile Include="Events\ChangeType.cs" /> - <Compile Include="Events\ContentEvents.cs" /> - <Compile Include="Events\ControlEvents.cs" /> - <Compile Include="Events\CursorMovedEventArgs.cs" /> - <Compile Include="Events\DayEndingEventArgs.cs" /> - <Compile Include="Events\DayStartedEventArgs.cs" /> - <Compile Include="Events\DebrisListChangedEventArgs.cs" /> - <Compile Include="Events\EventArgsClickableMenuChanged.cs" /> - <Compile Include="Events\EventArgsClickableMenuClosed.cs" /> - <Compile Include="Events\EventArgsControllerButtonPressed.cs" /> - <Compile Include="Events\EventArgsControllerButtonReleased.cs" /> - <Compile Include="Events\EventArgsControllerTriggerPressed.cs" /> - <Compile Include="Events\EventArgsControllerTriggerReleased.cs" /> - <Compile Include="Events\EventArgsInput.cs" /> - <Compile Include="Events\EventArgsIntChanged.cs" /> - <Compile Include="Events\EventArgsInventoryChanged.cs" /> - <Compile Include="Events\EventArgsKeyboardStateChanged.cs" /> - <Compile Include="Events\EventArgsKeyPressed.cs" /> - <Compile Include="Events\EventArgsLevelUp.cs" /> - <Compile Include="Events\EventArgsLocationBuildingsChanged.cs" /> - <Compile Include="Events\EventArgsLocationObjectsChanged.cs" /> - <Compile Include="Events\EventArgsLocationsChanged.cs" /> - <Compile Include="Events\EventArgsMineLevelChanged.cs" /> - <Compile Include="Events\EventArgsMouseStateChanged.cs" /> - <Compile Include="Events\EventArgsPlayerWarped.cs" /> - <Compile Include="Events\EventArgsValueChanged.cs" /> - <Compile Include="Events\GameEvents.cs" /> - <Compile Include="Events\GameLaunchedEventArgs.cs" /> - <Compile Include="Events\GraphicsEvents.cs" /> - <Compile Include="Events\IDisplayEvents.cs" /> - <Compile Include="Events\IGameLoopEvents.cs" /> - <Compile Include="Events\IInputEvents.cs" /> - <Compile Include="Events\IModEvents.cs" /> - <Compile Include="Events\IMultiplayerEvents.cs" /> - <Compile Include="Events\InputEvents.cs" /> - <Compile Include="Events\InventoryChangedEventArgs.cs" /> - <Compile Include="Events\IPlayerEvents.cs" /> - <Compile Include="Events\ISpecialisedEvents.cs" /> - <Compile Include="Events\ItemStackChange.cs" /> - <Compile Include="Events\ItemStackSizeChange.cs" /> - <Compile Include="Events\IWorldEvents.cs" /> - <Compile Include="Events\LargeTerrainFeatureListChangedEventArgs.cs" /> - <Compile Include="Events\LevelChangedEventArgs.cs" /> - <Compile Include="Events\LoadStageChangedEventArgs.cs" /> - <Compile Include="Events\LocationEvents.cs" /> - <Compile Include="Events\LocationListChangedEventArgs.cs" /> - <Compile Include="Events\MenuChangedEventArgs.cs" /> - <Compile Include="Events\MenuEvents.cs" /> - <Compile Include="Events\MineEvents.cs" /> - <Compile Include="Events\ModMessageReceivedEventArgs.cs" /> - <Compile Include="Events\MouseWheelScrolledEventArgs.cs" /> - <Compile Include="Events\MultiplayerEvents.cs" /> - <Compile Include="Events\NpcListChangedEventArgs.cs" /> - <Compile Include="Events\ObjectListChangedEventArgs.cs" /> - <Compile Include="Events\OneSecondUpdateTickedEventArgs.cs" /> - <Compile Include="Events\OneSecondUpdateTickingEventArgs.cs" /> - <Compile Include="Events\PeerContextReceivedEventArgs.cs" /> - <Compile Include="Events\PeerDisconnectedEventArgs.cs" /> - <Compile Include="Events\PlayerEvents.cs" /> - <Compile Include="Events\RenderedActiveMenuEventArgs.cs" /> - <Compile Include="Events\RenderedEventArgs.cs" /> - <Compile Include="Events\RenderedHudEventArgs.cs" /> - <Compile Include="Events\RenderedWorldEventArgs.cs" /> - <Compile Include="Events\RenderingActiveMenuEventArgs.cs" /> - <Compile Include="Events\RenderingEventArgs.cs" /> - <Compile Include="Events\RenderingHudEventArgs.cs" /> - <Compile Include="Events\RenderingWorldEventArgs.cs" /> - <Compile Include="Events\ReturnedToTitleEventArgs.cs" /> - <Compile Include="Events\SaveCreatedEventArgs.cs" /> - <Compile Include="Events\SaveCreatingEventArgs.cs" /> - <Compile Include="Events\SavedEventArgs.cs" /> - <Compile Include="Events\SaveEvents.cs" /> - <Compile Include="Events\SaveLoadedEventArgs.cs" /> - <Compile Include="Events\SavingEventArgs.cs" /> - <Compile Include="Events\SpecialisedEvents.cs" /> - <Compile Include="Events\TerrainFeatureListChangedEventArgs.cs" /> - <Compile Include="Events\TimeChangedEventArgs.cs" /> - <Compile Include="Events\TimeEvents.cs" /> - <Compile Include="Events\UnvalidatedUpdateTickedEventArgs.cs" /> - <Compile Include="Events\UnvalidatedUpdateTickingEventArgs.cs" /> - <Compile Include="Events\UpdateTickedEventArgs.cs" /> - <Compile Include="Events\UpdateTickingEventArgs.cs" /> - <Compile Include="Events\WarpedEventArgs.cs" /> - <Compile Include="Events\WindowResizedEventArgs.cs" /> - <Compile Include="Framework\DeprecationWarning.cs" /> - <Compile Include="Framework\Events\EventManager.cs" /> - <Compile Include="Framework\Events\ManagedEvent.cs" /> - <Compile Include="Framework\Events\ManagedEventBase.cs" /> - <Compile Include="Framework\Events\ModDisplayEvents.cs" /> - <Compile Include="Framework\Events\ModEvents.cs" /> - <Compile Include="Framework\Events\ModEventsBase.cs" /> - <Compile Include="Framework\Events\ModGameLoopEvents.cs" /> - <Compile Include="Framework\Events\ModInputEvents.cs" /> - <Compile Include="Framework\Events\ModMultiplayerEvents.cs" /> - <Compile Include="Framework\Events\ModPlayerEvents.cs" /> - <Compile Include="Framework\Events\ModSpecialisedEvents.cs" /> - <Compile Include="Framework\Events\ModWorldEvents.cs" /> - <Compile Include="Framework\ModHelpers\ContentPackHelper.cs" /> - <Compile Include="Framework\ModHelpers\DataHelper.cs" /> - <Compile Include="Framework\Networking\MessageType.cs" /> - <Compile Include="Framework\Networking\ModMessageModel.cs" /> - <Compile Include="Framework\Networking\MultiplayerPeer.cs" /> - <Compile Include="Framework\Networking\MultiplayerPeerMod.cs" /> - <Compile Include="Framework\Networking\RemoteContextModel.cs" /> - <Compile Include="Framework\Networking\RemoteContextModModel.cs" /> - <Compile Include="Framework\Networking\SGalaxyNetClient.cs" /> - <Compile Include="Framework\Networking\SGalaxyNetServer.cs" /> - <Compile Include="Framework\Networking\SLidgrenClient.cs" /> - <Compile Include="Framework\Networking\SLidgrenServer.cs" /> - <Compile Include="Framework\SCore.cs" /> - <Compile Include="Framework\SGameConstructorHack.cs" /> - <Compile Include="Framework\ContentManagers\BaseContentManager.cs" /> - <Compile Include="Framework\ContentManagers\GameContentManager.cs" /> - <Compile Include="Framework\ContentManagers\IContentManager.cs" /> - <Compile Include="Framework\ContentManagers\ModContentManager.cs" /> - <Compile Include="Framework\Models\ModFolderExport.cs" /> - <Compile Include="Framework\ModLoading\TypeReferenceComparer.cs" /> - <Compile Include="Framework\Patching\GamePatcher.cs" /> - <Compile Include="Framework\Patching\IHarmonyPatch.cs" /> - <Compile Include="Framework\Serialisation\ColorConverter.cs" /> - <Compile Include="Framework\Serialisation\PointConverter.cs" /> - <Compile Include="Framework\Serialisation\RectangleConverter.cs" /> - <Compile Include="Framework\ContentPack.cs" /> - <Compile Include="Framework\Content\ContentCache.cs" /> - <Compile Include="Framework\Input\GamePadStateBuilder.cs" /> - <Compile Include="Framework\ModHelpers\InputHelper.cs" /> - <Compile Include="Framework\SModHooks.cs" /> - <Compile Include="Framework\Singleton.cs" /> - <Compile Include="Framework\StateTracking\Comparers\GenericEqualsComparer.cs" /> - <Compile Include="Framework\StateTracking\FieldWatchers\ComparableListWatcher.cs" /> - <Compile Include="Framework\WatcherCore.cs" /> - <Compile Include="IContentPackHelper.cs" /> - <Compile Include="IDataHelper.cs" /> - <Compile Include="IInputHelper.cs" /> - <Compile Include="Framework\Input\SInputState.cs" /> - <Compile Include="Framework\Input\InputStatus.cs" /> - <Compile Include="Framework\ModHelpers\MultiplayerHelper.cs" /> - <Compile Include="Framework\ModLoading\Finders\EventFinder.cs" /> - <Compile Include="Framework\ModLoading\Finders\FieldFinder.cs" /> - <Compile Include="Framework\ModLoading\Finders\MethodFinder.cs" /> - <Compile Include="Framework\ModLoading\Finders\PropertyFinder.cs" /> - <Compile Include="Framework\ModLoading\Finders\ReferenceToMissingMemberFinder.cs" /> - <Compile Include="Framework\ModLoading\Finders\TypeFinder.cs" /> - <Compile Include="Framework\ModLoading\IInstructionHandler.cs" /> - <Compile Include="Framework\ModLoading\IncompatibleInstructionException.cs" /> - <Compile Include="Framework\ModLoading\InstructionHandleResult.cs" /> - <Compile Include="Framework\ModLoading\PlatformAssemblyMap.cs" /> - <Compile Include="Framework\ModLoading\RewriteHelper.cs" /> - <Compile Include="Framework\ModLoading\Rewriters\FieldReplaceRewriter.cs" /> - <Compile Include="Framework\ModLoading\Rewriters\StaticFieldToConstantRewriter.cs" /> - <Compile Include="Framework\ModLoading\Rewriters\FieldToPropertyRewriter.cs" /> - <Compile Include="Framework\ModLoading\Finders\ReferenceToMemberWithUnexpectedTypeFinder.cs" /> - <Compile Include="Framework\ModLoading\Rewriters\MethodParentRewriter.cs" /> - <Compile Include="Framework\ModLoading\Rewriters\TypeReferenceRewriter.cs" /> - <Compile Include="Framework\Exceptions\SAssemblyLoadFailedException.cs" /> - <Compile Include="Framework\ModLoading\AssemblyLoadStatus.cs" /> - <Compile Include="Framework\Reflection\InterfaceProxyBuilder.cs" /> - <Compile Include="Framework\Reflection\InterfaceProxyFactory.cs" /> - <Compile Include="Framework\RewriteFacades\SpriteBatchMethods.cs" /> - <Compile Include="Framework\SMultiplayer.cs" /> - <Compile Include="Framework\StateTracking\Comparers\EquatableComparer.cs" /> - <Compile Include="Framework\StateTracking\Comparers\ObjectReferenceComparer.cs" /> - <Compile Include="Framework\StateTracking\FieldWatchers\BaseDisposableWatcher.cs" /> - <Compile Include="Framework\StateTracking\FieldWatchers\ComparableWatcher.cs" /> - <Compile Include="Framework\StateTracking\FieldWatchers\NetDictionaryWatcher.cs" /> - <Compile Include="Framework\StateTracking\FieldWatchers\NetValueWatcher.cs" /> - <Compile Include="Framework\StateTracking\FieldWatchers\NetCollectionWatcher.cs" /> - <Compile Include="Framework\StateTracking\FieldWatchers\ObservableCollectionWatcher.cs" /> - <Compile Include="Framework\StateTracking\FieldWatchers\WatcherFactory.cs" /> - <Compile Include="Framework\StateTracking\ICollectionWatcher.cs" /> - <Compile Include="Framework\StateTracking\IDictionaryWatcher.cs" /> - <Compile Include="Framework\StateTracking\IValueWatcher.cs" /> - <Compile Include="Framework\StateTracking\IWatcher.cs" /> - <Compile Include="Framework\StateTracking\WorldLocationsTracker.cs" /> - <Compile Include="Framework\StateTracking\LocationTracker.cs" /> - <Compile Include="Framework\StateTracking\PlayerTracker.cs" /> - <Compile Include="Framework\Utilities\ContextHash.cs" /> - <Compile Include="IContentPack.cs" /> - <Compile Include="IModInfo.cs" /> - <Compile Include="IMultiplayerHelper.cs" /> - <Compile Include="IMultiplayerPeer.cs" /> - <Compile Include="IReflectedField.cs" /> - <Compile Include="IReflectedMethod.cs" /> - <Compile Include="IReflectedProperty.cs" /> - <Compile Include="IMultiplayerPeerMod.cs" /> - <Compile Include="Metadata\CoreAssetPropagator.cs" /> - <Compile Include="ContentSource.cs" /> - <Compile Include="Framework\Content\AssetInfo.cs" /> - <Compile Include="Framework\Exceptions\SContentLoadException.cs" /> - <Compile Include="Framework\Command.cs" /> - <Compile Include="Constants.cs" /> - <Compile Include="Framework\Utilities\Countdown.cs" /> - <Compile Include="Framework\GameVersion.cs" /> - <Compile Include="Framework\IModMetadata.cs" /> - <Compile Include="Framework\ModHelpers\BaseHelper.cs" /> - <Compile Include="Framework\ModHelpers\CommandHelper.cs" /> - <Compile Include="Framework\ModHelpers\ContentHelper.cs" /> - <Compile Include="Framework\ModHelpers\ModHelper.cs" /> - <Compile Include="Framework\ModHelpers\ModRegistryHelper.cs" /> - <Compile Include="Framework\ModHelpers\ReflectionHelper.cs" /> - <Compile Include="Framework\ModHelpers\TranslationHelper.cs" /> - <Compile Include="Framework\ModLoading\InvalidModStateException.cs" /> - <Compile Include="Framework\ModLoading\ModDependencyStatus.cs" /> - <Compile Include="Framework\ModLoading\ModMetadataStatus.cs" /> - <Compile Include="Framework\ModLoading\ModResolver.cs" /> - <Compile Include="Framework\ModLoading\AssemblyDefinitionResolver.cs" /> - <Compile Include="Framework\ModLoading\AssemblyParseResult.cs" /> - <Compile Include="Framework\CommandManager.cs" /> - <Compile Include="Framework\Content\AssetData.cs" /> - <Compile Include="Framework\Content\AssetDataForObject.cs" /> - <Compile Include="Framework\Content\AssetDataForDictionary.cs" /> - <Compile Include="Framework\Content\AssetDataForImage.cs" /> - <Compile Include="Context.cs" /> - <Compile Include="Framework\Logging\ConsoleInterceptionManager.cs" /> - <Compile Include="Framework\Logging\InterceptingTextWriter.cs" /> - <Compile Include="Framework\Models\SConfig.cs" /> - <Compile Include="Framework\ModLoading\ModMetadata.cs" /> - <Compile Include="Framework\Reflection\ReflectedProperty.cs" /> - <Compile Include="Framework\RequestExitDelegate.cs" /> - <Compile Include="Framework\ContentCoordinator.cs" /> - <Compile Include="IAssetEditor.cs" /> - <Compile Include="IAssetInfo.cs" /> - <Compile Include="IAssetLoader.cs" /> - <Compile Include="ICommandHelper.cs" /> - <Compile Include="IAssetData.cs" /> - <Compile Include="IAssetDataForDictionary.cs" /> - <Compile Include="IAssetDataForImage.cs" /> - <Compile Include="IContentHelper.cs" /> - <Compile Include="IModRegistry.cs" /> - <Compile Include="Framework\DeprecationLevel.cs" /> - <Compile Include="Framework\DeprecationManager.cs" /> - <Compile Include="Framework\InternalExtensions.cs" /> - <Compile Include="Framework\ModLoading\AssemblyLoader.cs" /> - <Compile Include="Framework\Reflection\CacheEntry.cs" /> - <Compile Include="Framework\Reflection\ReflectedField.cs" /> - <Compile Include="Framework\Reflection\ReflectedMethod.cs" /> - <Compile Include="Framework\Reflection\Reflector.cs" /> - <Compile Include="IMod.cs" /> - <Compile Include="IModHelper.cs" /> - <Compile Include="IModLinked.cs" /> - <Compile Include="Framework\Logging\LogFileManager.cs" /> - <Compile Include="ITranslationHelper.cs" /> - <Compile Include="LogLevel.cs" /> - <Compile Include="Framework\ModRegistry.cs" /> - <Compile Include="IMonitor.cs" /> - <Compile Include="Framework\Monitor.cs" /> - <Compile Include="Metadata\InstructionMetadata.cs" /> - <Compile Include="Mod.cs" /> - <Compile Include="Patches\LoadForNewGamePatch.cs" /> - <Compile Include="Patches\ObjectErrorPatch.cs" /> - <Compile Include="Patches\DialogueErrorPatch.cs" /> - <Compile Include="PatchMode.cs" /> - <Compile Include="GamePlatform.cs" /> - <Compile Include="Program.cs" /> - <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="Framework\SGame.cs" /> - <Compile Include="IReflectionHelper.cs" /> - <Compile Include="SemanticVersion.cs" /> - <Compile Include="Translation.cs" /> - <Compile Include="ICursorPosition.cs" /> - <Compile Include="Utilities\SDate.cs" /> - <Compile Include="SButton.cs" /> - <Compile Include="Framework\CursorPosition.cs" /> + <Compile Include="..\..\build\GlobalAssemblyInfo.cs" Link="Properties\GlobalAssemblyInfo.cs" /> </ItemGroup> + <ItemGroup> <Content Include="StardewModdingAPI.config.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> @@ -354,39 +49,12 @@ <Link>StardewModdingAPI.metadata.json</Link> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> - </ItemGroup> - <ItemGroup> - <Content Include="icon.ico" /> - <Content Include="steam_appid.txt"> + <None Update="steam_appid.txt"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - </ItemGroup> - <ItemGroup> - <BootstrapperPackage Include=".NETFramework,Version=v4.5"> - <Visible>False</Visible> - <ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName> - <Install>true</Install> - </BootstrapperPackage> - <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> - <Visible>False</Visible> - <ProductName>.NET Framework 3.5 SP1</ProductName> - <Install>false</Install> - </BootstrapperPackage> - </ItemGroup> - <ItemGroup> - <Analyzer Include="..\SMAPI.ModBuildConfig.Analyzer\bin\netstandard1.3\StardewModdingAPI.ModBuildConfig.Analyzer.dll" /> - </ItemGroup> - <ItemGroup> - <ProjectReference Include="..\StardewModdingAPI.Toolkit.CoreInterfaces\StardewModdingAPI.Toolkit.CoreInterfaces.csproj"> - <Project>{d5cfd923-37f1-4bc3-9be8-e506e202ac28}</Project> - <Name>StardewModdingAPI.Toolkit.CoreInterfaces</Name> - </ProjectReference> - <ProjectReference Include="..\StardewModdingAPI.Toolkit\StardewModdingAPI.Toolkit.csproj"> - <Project>{ea5cfd2e-9453-4d29-b80f-8e0ea23f4ac6}</Project> - <Name>StardewModdingAPI.Toolkit</Name> - </ProjectReference> + </None> </ItemGroup> + <Import Project="..\SMAPI.Internal\SMAPI.Internal.projitems" Label="Shared" /> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="..\..\build\common.targets" /> -</Project>
\ No newline at end of file + +</Project> |