1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
using System;
using System.IO;
using StardewModdingAPI.Framework.Serialisation;
namespace StardewModdingAPI.Framework
{
/// <summary>Provides simplified APIs for writing mods.</summary>
internal class ModHelper : IModHelper, IDisposable
{
/*********
** Properties
*********/
/// <summary>Encapsulates SMAPI's JSON file parsing.</summary>
private readonly JsonHelper JsonHelper;
/*********
** Accessors
*********/
/// <summary>The full path to the mod's folder.</summary>
public string DirectoryPath { get; }
/// <summary>An API for loading content assets.</summary>
public IContentHelper Content { get; }
/// <summary>Simplifies access to private game code.</summary>
public IReflectionHelper Reflection { get; }
/// <summary>Metadata about loaded mods.</summary>
public IModRegistry ModRegistry { get; }
/// <summary>An API for managing console commands.</summary>
public ICommandHelper ConsoleCommands { get; }
/// <summary>Provides translations stored in the mod's <c>i18n</c> folder, with one file per locale (like <c>en.json</c>) containing a flat key => value structure. Translations are fetched with locale fallback, so missing translations are filled in from broader locales (like <c>pt-BR.json</c> < <c>pt.json</c> < <c>default.json</c>).</summary>
public ITranslationHelper Translation { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="displayName">The mod's display name.</param>
/// <param name="modDirectory">The full path to the mod's folder.</param>
/// <param name="jsonHelper">Encapsulate SMAPI's JSON parsing.</param>
/// <param name="modRegistry">Metadata about loaded mods.</param>
/// <param name="commandManager">Manages console commands.</param>
/// <param name="contentManager">The content manager which loads content assets.</param>
/// <param name="reflection">Simplifies access to private game code.</param>
/// <param name="translations">Provides translations stored in the mod folder.</param>
/// <exception cref="ArgumentNullException">An argument is null or empty.</exception>
/// <exception cref="InvalidOperationException">The <paramref name="modDirectory"/> path does not exist on disk.</exception>
public ModHelper(string displayName, string modDirectory, JsonHelper jsonHelper, IModRegistry modRegistry, CommandManager commandManager, SContentManager contentManager, IReflectionHelper reflection, ITranslationHelper translations)
{
// validate
if (string.IsNullOrWhiteSpace(modDirectory))
throw new ArgumentNullException(nameof(modDirectory));
if (jsonHelper == null)
throw new ArgumentNullException(nameof(jsonHelper));
if (modRegistry == null)
throw new ArgumentNullException(nameof(modRegistry));
if (!Directory.Exists(modDirectory))
throw new InvalidOperationException("The specified mod directory does not exist.");
// initialise
this.DirectoryPath = modDirectory;
this.JsonHelper = jsonHelper;
this.Content = new ContentHelper(contentManager, modDirectory, displayName);
this.ModRegistry = modRegistry;
this.ConsoleCommands = new CommandHelper(displayName, commandManager);
this.Reflection = reflection;
this.Translation = translations;
}
/****
** 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()
{
TConfig 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>
/// <returns>Returns the deserialised model, or <c>null</c> if the file doesn't exist or is empty.</returns>
public TModel ReadJsonFile<TModel>(string path)
where TModel : class
{
path = Path.Combine(this.DirectoryPath, path);
return this.JsonHelper.ReadJsonFile<TModel>(path);
}
/// <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);
this.JsonHelper.WriteJsonFile(path, model);
}
/****
** Translation
****/
/// <summary>Get a translation for the current locale. This is a convenience shortcut for <see cref="IModHelper.Translation"/>.</summary>
/// <param name="key">The translation key.</param>
public Translation Translate(string key)
{
return this.Translation.Translate(key);
}
/****
** Disposal
****/
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
public void Dispose()
{
// nothing to dispose yet
}
}
}
|