diff options
| author | Jesse Plamondon-Willard <github@jplamondonw.com> | 2017-04-05 14:55:46 -0400 |
|---|---|---|
| committer | Jesse Plamondon-Willard <github@jplamondonw.com> | 2017-04-05 14:55:46 -0400 |
| commit | dbb9bd84306830456032778fc11fb9a34dd140c7 (patch) | |
| tree | 0219cab065bfffbbbb9b048b6a30044f510be2c5 /src/StardewModdingAPI | |
| parent | 9c9833c9086b758589dafee10243e3bf47e12d73 (diff) | |
| parent | 4675da0600edf6781cd740549ad0a175b606fc1e (diff) | |
| download | SMAPI-dbb9bd84306830456032778fc11fb9a34dd140c7.tar.gz SMAPI-dbb9bd84306830456032778fc11fb9a34dd140c7.tar.bz2 SMAPI-dbb9bd84306830456032778fc11fb9a34dd140c7.zip | |
Merge branch 'develop-1.9' into stable
Diffstat (limited to 'src/StardewModdingAPI')
69 files changed, 2781 insertions, 1882 deletions
diff --git a/src/StardewModdingAPI/Advanced/ConfigFile.cs b/src/StardewModdingAPI/Advanced/ConfigFile.cs deleted file mode 100644 index 1a2e6618..00000000 --- a/src/StardewModdingAPI/Advanced/ConfigFile.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.IO; -using Newtonsoft.Json; - -namespace StardewModdingAPI.Advanced -{ - /// <summary>Wraps a configuration file with IO methods for convenience.</summary> - public abstract class ConfigFile : IConfigFile - { - /********* - ** Accessors - *********/ - /// <summary>Provides simplified APIs for writing mods.</summary> - public IModHelper ModHelper { get; set; } - - /// <summary>The file path from which the model was loaded, relative to the mod directory.</summary> - public string FilePath { get; set; } - - - /********* - ** Public methods - *********/ - /// <summary>Reparse the underlying file and update this model.</summary> - public void Reload() - { - string json = File.ReadAllText(Path.Combine(this.ModHelper.DirectoryPath, this.FilePath)); - JsonConvert.PopulateObject(json, this); - } - - /// <summary>Save this model to the underlying file.</summary> - public void Save() - { - this.ModHelper.WriteJsonFile(this.FilePath, this); - } - } -}
\ No newline at end of file diff --git a/src/StardewModdingAPI/Advanced/IConfigFile.cs b/src/StardewModdingAPI/Advanced/IConfigFile.cs deleted file mode 100644 index 5bc31a88..00000000 --- a/src/StardewModdingAPI/Advanced/IConfigFile.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace StardewModdingAPI.Advanced -{ - /// <summary>Wraps a configuration file with IO methods for convenience.</summary> - public interface IConfigFile - { - /********* - ** Accessors - *********/ - /// <summary>Provides simplified APIs for writing mods.</summary> - IModHelper ModHelper { get; set; } - - /// <summary>The file path from which the model was loaded, relative to the mod directory.</summary> - string FilePath { get; set; } - - - /********* - ** Methods - *********/ - /// <summary>Reparse the underlying file and update this model.</summary> - void Reload(); - - /// <summary>Save this model to the underlying file.</summary> - void Save(); - } -} diff --git a/src/StardewModdingAPI/Command.cs b/src/StardewModdingAPI/Command.cs index 1fa18d49..e2d08538 100644 --- a/src/StardewModdingAPI/Command.cs +++ b/src/StardewModdingAPI/Command.cs @@ -1,23 +1,33 @@ using System; using System.Collections.Generic; -using System.Linq; using StardewModdingAPI.Events; using StardewModdingAPI.Framework; namespace StardewModdingAPI { /// <summary>A command that can be submitted through the SMAPI console to interact with SMAPI.</summary> + [Obsolete("Use " + nameof(IModHelper) + "." + nameof(IModHelper.ConsoleCommands))] public class Command { /********* ** Properties *********/ - /**** - ** SMAPI - ****/ /// <summary>The commands registered with SMAPI.</summary> - internal static List<Command> RegisteredCommands = new List<Command>(); + private static readonly IDictionary<string, Command> LegacyCommands = new Dictionary<string, Command>(StringComparer.InvariantCultureIgnoreCase); + + /// <summary>Manages console commands.</summary> + private static CommandManager CommandManager; + /// <summary>Manages deprecation warnings.</summary> + private static DeprecationManager DeprecationManager; + + /// <summary>Tracks the installed mods.</summary> + private static ModRegistry ModRegistry; + + + /********* + ** Accessors + *********/ /// <summary>The event raised when this command is submitted through the console.</summary> public event EventHandler<EventArgsCommand> CommandFired; @@ -43,6 +53,17 @@ namespace StardewModdingAPI /**** ** Command ****/ + /// <summary>Injects types required for backwards compatibility.</summary> + /// <param name="commandManager">Manages console commands.</param> + /// <param name="deprecationManager">Manages deprecation warnings.</param> + /// <param name="modRegistry">Tracks the installed mods.</param> + internal static void Shim(CommandManager commandManager, DeprecationManager deprecationManager, ModRegistry modRegistry) + { + Command.CommandManager = commandManager; + Command.DeprecationManager = deprecationManager; + Command.ModRegistry = modRegistry; + } + /// <summary>Construct an instance.</summary> /// <param name="name">The name of the command.</param> /// <param name="description">A human-readable description of what the command does.</param> @@ -64,44 +85,17 @@ namespace StardewModdingAPI this.CommandFired.Invoke(this, new EventArgsCommand(this)); } + /**** ** SMAPI ****/ /// <summary>Parse a command string and invoke it if valid.</summary> /// <param name="input">The command to run, including the command name and any arguments.</param> - [Obsolete("Use the overload which passes in your mod's monitor")] - public static void CallCommand(string input) - { - Program.DeprecationManager.Warn($"an old version of {nameof(Command)}.{nameof(Command.CallCommand)}", "1.1", DeprecationLevel.Notice); - Command.CallCommand(input, Program.GetLegacyMonitorForMod()); - } - - /// <summary>Parse a command string and invoke it if valid.</summary> - /// <param name="input">The command to run, including the command name and any arguments.</param> /// <param name="monitor">Encapsulates monitoring and logging.</param> public static void CallCommand(string input, IMonitor monitor) { - // normalise input - input = input?.Trim(); - if (string.IsNullOrWhiteSpace(input)) - return; - - // tokenise input - string[] args = input.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); - string commandName = args[0]; - args = args.Skip(1).ToArray(); - - // get command - Command command = Command.FindCommand(commandName); - if (command == null) - { - monitor.Log("Unknown command", LogLevel.Error); - return; - } - - // fire command - command.CalledArgs = args; - command.Fire(); + Command.DeprecationManager.Warn("Command.CallCommand", "1.9", DeprecationLevel.Info); + Command.CommandManager.Trigger(input); } /// <summary>Register a command with SMAPI.</summary> @@ -110,11 +104,25 @@ namespace StardewModdingAPI /// <param name="args">A human-readable list of accepted arguments.</param> public static Command RegisterCommand(string name, string description, string[] args = null) { - var command = new Command(name, description, args); - if (Command.RegisteredCommands.Contains(command)) - throw new InvalidOperationException($"The '{command.CommandName}' command is already registered!"); + name = name?.Trim().ToLower(); + + // raise deprecation warning + Command.DeprecationManager.Warn("Command.RegisterCommand", "1.9", DeprecationLevel.Info); - Command.RegisteredCommands.Add(command); + // validate + if (Command.LegacyCommands.ContainsKey(name)) + throw new InvalidOperationException($"The '{name}' command is already registered!"); + + // add command + string modName = Command.ModRegistry.GetModFromStack() ?? "<unknown mod>"; + string documentation = args?.Length > 0 + ? $"{description} - {string.Join(", ", args)}" + : description; + Command.CommandManager.Add(modName, name, documentation, Command.Fire); + + // add legacy command + Command command = new Command(name, description, args); + Command.LegacyCommands.Add(name, command); return command; } @@ -122,7 +130,28 @@ namespace StardewModdingAPI /// <param name="name">The command name to find.</param> public static Command FindCommand(string name) { - return Command.RegisteredCommands.Find(x => x.CommandName.Equals(name)); + Command.DeprecationManager.Warn("Command.FindCommand", "1.9", DeprecationLevel.Info); + if (name == null) + return null; + + Command command; + Command.LegacyCommands.TryGetValue(name.Trim(), out command); + return command; + } + + + /********* + ** Private methods + *********/ + /// <summary>Trigger this command.</summary> + /// <param name="name">The command name.</param> + /// <param name="args">The command arguments.</param> + private static void Fire(string name, string[] args) + { + Command command; + if (!Command.LegacyCommands.TryGetValue(name, out command)) + throw new InvalidOperationException($"Can't run command '{name}' because there's no such legacy command."); + command.Fire(); } } } diff --git a/src/StardewModdingAPI/Config.cs b/src/StardewModdingAPI/Config.cs index 037c0fdf..9f4bfad2 100644 --- a/src/StardewModdingAPI/Config.cs +++ b/src/StardewModdingAPI/Config.cs @@ -12,6 +12,13 @@ namespace StardewModdingAPI public abstract class Config { /********* + ** Properties + *********/ + /// <summary>Manages deprecation warnings.</summary> + private static DeprecationManager DeprecationManager; + + + /********* ** Accessors *********/ /// <summary>The full path to the configuration file.</summary> @@ -26,6 +33,13 @@ namespace StardewModdingAPI /********* ** Public methods *********/ + /// <summary>Injects types required for backwards compatibility.</summary> + /// <param name="deprecationManager">Manages deprecation warnings.</param> + internal static void Shim(DeprecationManager deprecationManager) + { + Config.DeprecationManager = deprecationManager; + } + /// <summary>Construct an instance of the config class.</summary> /// <typeparam name="T">The config class type.</typeparam> [Obsolete("This base class is obsolete since SMAPI 1.0. See the latest project README for details.")] @@ -111,8 +125,8 @@ namespace StardewModdingAPI /// <summary>Construct an instance.</summary> protected Config() { - Program.DeprecationManager.Warn("the Config class", "1.0", DeprecationLevel.Notice); - Program.DeprecationManager.MarkWarned($"{nameof(Mod)}.{nameof(Mod.BaseConfigPath)}", "1.0"); // typically used to construct config, avoid redundant warnings + Config.DeprecationManager.Warn("the Config class", "1.0", DeprecationLevel.Info); + Config.DeprecationManager.MarkWarned($"{nameof(Mod)}.{nameof(Mod.BaseConfigPath)}", "1.0"); // typically used to construct config, avoid redundant warnings } } diff --git a/src/StardewModdingAPI/Constants.cs b/src/StardewModdingAPI/Constants.cs index a62a0d58..4a036cd0 100644 --- a/src/StardewModdingAPI/Constants.cs +++ b/src/StardewModdingAPI/Constants.cs @@ -3,8 +3,12 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using Microsoft.Xna.Framework.Graphics; using StardewModdingAPI.AssemblyRewriters; +using StardewModdingAPI.AssemblyRewriters.Finders; using StardewModdingAPI.AssemblyRewriters.Rewriters; +using StardewModdingAPI.AssemblyRewriters.Rewriters.Wrappers; +using StardewModdingAPI.Events; using StardewValley; namespace StardewModdingAPI @@ -15,64 +19,74 @@ namespace StardewModdingAPI /********* ** Properties *********/ - /// <summary>The directory name containing the current save's data (if a save is loaded).</summary> - private static string RawSaveFolderName => Constants.PlayerNull ? string.Empty : Constants.GetSaveFolderName(); - /// <summary>The directory path containing the current save's data (if a save is loaded).</summary> - private static string RawSavePath => Constants.PlayerNull ? string.Empty : Path.Combine(Constants.SavesPath, Constants.RawSaveFolderName); + private static string RawSavePath => Constants.IsSaveLoaded ? Path.Combine(Constants.SavesPath, Constants.GetSaveFolderName()) : null; + + /// <summary>Whether the directory containing the current save's data exists on disk.</summary> + private static bool SavePathReady => Constants.IsSaveLoaded && Directory.Exists(Constants.RawSavePath); /********* ** Accessors *********/ + /**** + ** Public + ****/ /// <summary>SMAPI's current semantic version.</summary> - [Obsolete("Use " + nameof(Constants) + "." + nameof(ApiVersion))] - public static readonly Version Version = (Version)Constants.ApiVersion; - - /// <summary>SMAPI's current semantic version.</summary> - public static ISemanticVersion ApiVersion => new Version(1, 8, 0, null, suppressDeprecationWarning: true); + public static ISemanticVersion ApiVersion { get; } = new SemanticVersion(1, 9, 0); /// <summary>The minimum supported version of Stardew Valley.</summary> - public const string MinimumGameVersion = "1.1"; + public static ISemanticVersion MinimumGameVersion { get; } = new SemanticVersion("1.1"); - /// <summary>The GitHub repository to check for updates.</summary> - public const string GitHubRepository = "Pathoschild/SMAPI"; + /// <summary>The maximum supported version of Stardew Valley.</summary> + public static ISemanticVersion MaximumGameVersion { get; } = new SemanticVersion("1.1.1"); + + /// <summary>The path to the game folder.</summary> + public static string ExecutionPath { get; } = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); /// <summary>The directory path containing Stardew Valley's app data.</summary> - public static string DataPath => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley"); + public static string DataPath { get; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley"); - /// <summary>The directory path where all saves are stored.</summary> - public static string SavesPath => Path.Combine(Constants.DataPath, "Saves"); + /// <summary>The directory path in which error logs should be stored.</summary> + public static string LogDir { get; } = Path.Combine(Constants.DataPath, "ErrorLogs"); - /// <summary>Whether the directory containing the current save's data exists on disk.</summary> - public static bool CurrentSavePathExists => Directory.Exists(Constants.RawSavePath); + /// <summary>The directory path where all saves are stored.</summary> + public static string SavesPath { get; } = Path.Combine(Constants.DataPath, "Saves"); /// <summary>The directory name containing the current save's data (if a save is loaded and the directory exists).</summary> - public static string SaveFolderName => Constants.CurrentSavePathExists ? Constants.RawSaveFolderName : ""; + public static string SaveFolderName => Constants.SavePathReady ? Constants.GetSaveFolderName() : ""; /// <summary>The directory path containing the current save's data (if a save is loaded and the directory exists).</summary> - public static string CurrentSavePath => Constants.CurrentSavePathExists ? Constants.RawSavePath : ""; + public static string CurrentSavePath => Constants.SavePathReady ? Path.Combine(Constants.SavesPath, Constants.GetSaveFolderName()) : ""; - /// <summary>Whether a player save has been loaded.</summary> - public static bool PlayerNull => !Game1.hasLoadedGame || Game1.player == null || string.IsNullOrEmpty(Gam |
