summaryrefslogtreecommitdiff
path: root/src/SMAPI/Program.cs
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2018-02-17 16:34:31 -0500
committerJesse Plamondon-Willard <github@jplamondonw.com>2018-02-17 18:54:57 -0500
commit4444b590f016ebecfc113a0dd4584723b0250f41 (patch)
treedea12bd0ad7d6c0328ffefcd47dc1c5166b4b8db /src/SMAPI/Program.cs
parent0c1bca3db044b6f228538f1738d52c31e4481e48 (diff)
downloadSMAPI-4444b590f016ebecfc113a0dd4584723b0250f41.tar.gz
SMAPI-4444b590f016ebecfc113a0dd4584723b0250f41.tar.bz2
SMAPI-4444b590f016ebecfc113a0dd4584723b0250f41.zip
add content pack feature (#436)
Diffstat (limited to 'src/SMAPI/Program.cs')
-rw-r--r--src/SMAPI/Program.cs90
1 files changed, 78 insertions, 12 deletions
diff --git a/src/SMAPI/Program.cs b/src/SMAPI/Program.cs
index fd2bb340..e0064714 100644
--- a/src/SMAPI/Program.cs
+++ b/src/SMAPI/Program.cs
@@ -394,7 +394,7 @@ namespace StardewModdingAPI
LocalizedContentManager.LanguageCode languageCode = this.ContentManager.GetCurrentLanguage();
// update mod translation helpers
- foreach (IModMetadata mod in this.ModRegistry.GetAll())
+ foreach (IModMetadata mod in this.ModRegistry.GetAll(contentPacks: false))
(mod.Mod.Helper.Translation as TranslationHelper)?.SetLocale(locale, languageCode);
}
@@ -652,15 +652,52 @@ namespace StardewModdingAPI
{
this.Monitor.Log("Loading mods...", LogLevel.Trace);
- // load mod assemblies
IDictionary<IModMetadata, string> skippedMods = new Dictionary<IModMetadata, string>();
+ void TrackSkip(IModMetadata mod, string reasonPhrase) => skippedMods[mod] = reasonPhrase;
+
+ // load content packs
+ foreach (IModMetadata metadata in mods.Where(p => p.IsContentPack))
+ {
+ // get basic info
+ IManifest manifest = metadata.Manifest;
+ this.Monitor.Log($"Loading {metadata.DisplayName} from {metadata.DirectoryPath.Replace(Constants.ModPath, "").TrimStart(Path.DirectorySeparatorChar)} (content pack)...", LogLevel.Trace);
+
+ // validate status
+ if (metadata.Status == ModMetadataStatus.Failed)
+ {
+ this.Monitor.Log($" Failed: {metadata.Error}", LogLevel.Trace);
+ TrackSkip(metadata, metadata.Error);
+ continue;
+ }
+
+ // load mod as content pack
+ IMonitor monitor = this.GetSecondaryMonitor(metadata.DisplayName);
+ IContentHelper contentHelper = new ContentHelper(contentManager, metadata.DirectoryPath, manifest.UniqueID, metadata.DisplayName, monitor);
+ IContentPack contentPack = new ContentPack(metadata.DirectoryPath, manifest, contentHelper, jsonHelper);
+ metadata.SetMod(contentPack, monitor);
+ this.ModRegistry.Add(metadata);
+ }
+ IModMetadata[] loadedContentPacks = this.ModRegistry.GetAll(assemblyMods: false).ToArray();
+
+ // load mods
{
- void TrackSkip(IModMetadata mod, string reasonPhrase) => skippedMods[mod] = reasonPhrase;
+ // get content packs by mod ID
+ IDictionary<string, IContentPack[]> contentPacksByModID =
+ loadedContentPacks
+ .GroupBy(p => p.Manifest.ContentPackFor.UniqueID)
+ .ToDictionary(
+ group => group.Key,
+ group => group.Select(metadata => metadata.ContentPack).ToArray(),
+ StringComparer.InvariantCultureIgnoreCase
+ );
+ // get assembly loaders
AssemblyLoader modAssemblyLoader = new AssemblyLoader(Constants.TargetPlatform, this.Monitor, this.Settings.DeveloperMode);
AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => modAssemblyLoader.ResolveAssembly(e.Name);
InterfaceProxyFactory proxyFactory = new InterfaceProxyFactory();
- foreach (IModMetadata metadata in mods)
+
+ // load from metadata
+ foreach (IModMetadata metadata in mods.Where(p => !p.IsContentPack))
{
// get basic info
IManifest manifest = metadata.Manifest;
@@ -676,7 +713,7 @@ namespace StardewModdingAPI
continue;
}
- // preprocess & load mod assembly
+ // load mod
string assemblyPath = metadata.Manifest?.EntryDll != null
? Path.Combine(metadata.DirectoryPath, metadata.Manifest.EntryDll)
: null;
@@ -704,6 +741,10 @@ namespace StardewModdingAPI
// initialise mod
try
{
+ // get content packs
+ if (!contentPacksByModID.TryGetValue(manifest.UniqueID, out IContentPack[] contentPacks))
+ contentPacks = new IContentPack[0];
+
// init mod helpers
IMonitor monitor = this.GetSecondaryMonitor(metadata.DisplayName);
IModHelper modHelper;
@@ -713,7 +754,7 @@ namespace StardewModdingAPI
IReflectionHelper reflectionHelper = new ReflectionHelper(manifest.UniqueID, metadata.DisplayName, this.Reflection, this.DeprecationManager);
IModRegistry modRegistryHelper = new ModRegistryHelper(manifest.UniqueID, this.ModRegistry, proxyFactory, monitor);
ITranslationHelper translationHelper = new TranslationHelper(manifest.UniqueID, manifest.Name, contentManager.GetLocale(), contentManager.GetCurrentLanguage());
- modHelper = new ModHelper(manifest.UniqueID, metadata.DirectoryPath, jsonHelper, contentHelper, commandHelper, modRegistryHelper, reflectionHelper, translationHelper);
+ modHelper = new ModHelper(manifest.UniqueID, metadata.DirectoryPath, jsonHelper, contentHelper, commandHelper, modRegistryHelper, reflectionHelper, translationHelper, contentPacks);
}
// get mod instance
@@ -735,7 +776,7 @@ namespace StardewModdingAPI
}
}
}
- IModMetadata[] loadedMods = this.ModRegistry.GetAll().ToArray();
+ IModMetadata[] loadedMods = this.ModRegistry.GetAll(contentPacks: false).ToArray();
// log skipped mods
this.Monitor.Newline();
@@ -757,6 +798,7 @@ namespace StardewModdingAPI
// log loaded mods
this.Monitor.Log($"Loaded {loadedMods.Length} mods" + (loadedMods.Length > 0 ? ":" : "."), LogLevel.Info);
+
foreach (IModMetadata metadata in loadedMods.OrderBy(p => p.DisplayName))
{
IManifest manifest = metadata.Manifest;
@@ -769,10 +811,30 @@ namespace StardewModdingAPI
}
this.Monitor.Newline();
+ // log loaded content packs
+ if (loadedContentPacks.Any())
+ {
+ string GetModDisplayName(string id) => loadedMods.First(p => id != null && id.Equals(p.Manifest?.UniqueID, StringComparison.InvariantCultureIgnoreCase))?.DisplayName;
+
+ this.Monitor.Log($"Loaded {loadedContentPacks.Length} content packs:", LogLevel.Info);
+ foreach (IModMetadata metadata in loadedContentPacks.OrderBy(p => p.DisplayName))
+ {
+ IManifest manifest = metadata.Manifest;
+ this.Monitor.Log(
+ $" {metadata.DisplayName} {manifest.Version}"
+ + (!string.IsNullOrWhiteSpace(manifest.Author) ? $" by {manifest.Author}" : "")
+ + (metadata.IsContentPack ? $" | content pack for {GetModDisplayName(metadata.Manifest.ContentPackFor.UniqueID)}" : "")
+ + (!string.IsNullOrWhiteSpace(manifest.Description) ? $" | {manifest.Description}" : ""),
+ LogLevel.Info
+ );
+ }
+ this.Monitor.Newline();
+ }
+
// initialise translations
- this.ReloadTranslations();
+ this.ReloadTranslations(loadedMods);
- // initialise loaded mods
+ // initialise loaded non-content-pack mods
foreach (IModMetadata metadata in loadedMods)
{
// add interceptors
@@ -891,11 +953,15 @@ namespace StardewModdingAPI
}
/// <summary>Reload translations for all mods.</summary>
- private void ReloadTranslations()
+ /// <param name="mods">The mods for which to reload translations.</param>
+ private void ReloadTranslations(IEnumerable<IModMetadata> mods)
{
JsonHelper jsonHelper = new JsonHelper();
- foreach (IModMetadata metadata in this.ModRegistry.GetAll())
+ foreach (IModMetadata metadata in mods)
{
+ if (metadata.IsContentPack)
+ throw new InvalidOperationException("Can't reload translations for a content pack.");
+
// read translation files
IDictionary<string, IDictionary<string, string>> translations = new Dictionary<string, IDictionary<string, string>>();
DirectoryInfo translationsDir = new DirectoryInfo(Path.Combine(metadata.DirectoryPath, "i18n"));
@@ -954,7 +1020,7 @@ namespace StardewModdingAPI
break;
case "reload_i18n":
- this.ReloadTranslations();
+ this.ReloadTranslations(this.ModRegistry.GetAll(contentPacks: false));
this.Monitor.Log("Reloaded translation files for all mods. This only affects new translations the mods fetch; if they cached some text, it may not be updated.", LogLevel.Info);
break;