let players override SMAPI incompatible-code detection if needed
This commit is contained in:
parent
33df1e8c94
commit
104aa31412
|
@ -142,7 +142,7 @@ field | purpose
|
|||
----- | -------
|
||||
`DeveloperMode` | Default `false` (except in _SMAPI for developers_ releases). Whether to enable features intended for mod developers. Currently this only makes `TRACE`-level messages appear in the console.
|
||||
`CheckForUpdates` | Default `true`. Whether SMAPI should check for a newer version when you load the game. If a new version is available, a small message will appear in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.
|
||||
`IncompatibleMods` | A list of mod versions SMAPI considers incompatible and will refuse to load. Changing this field is not recommended.
|
||||
`ModCompatibility` | A list of mod versions SMAPI should consider compatible or broken regardless of whether it detects incompatible code. Each record can be set to `AssumeCompatible` or `AssumeBroken`. Changing this field is not recommended and may destabilise your game.
|
||||
|
||||
### Command-line arguments
|
||||
SMAPI recognises the following command-line arguments. These are intended for internal use and may
|
||||
|
|
|
@ -54,9 +54,10 @@ namespace StardewModdingAPI.Framework
|
|||
|
||||
/// <summary>Preprocess and load an assembly.</summary>
|
||||
/// <param name="assemblyPath">The assembly file path.</param>
|
||||
/// <param name="assumeCompatible">Assume the mod is compatible, even if incompatible code is detected.</param>
|
||||
/// <returns>Returns the rewrite metadata for the preprocessed assembly.</returns>
|
||||
/// <exception cref="IncompatibleInstructionException">An incompatible CIL instruction was found while rewriting the assembly.</exception>
|
||||
public Assembly Load(string assemblyPath)
|
||||
public Assembly Load(string assemblyPath, bool assumeCompatible)
|
||||
{
|
||||
// get referenced local assemblies
|
||||
AssemblyParseResult[] assemblies;
|
||||
|
@ -73,7 +74,7 @@ namespace StardewModdingAPI.Framework
|
|||
Assembly lastAssembly = null;
|
||||
foreach (AssemblyParseResult assembly in assemblies)
|
||||
{
|
||||
bool changed = this.RewriteAssembly(assembly.Definition);
|
||||
bool changed = this.RewriteAssembly(assembly.Definition, assumeCompatible);
|
||||
if (changed)
|
||||
{
|
||||
this.Monitor.Log($"Loading {assembly.File.Name} (rewritten in memory)...", LogLevel.Trace);
|
||||
|
@ -159,12 +160,13 @@ namespace StardewModdingAPI.Framework
|
|||
****/
|
||||
/// <summary>Rewrite the types referenced by an assembly.</summary>
|
||||
/// <param name="assembly">The assembly to rewrite.</param>
|
||||
/// <param name="assumeCompatible">Assume the mod is compatible, even if incompatible code is detected.</param>
|
||||
/// <returns>Returns whether the assembly was modified.</returns>
|
||||
/// <exception cref="IncompatibleInstructionException">An incompatible CIL instruction was found while rewriting the assembly.</exception>
|
||||
private bool RewriteAssembly(AssemblyDefinition assembly)
|
||||
private bool RewriteAssembly(AssemblyDefinition assembly, bool assumeCompatible)
|
||||
{
|
||||
ModuleDefinition module = assembly.MainModule;
|
||||
HashSet<string> loggedRewrites = new HashSet<string>();
|
||||
HashSet<string> loggedMessages = new HashSet<string>();
|
||||
|
||||
// swap assembly references if needed (e.g. XNA => MonoGame)
|
||||
bool platformChanged = false;
|
||||
|
@ -173,7 +175,7 @@ namespace StardewModdingAPI.Framework
|
|||
// remove old assembly reference
|
||||
if (this.AssemblyMap.RemoveNames.Any(name => module.AssemblyReferences[i].Name == name))
|
||||
{
|
||||
this.LogOnce(this.Monitor, loggedRewrites, $"Rewriting {assembly.Name.Name} for OS...");
|
||||
this.LogOnce(this.Monitor, loggedMessages, $"Rewriting {assembly.Name.Name} for OS...");
|
||||
platformChanged = true;
|
||||
module.AssemblyReferences.RemoveAt(i);
|
||||
i--;
|
||||
|
@ -203,13 +205,17 @@ namespace StardewModdingAPI.Framework
|
|||
// throw exception if instruction is incompatible but can't be rewritten
|
||||
IInstructionFinder finder = finders.FirstOrDefault(p => p.IsMatch(instruction, platformChanged));
|
||||
if (finder != null)
|
||||
{
|
||||
if (!assumeCompatible)
|
||||
throw new IncompatibleInstructionException(finder.NounPhrase, $"Found an incompatible CIL instruction ({finder.NounPhrase}) while loading assembly {assembly.Name.Name}.");
|
||||
this.LogOnce(this.Monitor, loggedMessages, $"Found an incompatible CIL instruction ({finder.NounPhrase}) while loading assembly {assembly.Name.Name}, but SMAPI is configured to allow it anyway. The mod may crash or behave unexpectedly.", LogLevel.Warn);
|
||||
}
|
||||
|
||||
// rewrite instruction if needed
|
||||
IInstructionRewriter rewriter = rewriters.FirstOrDefault(p => p.IsMatch(instruction, platformChanged));
|
||||
if (rewriter != null)
|
||||
{
|
||||
this.LogOnce(this.Monitor, loggedRewrites, $"Rewriting {assembly.Name.Name} to fix {rewriter.NounPhrase}...");
|
||||
this.LogOnce(this.Monitor, loggedMessages, $"Rewriting {assembly.Name.Name} to fix {rewriter.NounPhrase}...");
|
||||
rewriter.Rewrite(module, cil, instruction, this.AssemblyMap);
|
||||
anyRewritten = true;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using StardewModdingAPI.Framework.Models;
|
||||
|
||||
namespace StardewModdingAPI.Framework
|
||||
|
@ -20,18 +19,18 @@ namespace StardewModdingAPI.Framework
|
|||
/// <summary>The friendly mod names treated as deprecation warning sources (assembly full name => mod name).</summary>
|
||||
private readonly IDictionary<string, string> ModNamesByAssembly = new Dictionary<string, string>();
|
||||
|
||||
/// <summary>The mod versions which should be disabled due to incompatibility.</summary>
|
||||
private readonly IncompatibleMod[] IncompatibleMods;
|
||||
/// <summary>Metadata about mods that SMAPI should assume is compatible or broken, regardless of whether it detects incompatible code.</summary>
|
||||
private readonly ModCompatibility[] CompatibilityRecords;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="incompatibleMods">The mod versions which should be disabled due to incompatibility.</param>
|
||||
public ModRegistry(IEnumerable<IncompatibleMod> incompatibleMods)
|
||||
/// <param name="compatibilityRecords">Metadata about mods that SMAPI should assume is compatible or broken, regardless of whether it detects incompatible code.</param>
|
||||
public ModRegistry(IEnumerable<ModCompatibility> compatibilityRecords)
|
||||
{
|
||||
this.IncompatibleMods = incompatibleMods.ToArray();
|
||||
this.CompatibilityRecords = compatibilityRecords.ToArray();
|
||||
}
|
||||
|
||||
|
||||
|
@ -127,19 +126,18 @@ namespace StardewModdingAPI.Framework
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>Get a record indicating why a mod is incompatible (if applicable).</summary>
|
||||
/// <summary>Get metadata that indicates whether SMAPI should assume the mod is compatible or broken, regardless of whether it detects incompatible code.</summary>
|
||||
/// <param name="manifest">The mod manifest.</param>
|
||||
/// <returns>Returns the incompatibility record if applicable, else <c>null</c>.</returns>
|
||||
internal IncompatibleMod GetIncompatibilityRecord(IManifest manifest)
|
||||
internal ModCompatibility GetCompatibilityRecord(IManifest manifest)
|
||||
{
|
||||
string key = !string.IsNullOrWhiteSpace(manifest.UniqueID) ? manifest.UniqueID : manifest.EntryDll;
|
||||
return (
|
||||
from mod in this.IncompatibleMods
|
||||
from mod in this.CompatibilityRecords
|
||||
where
|
||||
mod.ID == key
|
||||
&& (mod.LowerSemanticVersion == null || !manifest.Version.IsOlderThan(mod.LowerSemanticVersion))
|
||||
&& !manifest.Version.IsNewerThan(mod.UpperSemanticVersion)
|
||||
&& (string.IsNullOrWhiteSpace(mod.ForceCompatibleVersion) || !Regex.IsMatch(manifest.Version.ToString(), mod.ForceCompatibleVersion, RegexOptions.IgnoreCase))
|
||||
select mod
|
||||
).FirstOrDefault();
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ using Newtonsoft.Json;
|
|||
|
||||
namespace StardewModdingAPI.Framework.Models
|
||||
{
|
||||
/// <summary>Contains abstract metadata about an incompatible mod.</summary>
|
||||
internal class IncompatibleMod
|
||||
/// <summary>Metadata about a mod version that SMAPI should assume is compatible or broken, regardless of whether it detects incompatible code.</summary>
|
||||
internal class ModCompatibility
|
||||
{
|
||||
/*********
|
||||
** Accessors
|
||||
|
@ -30,13 +30,13 @@ namespace StardewModdingAPI.Framework.Models
|
|||
/// <summary>The URL the user can check for an unofficial updated version.</summary>
|
||||
public string UnofficialUpdateUrl { get; set; }
|
||||
|
||||
/// <summary>A regular expression matching version strings to consider compatible, even if they technically precede <see cref="UpperVersion"/>.</summary>
|
||||
public string ForceCompatibleVersion { get; set; }
|
||||
|
||||
/// <summary>The reason phrase to show in the warning, or <c>null</c> to use the default value.</summary>
|
||||
/// <example>"this version is incompatible with the latest version of the game"</example>
|
||||
public string ReasonPhrase { get; set; }
|
||||
|
||||
/// <summary>Indicates how SMAPI should consider the mod.</summary>
|
||||
public ModCompatibilityType Compatibility { get; set; }
|
||||
|
||||
|
||||
/****
|
||||
** Injected
|
|
@ -0,0 +1,12 @@
|
|||
namespace StardewModdingAPI.Framework.Models
|
||||
{
|
||||
/// <summary>Indicates how SMAPI should consider a mod.</summary>
|
||||
internal enum ModCompatibilityType
|
||||
{
|
||||
/// <summary>Assume the mod is not compatible, even if SMAPI doesn't detect any incompatible code.</summary>
|
||||
AssumeBroken = 0,
|
||||
|
||||
/// <summary>Assume the mod is compatible, even if SMAPI detects incompatible code.</summary>
|
||||
AssumeCompatible = 1
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
/// <summary>Whether to check if a newer version of SMAPI is available on startup.</summary>
|
||||
public bool CheckForUpdates { get; set; } = true;
|
||||
|
||||
/// <summary>A list of mod versions which should be considered incompatible.</summary>
|
||||
public IncompatibleMod[] IncompatibleMods { get; set; }
|
||||
/// <summary>A list of mod versions which should be considered compatible or incompatible regardless of whether SMAPI detects incompatible code.</summary>
|
||||
public ModCompatibility[] ModCompatibility { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ namespace StardewModdingAPI
|
|||
|
||||
// initialise
|
||||
this.Monitor = new Monitor("SMAPI", this.ConsoleManager, this.LogFile, this.ExitGameImmediately) { WriteToConsole = writeToConsole };
|
||||
this.ModRegistry = new ModRegistry(this.Settings.IncompatibleMods);
|
||||
this.ModRegistry = new ModRegistry(this.Settings.ModCompatibility);
|
||||
this.DeprecationManager = new DeprecationManager(this.Monitor, this.ModRegistry);
|
||||
}
|
||||
|
||||
|
@ -364,8 +364,8 @@ namespace StardewModdingAPI
|
|||
skippedPrefix = $"Skipped {manifest.Name}";
|
||||
|
||||
// validate compatibility
|
||||
IncompatibleMod compatibility = this.ModRegistry.GetIncompatibilityRecord(manifest);
|
||||
if (compatibility != null)
|
||||
ModCompatibility compatibility = this.ModRegistry.GetCompatibilityRecord(manifest);
|
||||
if (compatibility?.Compatibility == ModCompatibilityType.AssumeBroken)
|
||||
{
|
||||
bool hasOfficialUrl = !string.IsNullOrWhiteSpace(compatibility.UpdateUrl);
|
||||
bool hasUnofficialUrl = !string.IsNullOrWhiteSpace(compatibility.UnofficialUpdateUrl);
|
||||
|
@ -433,7 +433,7 @@ namespace StardewModdingAPI
|
|||
Assembly modAssembly;
|
||||
try
|
||||
{
|
||||
modAssembly = modAssemblyLoader.Load(assemblyPath);
|
||||
modAssembly = modAssemblyLoader.Load(assemblyPath, assumeCompatible: compatibility?.Compatibility == ModCompatibilityType.AssumeCompatible);
|
||||
}
|
||||
catch (IncompatibleInstructionException ex)
|
||||
{
|
||||
|
|
|
@ -9,7 +9,7 @@ generally shouldn't change this file unless necessary.
|
|||
{
|
||||
"DeveloperMode": true,
|
||||
"CheckForUpdates": true,
|
||||
"IncompatibleMods": [
|
||||
"ModCompatibility": [
|
||||
/* versions which crash the game */
|
||||
{
|
||||
"Name": "NPC Map Locations",
|
||||
|
@ -17,7 +17,8 @@ generally shouldn't change this file unless necessary.
|
|||
"LowerVersion": "1.42",
|
||||
"UpperVersion": "1.43",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/239",
|
||||
"ReasonPhrase": "this version has an update check error which crashes the game"
|
||||
"ReasonPhrase": "this version has an update check error which crashes the game",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
|
||||
/* versions not compatible with Stardew Valley 1.1+ */
|
||||
|
@ -25,7 +26,8 @@ generally shouldn't change this file unless necessary.
|
|||
"Name": "Chest Label System",
|
||||
"ID": "SPDChestLabel",
|
||||
"UpperVersion": "1.5",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/242"
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/242",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
|
||||
/* versions not compatible with Stardew Valley 1.2+ */
|
||||
|
@ -35,14 +37,16 @@ generally shouldn't change this file unless necessary.
|
|||
"UpperVersion": "1.1",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/257",
|
||||
"UnofficialUpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/518",
|
||||
"Notes": "Crashes with 'Method not found: Void StardewValley.Item.set_Name(System.String)'."
|
||||
"Notes": "Crashes with 'Method not found: Void StardewValley.Item.set_Name(System.String)'.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Almighty Tool",
|
||||
"ID": "AlmightyTool.dll",
|
||||
"UpperVersion": "1.1.1",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/439",
|
||||
"Notes": "Uses obsolete StardewModdingAPI.Extensions."
|
||||
"Notes": "Uses obsolete StardewModdingAPI.Extensions.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Better Sprinklers",
|
||||
|
@ -50,189 +54,216 @@ generally shouldn't change this file unless necessary.
|
|||
"UpperVersion": "2.3",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/41",
|
||||
"UnofficialUpdateUrl": "http://community.playstarbound.com/threads/125031",
|
||||
"Notes": "Uses obsolete StardewModdingAPI.Extensions."
|
||||
"Notes": "Uses obsolete StardewModdingAPI.Extensions.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Casks Anywhere",
|
||||
"ID": "CasksAnywhere",
|
||||
"UpperVersion": "1.1",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/878",
|
||||
"Notes": "Uses obsolete StardewModdingAPI.Inheritance.ItemStackChange."
|
||||
"Notes": "Uses obsolete StardewModdingAPI.Inheritance.ItemStackChange.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Chests Anywhere",
|
||||
"ID": "ChestsAnywhere",
|
||||
"UpperVersion": "1.8.2",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/518",
|
||||
"Notes": "Crashes with 'Method not found: Void StardewValley.Menus.TextBox.set_Highlighted(Boolean)'."
|
||||
"Notes": "Crashes with 'Method not found: Void StardewValley.Menus.TextBox.set_Highlighted(Boolean)'.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Chests Anywhere",
|
||||
"ID": "Pathoschild.ChestsAnywhere",
|
||||
"UpperVersion": "1.9-beta",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/518",
|
||||
"Notes": "ID changed in 1.9. Crashes with InvalidOperationException: 'The menu doesn't seem to have a player inventory'."
|
||||
"Notes": "ID changed in 1.9. Crashes with InvalidOperationException: 'The menu doesn't seem to have a player inventory'.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "CJB Automation",
|
||||
"ID": "CJBAutomation",
|
||||
"UpperVersion": "1.4",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/211",
|
||||
"Notes": "Crashes with 'Method not found: Void StardewValley.Item.set_Name(System.String)'."
|
||||
"Notes": "Crashes with 'Method not found: Void StardewValley.Item.set_Name(System.String)'.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "CJB Cheats Menu",
|
||||
"ID": "CJBCheatsMenu",
|
||||
"UpperVersion": "1.13",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/4",
|
||||
"Notes": "Uses removed Game1.borderFont."
|
||||
"Notes": "Uses removed Game1.borderFont.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "CJB Item Spawner",
|
||||
"ID": "CJBItemSpawner",
|
||||
"UpperVersion": "1.6",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/93",
|
||||
"Notes": "Uses removed Game1.borderFont."
|
||||
"Notes": "Uses removed Game1.borderFont.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Cooking Skill",
|
||||
"ID": "CookingSkill",
|
||||
"UpperVersion": "1.0.3",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/522",
|
||||
"Notes": "Crashes with 'Method not found: Void StardewValley.Buff..ctor(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, System.String)'."
|
||||
"Notes": "Crashes with 'Method not found: Void StardewValley.Buff..ctor(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, System.String)'.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Enemy Health Bars",
|
||||
"ID": "SPDHealthBar",
|
||||
"UpperVersion": "1.7",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/193",
|
||||
"Notes": "Uses obsolete GraphicsEvents.DrawTick."
|
||||
"Notes": "Uses obsolete GraphicsEvents.DrawTick.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Entoarox Framework",
|
||||
"ID": "eacdb74b-4080-4452-b16b-93773cda5cf9",
|
||||
"UpperVersion": "1.6.5",
|
||||
"UpdateUrl": "http://community.playstarbound.com/resources/4228",
|
||||
"Notes": "Uses obsolete StardewModdingAPI.Inheritance.SObject until 1.6.1; then crashes until 1.6.4 ('Entoarox Framework requested an immediate game shutdown: Fatal error attempting to update player tick properties System.NullReferenceException: Object reference not set to an instance of an object. at Entoarox.Framework.PlayerHelper.Update(Object s, EventArgs e)')."
|
||||
"Notes": "Uses obsolete StardewModdingAPI.Inheritance.SObject until 1.6.1; then crashes until 1.6.4 ('Entoarox Framework requested an immediate game shutdown: Fatal error attempting to update player tick properties System.NullReferenceException: Object reference not set to an instance of an object. at Entoarox.Framework.PlayerHelper.Update(Object s, EventArgs e)').",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Extended Fridge",
|
||||
"ID": "Mystra007ExtendedFridge",
|
||||
"UpperVersion": "1.0",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/485",
|
||||
"Notes": "Actual upper version is 0.94, but mod incorrectly sets it to 1.0 in the manifest. Crashes with 'Field not found: StardewValley.Game1.mouseCursorTransparency'."
|
||||
"Notes": "Actual upper version is 0.94, but mod incorrectly sets it to 1.0 in the manifest. Crashes with 'Field not found: StardewValley.Game1.mouseCursorTransparency'.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Get Dressed",
|
||||
"ID": "GetDressed.dll",
|
||||
"UpperVersion": "3.2",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/331",
|
||||
"Notes": "Crashes with NullReferenceException in GameEvents.UpdateTick."
|
||||
"Notes": "Crashes with NullReferenceException in GameEvents.UpdateTick.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Lookup Anything",
|
||||
"ID": "LookupAnything",
|
||||
"UpperVersion": "1.10",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/541",
|
||||
"Notes": "Crashes with FormatException when looking up NPCs."
|
||||
"Notes": "Crashes with FormatException when looking up NPCs.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Lookup Anything",
|
||||
"ID": "Pathoschild.LookupAnything",
|
||||
"UpperVersion": "1.10.1",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/541",
|
||||
"Notes": "ID changed in 1.10.1. Crashes with FormatException when looking up NPCs."
|
||||
"Notes": "ID changed in 1.10.1. Crashes with FormatException when looking up NPCs.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Makeshift Multiplayer",
|
||||
"ID": "StardewValleyMP",
|
||||
"UpperVersion": "0.2.10",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/501",
|
||||
"Notes": "Uses obsolete GraphicsEvents.OnPreRenderHudEventNoCheck."
|
||||
"Notes": "Uses obsolete GraphicsEvents.OnPreRenderHudEventNoCheck.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "NoSoilDecay",
|
||||
"ID": "289dee03-5f38-4d8e-8ffc-e440198e8610",
|
||||
"UpperVersion": "0.5",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/237",
|
||||
"Notes": "Uses Assembly.GetExecutingAssembly().Location."
|
||||
"Notes": "Uses Assembly.GetExecutingAssembly().Location.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Point-and-Plant",
|
||||
"ID": "PointAndPlant.dll",
|
||||
"UpperVersion": "1.0.2",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/572",
|
||||
"Notes": "Uses obsolete StardewModdingAPI.Extensions."
|
||||
"Notes": "Uses obsolete StardewModdingAPI.Extensions.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Reusable Wallpapers",
|
||||
"ID": "dae1b553-2e39-43e7-8400-c7c5c836134b",
|
||||
"UpperVersion": "1.5",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/356",
|
||||
"Notes": "Uses obsolete StardewModdingAPI.Inheritance.ItemStackChange."
|
||||
"Notes": "Uses obsolete StardewModdingAPI.Inheritance.ItemStackChange.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Save Anywhere",
|
||||
"ID": "SaveAnywhere",
|
||||
"UpperVersion": "2.0",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/444",
|
||||
"Notes": "Depends on StarDustCore."
|
||||
"Notes": "Depends on StarDustCore.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "StackSplitX",
|
||||
"ID": "StackSplitX.dll",
|
||||
"UpperVersion": "1.0",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/798",
|
||||
"Notes": "Uses SMAPI's internal SGame class."
|
||||
"Notes": "Uses SMAPI's internal SGame class.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "StarDustCore",
|
||||
"ID": "StarDustCore",
|
||||
"UpperVersion": "1.0",
|
||||
"UpdateUrl": "http://www.nexusmods.com/stardewvalley/mods/683",
|
||||
"Notes": "Crashes with 'Method not found: Void StardewModdingAPI.Command.CallCommand(System.String)'."
|
||||
"Notes": "Crashes with 'Method not found: Void StardewModdingAPI.Command.CallCommand(System.String)'.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Teleporter",
|
||||
"ID": "Teleporter",
|
||||
"UpperVersion": "1.0.2",
|
||||
"UpdateUrl": "http://community.playstarbound.com/resources/4374",
|
||||
"Notes": "Crashes with 'InvalidOperationException: The StardewValley.Menus.MapPage object doesn't have a private 'points' instance field'."
|
||||
"Notes": "Crashes with 'InvalidOperationException: The StardewValley.Menus.MapPage object doesn't have a private 'points' instance field'.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Zoryn's Better RNG",
|
||||
"ID": "76b6d1e1-f7ba-4d72-8c32-5a1e6d2716f6",
|
||||
"UpperVersion": "1.5",
|
||||
"UpdateUrl": "http://community.playstarbound.com/threads/108756",
|
||||
"Notes": "Uses SMAPI's internal SGame class."
|
||||
"Notes": "Uses SMAPI's internal SGame class.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Zoryn's Calendar Anywhere",
|
||||
"ID": "a41c01cd-0437-43eb-944f-78cb5a53002a",
|
||||
"UpperVersion": "1.5",
|
||||
"UpdateUrl": "http://community.playstarbound.com/threads/108756",
|
||||
"Notes": "Uses SMAPI's internal SGame class."
|
||||
"Notes": "Uses SMAPI's internal SGame class.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Zoryn's Health Bars",
|
||||
"ID": "HealthBars.dll",
|
||||
"UpperVersion": "1.5",
|
||||
"UpdateUrl": "http://community.playstarbound.com/threads/108756",
|
||||
"Notes": "Uses SMAPI's internal SGame class."
|
||||
"Notes": "Uses SMAPI's internal SGame class.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Zoryn's Movement Mod",
|
||||
"ID": "8a632929-8335-484f-87dd-c29d2ba3215d",
|
||||
"UpperVersion": "1.5",
|
||||
"UpdateUrl": "http://community.playstarbound.com/threads/108756",
|
||||
"Notes": "Uses SMAPI's internal SGame class."
|
||||
"Notes": "Uses SMAPI's internal SGame class.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
},
|
||||
{
|
||||
"Name": "Zoryn's Regen Mod",
|
||||
"ID": "dfac4383-1b6b-4f33-ae4e-37fc23e5252e",
|
||||
"UpperVersion": "1.5",
|
||||
"UpdateUrl": "http://community.playstarbound.com/threads/108756",
|
||||
"Notes": "Uses SMAPI's internal SGame class."
|
||||
"Notes": "Uses SMAPI's internal SGame class.",
|
||||
"Compatibility": "AssumeBroken"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -154,6 +154,7 @@
|
|||
<Compile Include="Framework\Logging\ConsoleInterceptionManager.cs" />
|
||||
<Compile Include="Framework\Logging\InterceptingTextWriter.cs" />
|
||||
<Compile Include="Framework\CommandHelper.cs" />
|
||||
<Compile Include="Framework\Models\ModCompatibilityType.cs" />
|
||||
<Compile Include="Framework\Models\SConfig.cs" />
|
||||
<Compile Include="Framework\Reflection\PrivateProperty.cs" />
|
||||
<Compile Include="Framework\RequestExitDelegate.cs" />
|
||||
|
@ -176,7 +177,7 @@
|
|||
<Compile Include="Framework\DeprecationLevel.cs" />
|
||||
<Compile Include="Framework\DeprecationManager.cs" />
|
||||
<Compile Include="Framework\InternalExtensions.cs" />
|
||||
<Compile Include="Framework\Models\IncompatibleMod.cs" />
|
||||
<Compile Include="Framework\Models\ModCompatibility.cs" />
|
||||
<Compile Include="Framework\AssemblyLoader.cs" />
|
||||
<Compile Include="Framework\Reflection\CacheEntry.cs" />
|
||||
<Compile Include="Framework\Reflection\PrivateField.cs" />
|
||||
|
|
Loading…
Reference in New Issue