Line 1: |
Line 1: |
| {{../../header}} | | {{../../header}} |
| | | |
− | ===Content packs===
| + | A '''content pack''' is a special type of mod that isn't run by SMAPI directly, but contains files your own mod can read. |
− | A content pack is a sub-mod containing files your mod can read. These are installed just like a regular SMAPI mod, but don't do anything on their own. These must specify your mod in their <tt>manifest.json</tt>. See [[Modding:Content packs]] for more info about content packs. | |
| | | |
− | SMAPI provides a method to get content packs loaded for your mod, and each content pack has an API you can use to read its files:
| + | __TOC__ |
− | <source lang="c#"> | + | ==Content pack format== |
− | foreach(IContentPack contentPack in this.Helper.GetContentPacks()) | + | A content pack is a folder containing a <samp>manifest.json</samp> file which specifies your mod in its <samp>ContentPackFor</samp> field (see [[../Manifest|manifest]]). The format beyond that is up to you to define. For example, {{nexus mod|1915|Content Patcher}} requires a <samp>content.json</samp> file, but that's not validated by SMAPI itself. Instead, SMAPI provides an API you can use to read any other file you need from the content pack. |
| + | |
| + | See [[Modding:Content packs]] for more info about content packs. |
| + | |
| + | ==Content pack API== |
| + | ===Get owned content packs=== |
| + | To get the content packs installed for your mod (including a <samp>Manifest</samp> field with the content pack's [[Modding:Modder Guide/APIs/Manifest|full manifest info]]): |
| + | <syntaxhighlight lang="c#"> |
| + | foreach(IContentPack contentPack in this.Helper.ContentPacks.GetOwned()) |
| { | | { |
− | // read content pack manifest
| + | this.Monitor.Log($"Reading content pack: {contentPack.Manifest.Name} {contentPack.Manifest.Version} from {contentPack.DirectoryPath}"); |
− | this.Monitor.Log($"Reading content pack: {contentPack.Manifest.Name} {contentPack.Manifest.Version}");
| + | } |
| + | </syntaxhighlight> |
| | | |
− | // read a JSON file
| + | Content packs are listed in load order, so they're already sorted for dependencies. For example, if content pack B requires A, they'll be listed in the order A → B. |
− | YourDataFile data = contentPack.ReadJsonFile<YourDataFile>("content.json");
| |
| | | |
− | // load an asset or image
| + | As a note, this can be done as early as ModEntry, although mods often choose to perform this step in the GameLoad or SaveLoaded event. |
− | Texture2D image = contentPack.LoadAsset<Texture2D>("image.png");
| + | |
| + | ===Check if a file exists=== |
| + | You can check if a file exists in the content pack folder using <samp>HasFile</samp>. You can specify a relative path like <samp>data/content.json</samp>. |
| + | |
| + | <syntaxhighlight lang="c#"> |
| + | if (!contentPack.HasFile("content.json")) |
| + | { |
| + | // show 'required file missing' error |
| } | | } |
− | </source> | + | </syntaxhighlight> |
| + | |
| + | It is often a good idea to alert the player (and modders who may be using your mod) if the file is missing on deployment. |
| + | |
| + | ===Read a JSON file=== |
| + | You can read a JSON file from a content pack folder into [[Modding:Modder Guide/APIs/Data#Data model|a data model]] (<samp>YourDataModel</samp> in the example below) using <samp>ReadJsonFile</samp>. You can specify a relative path like <samp>data/content.json</samp>. This will return <samp>null</samp> if the file doesn't exist. |
| + | |
| + | <syntaxhighlight lang="c#"> |
| + | YourDataModel data = contentPack.ReadJsonFile<YourDataFile>("content.json"); |
| + | </syntaxhighlight> |
| + | |
| + | ===Write a JSON file=== |
| + | You can write a JSON file in a content pack folder using <samp>WriteJsonFile</samp>, using a [[Modding:Modder Guide/APIs/Data#Data model|data model]] (<samp>YourDataModel</samp> in the example below). You can specify a relative path like <samp>data/content.json</samp> (subdirectories will be created automatically if needed). This will create the file if it doesn't exist, or overwrite it if it does. |
| + | |
| + | '''Note:''' this is best used for generated files. Overwriting the original files isn't recommended, since a bug in your mod which changes an original file might permanently break the content pack and require the player to reinstall it. |
| + | |
| + | <syntaxhighlight lang="c#"> |
| + | YourDataModel data = new YourDataModel(); |
| + | contentPack.WriteJsonFile("content.json", data); |
| + | </syntaxhighlight> |
| + | |
| + | ===Read content asset=== |
| + | You can read [[Modding:Modder Guide/APIs/Content|a content asset]] from the content pack folder using <samp>LoadAsset</samp>. You can optionally specify a relative path to read from a subfolder. |
| + | <syntaxhighlight lang="c#"> |
| + | Texture2D image = contentPack.ModContent.Load<Texture2D>("image.png"); |
| + | </syntaxhighlight> |
| + | |
| + | If you need to pass an asset name to game code, you can use the <samp>GetActualAssetKey</samp> method: |
| + | <syntaxhighlight lang="c#"> |
| + | tilesheet.ImageSource = contentPack.GetActualAssetKey("image.png"); |
| + | </syntaxhighlight> |
| + | |
| + | ===Get translations=== |
| + | You can read translations from the content pack's <samp>i18n</samp> folder. This is identical to the [[Modding:Modder Guide/APIs/Translation|translation API]], but accessed through <samp>contentPack.Translations</samp>: |
| + | <syntaxhighlight lang="c#"> |
| + | string text = contentPack.Translation.Get("item-type.label"); |
| + | </syntaxhighlight> |
| + | |
| + | ===Create a fake content pack=== |
| + | In specialised cases, you can create a temporary content pack for a given directory path: |
| + | <syntaxhighlight lang="c#"> |
| + | // create with random manifest data |
| + | IContentPack contentPack = this.Helper.ContentPacks.CreateFake( |
| + | directoryPath: Path.Combine(this.Helper.DirectoryPath, "content-pack"), |
| + | ); |
| + | |
| + | // create with given manifest fields |
| + | IContentPack contentPack = this.Helper.ContentPacks.CreateTemporary( |
| + | directoryPath: Path.Combine(this.Helper.DirectoryPath, "content-pack"), |
| + | id: Guid.NewGuid().ToString("N"), |
| + | name: "temporary content pack", |
| + | description: "...", |
| + | author: "...", |
| + | version: new SemanticVersion(1, 0, 0) |
| + | ); |
| + | </syntaxhighlight> |