using System; using System.IO; using StardewModdingAPI.Framework; using StardewModdingAPI.Framework.Models; namespace StardewModdingAPI { /// The base class for a mod. public class Mod : IMod, IDisposable { /********* ** Properties *********/ /// Manages deprecation warnings. private static DeprecationManager DeprecationManager; /// The backing field for . private string _pathOnDisk; /********* ** Accessors *********/ /// Provides simplified APIs for writing mods. public IModHelper Helper { get; internal set; } /// Writes messages to the console and log file. public IMonitor Monitor { get; internal set; } /// The mod's manifest. public IManifest ModManifest { get; internal set; } /// The full path to the mod's directory on the disk. [Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.DirectoryPath) + " instead")] public string PathOnDisk { get { Mod.DeprecationManager.Warn($"{nameof(Mod)}.{nameof(Mod.PathOnDisk)}", "1.0", DeprecationLevel.Info); return this._pathOnDisk; } internal set { this._pathOnDisk = value; } } /// The full path to the mod's config.json file on the disk. [Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.ReadConfig) + " instead")] public string BaseConfigPath { get { Mod.DeprecationManager.Warn($"{nameof(Mod)}.{nameof(Mod.BaseConfigPath)}", "1.0", DeprecationLevel.Info); Mod.DeprecationManager.MarkWarned($"{nameof(Mod)}.{nameof(Mod.PathOnDisk)}", "1.0"); // avoid redundant warnings return Path.Combine(this.PathOnDisk, "config.json"); } } /// The full path to the per-save configs folder (if is true). [Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.ReadJsonFile) + " instead")] public string PerSaveConfigFolder => this.GetPerSaveConfigFolder(); /// The full path to the per-save configuration file for the current save (if is true). [Obsolete("Use " + nameof(Mod.Helper) + "." + nameof(IModHelper.ReadJsonFile) + " instead")] public string PerSaveConfigPath { get { Mod.DeprecationManager.Warn($"{nameof(Mod)}.{nameof(Mod.PerSaveConfigPath)}", "1.0", DeprecationLevel.Info); Mod.DeprecationManager.MarkWarned($"{nameof(Mod)}.{nameof(Mod.PerSaveConfigFolder)}", "1.0"); // avoid redundant warnings return Context.IsSaveLoaded ? Path.Combine(this.PerSaveConfigFolder, $"{Constants.SaveFolderName}.json") : ""; } } /********* ** Public methods *********/ /// Injects types required for backwards compatibility. /// Manages deprecation warnings. internal static void Shim(DeprecationManager deprecationManager) { Mod.DeprecationManager = deprecationManager; } /// The mod entry point, called after the mod is first loaded. [Obsolete("This overload is obsolete since SMAPI 1.0.")] public virtual void Entry(params object[] objects) { } /// The mod entry point, called after the mod is first loaded. /// Provides simplified APIs for writing mods. public virtual void Entry(IModHelper helper) { } /// Release or reset unmanaged resources. public void Dispose() { (this.Helper as IDisposable)?.Dispose(); // deliberate do this outside overridable dispose method so mods don't accidentally suppress it this.Dispose(true); GC.SuppressFinalize(this); } /********* ** Private methods *********/ /// Get the full path to the per-save configuration file for the current save (if is true). [Obsolete] private string GetPerSaveConfigFolder() { Mod.DeprecationManager.Warn($"{nameof(Mod)}.{nameof(Mod.PerSaveConfigFolder)}", "1.0", DeprecationLevel.Info); Mod.DeprecationManager.MarkWarned($"{nameof(Mod)}.{nameof(Mod.PathOnDisk)}", "1.0"); // avoid redundant warnings if (!((Manifest)this.ModManifest).PerSaveConfigs) { this.Monitor.Log("Tried to fetch the per-save config folder, but this mod isn't configured to use per-save config files.", LogLevel.Error); return ""; } return Path.Combine(this.PathOnDisk, "psconfigs"); } /// Release or reset unmanaged resources when the game exits. There's no guarantee this will be called on every exit. /// Whether the instance is being disposed explicitly rather than finalised. If this is false, the instance shouldn't dispose other objects since they may already be finalised. protected virtual void Dispose(bool disposing) { } /// Destruct the instance. ~Mod() { this.Dispose(false); } } }