summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/StardewModdingAPI/Advanced/ConfigFile.cs35
-rw-r--r--src/StardewModdingAPI/Advanced/IConfigFile.cs25
-rw-r--r--src/StardewModdingAPI/Config.cs9
-rw-r--r--src/StardewModdingAPI/Mod.cs15
-rw-r--r--src/StardewModdingAPI/ModHelper.cs98
-rw-r--r--src/StardewModdingAPI/Program.cs4
-rw-r--r--src/StardewModdingAPI/StardewModdingAPI.csproj3
7 files changed, 184 insertions, 5 deletions
diff --git a/src/StardewModdingAPI/Advanced/ConfigFile.cs b/src/StardewModdingAPI/Advanced/ConfigFile.cs
new file mode 100644
index 00000000..000eaf4c
--- /dev/null
+++ b/src/StardewModdingAPI/Advanced/ConfigFile.cs
@@ -0,0 +1,35 @@
+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 methods for interacting with the mod directory, including read/writing the config file.</summary>
+ public ModHelper 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
new file mode 100644
index 00000000..78fd44a6
--- /dev/null
+++ b/src/StardewModdingAPI/Advanced/IConfigFile.cs
@@ -0,0 +1,25 @@
+namespace StardewModdingAPI.Advanced
+{
+ /// <summary>Wraps a configuration file with IO methods for convenience.</summary>
+ public interface IConfigFile
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>Provides methods for interacting with the mod directory, including read/writing the config file.</summary>
+ ModHelper 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/Config.cs b/src/StardewModdingAPI/Config.cs
index ff8ade90..d811d69d 100644
--- a/src/StardewModdingAPI/Config.cs
+++ b/src/StardewModdingAPI/Config.cs
@@ -7,6 +7,7 @@ using Newtonsoft.Json.Linq;
namespace StardewModdingAPI
{
/// <summary>A dynamic configuration class for a mod.</summary>
+ [Obsolete("This base class is obsolete since SMAPI 1.0. See the latest project README for details.")]
public abstract class Config
{
/*********
@@ -26,10 +27,12 @@ namespace StardewModdingAPI
*********/
/// <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.")]
public virtual Config Instance<T>() where T : Config => Activator.CreateInstance<T>();
/// <summary>Load the config from the JSON file, saving it to disk if needed.</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.")]
public virtual T LoadConfig<T>() where T : Config
{
// validate
@@ -67,10 +70,12 @@ namespace StardewModdingAPI
}
/// <summary>Get the default config values.</summary>
+ [Obsolete("This base class is obsolete since SMAPI 1.0. See the latest project README for details.")]
public abstract T GenerateDefaultConfig<T>() where T : Config;
/// <summary>Get the current configuration with missing values defaulted.</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.")]
public virtual T UpdateConfig<T>() where T : Config
{
try
@@ -97,12 +102,14 @@ namespace StardewModdingAPI
}
/// <summary>Provides extension methods for <see cref="Config"/> classes.</summary>
+ [Obsolete("This base class is obsolete since SMAPI 1.0. See the latest project README for details.")]
public static class ConfigExtensions
{
/// <summary>Initialise the configuration. That includes loading, saving, and merging the config file and in memory at a default state. This method should not be used to reload or to resave a config. NOTE: You MUST set your config EQUAL to the return of this method!</summary>
/// <typeparam name="T">The config class type.</typeparam>
/// <param name="baseConfig">The base configuration to initialise.</param>
/// <param name="configLocation">The base configuration file path.</param>
+ [Obsolete("This base class is obsolete since SMAPI 1.0. See the latest project README for details.")]
public static T InitializeConfig<T>(this T baseConfig, string configLocation) where T : Config
{
if (baseConfig == null)
@@ -121,6 +128,7 @@ namespace StardewModdingAPI
/// <summary>Writes the configuration to the JSON file.</summary>
/// <typeparam name="T">The config class type.</typeparam>
/// <param name="baseConfig">The base configuration to initialise.</param>
+ [Obsolete("This base class is obsolete since SMAPI 1.0. See the latest project README for details.")]
public static void WriteConfig<T>(this T baseConfig) where T : Config
{
if (string.IsNullOrEmpty(baseConfig?.ConfigLocation) || string.IsNullOrEmpty(baseConfig.ConfigDir))
@@ -140,6 +148,7 @@ namespace StardewModdingAPI
/// <summary>Rereads the JSON file and merges its values with a default config. NOTE: You MUST set your config EQUAL to the return of this method!</summary>
/// <typeparam name="T">The config class type.</typeparam>
/// <param name="baseConfig">The base configuration to initialise.</param>
+ [Obsolete("This base class is obsolete since SMAPI 1.0. See the latest project README for details.")]
public static T ReloadConfig<T>(this T baseConfig) where T : Config
{
return baseConfig.LoadConfig<T>();
diff --git a/src/StardewModdingAPI/Mod.cs b/src/StardewModdingAPI/Mod.cs
index e8824fc6..c1cc99d4 100644
--- a/src/StardewModdingAPI/Mod.cs
+++ b/src/StardewModdingAPI/Mod.cs
@@ -1,4 +1,5 @@
-using System.IO;
+using System;
+using System.IO;
namespace StardewModdingAPI
{
@@ -8,6 +9,9 @@ namespace StardewModdingAPI
/*********
** Accessors
*********/
+ /// <summary>Provides methods for interacting with the mod directory, such as read/writing a config file or custom JSON files.</summary>
+ public ModHelper Helper { get; internal set; }
+
/// <summary>The mod's manifest.</summary>
public Manifest Manifest { get; internal set; }
@@ -28,9 +32,12 @@ namespace StardewModdingAPI
** Public methods
*********/
/// <summary>The entry point for your mod. It will always be called once when the mod loads.</summary>
- public virtual void Entry(params object[] objects)
- {
- }
+ [Obsolete("This overload is obsolete since SMAPI 1.0.")]
+ public virtual void Entry(params object[] objects) { }
+
+ /// <summary>The entry point for your mod. It will always be called once when the mod loads.</summary>
+ /// <param name="helper">Provides methods for interacting with the mod directory, such as read/writing a config file or custom JSON files.</param>
+ public virtual void Entry(ModHelper helper) { }
/*********
diff --git a/src/StardewModdingAPI/ModHelper.cs b/src/StardewModdingAPI/ModHelper.cs
new file mode 100644
index 00000000..bb753170
--- /dev/null
+++ b/src/StardewModdingAPI/ModHelper.cs
@@ -0,0 +1,98 @@
+using System;
+using System.IO;
+using Newtonsoft.Json;
+using StardewModdingAPI.Advanced;
+
+namespace StardewModdingAPI
+{
+ /// <summary>Provides methods for interacting with a mod directory.</summary>
+ public class ModHelper
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The mod directory path.</summary>
+ public string DirectoryPath { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="modDirectory">The mod directory path.</param>
+ public ModHelper(string modDirectory)
+ {
+ // validate
+ if (string.IsNullOrWhiteSpace(modDirectory))
+ throw new InvalidOperationException("The mod directory cannot be empty.");
+ if (!Directory.Exists(modDirectory))
+ throw new InvalidOperationException("The specified mod directory does not exist.");
+
+ // initialise
+ this.DirectoryPath = modDirectory;
+ }
+
+ /****
+ ** Mod config file
+ ****/
+ /// <summary>Read the mod's configuration file (and create it if needed).</summary>
+ /// <typeparam name="TConfig">The config class type. This should be a plain class that has public properties for the settings you want. These can be complex types.</typeparam>
+ public TConfig ReadConfig<TConfig>()
+ where TConfig : class, new()
+ {
+ var config = this.ReadJsonFile<TConfig>("config.json") ?? new TConfig();
+ this.WriteConfig(config); // create file or fill in missing fields
+ return config;
+ }
+
+ /// <summary>Save to the mod's configuration file.</summary>
+ /// <typeparam name="TConfig">The config class type.</typeparam>
+ /// <param name="config">The config settings to save.</param>
+ public void WriteConfig<TConfig>(TConfig config)
+ where TConfig : class, new()
+ {
+ this.WriteJsonFile("config.json", config);
+ }
+
+ /****
+ ** Generic JSON files
+ ****/
+ /// <summary>Read a JSON file.</summary>
+ /// <typeparam name="TModel">The model type.</typeparam>
+ /// <param name="path">The file path relative to the mod directory.</param>
+ public TModel ReadJsonFile<TModel>(string path)
+ where TModel : class
+ {
+ string fullPath = Path.Combine(this.DirectoryPath, path);
+ TModel model = JsonConvert.DeserializeObject<TModel>(File.ReadAllText(fullPath));
+
+ if (model is IConfigFile)
+ {
+ var wrapper = (IConfigFile)model;
+ wrapper.ModHelper = this;
+ wrapper.FilePath = path;
+ }
+
+ return model;
+ }
+
+ /// <summary>Save to a JSON file.</summary>
+ /// <typeparam name="TModel">The model type.</typeparam>
+ /// <param name="path">The file path relative to the mod directory.</param>
+ /// <param name="model">The model to save.</param>
+ public void WriteJsonFile<TModel>(string path, TModel model)
+ where TModel : class
+ {
+ path = Path.Combine(this.DirectoryPath, path);
+
+ // create directory if needed
+ string dir = Path.GetDirectoryName(path);
+ if (!Directory.Exists(dir))
+ Directory.CreateDirectory(dir);
+
+ // write file
+ string json = JsonConvert.SerializeObject(model, Formatting.Indented);
+ File.WriteAllText(path, json);
+ }
+ }
+}
diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs
index 8c38a88b..032f1192 100644
--- a/src/StardewModdingAPI/Program.cs
+++ b/src/StardewModdingAPI/Program.cs
@@ -314,11 +314,13 @@ namespace StardewModdingAPI
Mod modEntry = (Mod)modAssembly.CreateInstance(tar.ToString());
if (modEntry != null)
{
+ modEntry.Helper = new ModHelper(targDir);
modEntry.PathOnDisk = targDir;
modEntry.Manifest = manifest;
Log.Info($"Loaded mod: {modEntry.Manifest.Name} by {modEntry.Manifest.Author}, v{modEntry.Manifest.Version} | {modEntry.Manifest.Description}\n@ {targDll}");
Program.ModsLoaded += 1;
- modEntry.Entry();
+ modEntry.Entry(); // obsolete
+ modEntry.Entry(modEntry.Helper);
}
}
else
diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj
index 9e89c9e6..451e5961 100644
--- a/src/StardewModdingAPI/StardewModdingAPI.csproj
+++ b/src/StardewModdingAPI/StardewModdingAPI.csproj
@@ -161,6 +161,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="Advanced\ConfigFile.cs" />
+ <Compile Include="Advanced\IConfigFile.cs" />
<Compile Include="Command.cs" />
<Compile Include="Config.cs" />
<Compile Include="Constants.cs" />
@@ -202,6 +204,7 @@
<Compile Include="Framework\LogWriter.cs" />
<Compile Include="Manifest.cs" />
<Compile Include="Mod.cs" />
+ <Compile Include="ModHelper.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Inheritance\SGame.cs" />