/// <summary>Extract information from a mod folder.</summary> /// <param name="root">The root folder containing mods.</param> /// <param name="searchFolder">The folder to search for a mod.</param> public ModFolder ReadFolder(DirectoryInfo root, DirectoryInfo searchFolder) { // find manifest.json FileInfo manifestFile = this.FindManifest(searchFolder); // set appropriate invalid-mod error if (manifestFile == null) { FileInfo[] files = this.RecursivelyGetRelevantFiles(searchFolder).ToArray(); // empty folder if (!files.Any()) { return(new ModFolder(root, searchFolder, ModType.Invalid, null, ModParseError.EmptyFolder, "it's an empty folder.")); } // XNB mod if (files.All(this.IsPotentialXnbFile)) { return(new ModFolder(root, searchFolder, ModType.Xnb, null, ModParseError.XnbMod, "it's not a SMAPI mod (see https://smapi.io/xnb for info).")); } // SMAPI installer if (files.Any(p => p.Name == "install on Linux.sh" || p.Name == "install on Mac.command" || p.Name == "install on Windows.bat")) { return(new ModFolder(root, searchFolder, ModType.Invalid, null, ModParseError.ManifestMissing, "the SMAPI installer isn't a mod (you can delete this folder after running the installer file).")); } // not a mod? return(new ModFolder(root, searchFolder, ModType.Invalid, null, ModParseError.ManifestMissing, "it contains files, but none of them are manifest.json.")); } // read mod info Manifest manifest = null; ModParseError error = ModParseError.None; string errorText = null; { try { if (!this.JsonHelper.ReadJsonFileIfExists <Manifest>(manifestFile.FullName, out manifest) || manifest == null) { error = ModParseError.ManifestInvalid; errorText = "its manifest is invalid."; } } catch (SParseException ex) { error = ModParseError.ManifestInvalid; errorText = $"parsing its manifest failed: {ex.Message}"; } catch (Exception ex) { error = ModParseError.ManifestInvalid; errorText = $"parsing its manifest failed:\n{ex}"; } } // normalize display fields if (manifest != null) { manifest.Name = this.StripNewlines(manifest.Name); manifest.Description = this.StripNewlines(manifest.Description); manifest.Author = this.StripNewlines(manifest.Author); } // get mod type ModType type = ModType.Invalid; if (manifest != null) { type = !string.IsNullOrWhiteSpace(manifest.ContentPackFor?.UniqueID) ? ModType.ContentPack : ModType.Smapi; } // build result return(new ModFolder(root, manifestFile.Directory, type, manifest, error, errorText)); }
/// <summary>Construct an instance.</summary> /// <param name="root">The root folder containing mods.</param> /// <param name="directory">The folder containing the mod's manifest.json.</param> /// <param name="type">The mod type.</param> /// <param name="manifest">The mod manifest.</param> /// <param name="manifestParseError">The error which occurred parsing the manifest, if any.</param> /// <param name="manifestParseErrorText">A human-readable message for the <paramref name="manifestParseError"/>, if any.</param> public ModFolder(DirectoryInfo root, DirectoryInfo directory, ModType type, Manifest manifest, ModParseError manifestParseError, string manifestParseErrorText) { // save info this.Directory = directory; this.Type = type; this.Manifest = manifest; this.ManifestParseError = manifestParseError; this.ManifestParseErrorText = manifestParseErrorText; // set display name this.DisplayName = manifest?.Name; if (string.IsNullOrWhiteSpace(this.DisplayName)) { this.DisplayName = PathUtilities.GetRelativePath(root.FullName, directory.FullName); } }