Difference between revisions of "Modding:Modder Guide/APIs/Content Packs"
(some additions and tips) |
m (Replace deprecated <source> tags with <syntaxhighlight> tags) |
||
Line 12: | Line 12: | ||
===Get owned content packs=== | ===Get owned content packs=== | ||
To get the content packs installed for your mod (including a <tt>Manifest</tt> field with the content pack's [[Modding:Modder Guide/APIs/Manifest|full manifest info]]): | To get the content packs installed for your mod (including a <tt>Manifest</tt> 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()) | foreach(IContentPack contentPack in this.Helper.ContentPacks.GetOwned()) | ||
{ | { | ||
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} from {contentPack.DirectoryPath}"); | ||
} | } | ||
− | </ | + | </syntaxhighlight> |
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. | 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. | ||
Line 26: | Line 26: | ||
You can check if a file exists in the content pack folder using <tt>HasFile</tt>. You can specify a relative path like <tt>data/content.json</tt>. | You can check if a file exists in the content pack folder using <tt>HasFile</tt>. You can specify a relative path like <tt>data/content.json</tt>. | ||
− | < | + | <syntaxhighlight lang="c#"> |
if (!contentPack.HasFile("content.json")) | if (!contentPack.HasFile("content.json")) | ||
{ | { | ||
// show 'required file missing' error | // show 'required file missing' error | ||
} | } | ||
− | </ | + | </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. | 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. | ||
Line 38: | Line 38: | ||
You can read a JSON file from a content pack folder into [[Modding:Modder Guide/APIs/Data#Data model|a data model]] (<tt>YourDataModel</tt> in the example below) using <tt>ReadJsonFile</tt>. You can specify a relative path like <tt>data/content.json</tt>. This will return <tt>null</tt> if the file doesn't exist. | You can read a JSON file from a content pack folder into [[Modding:Modder Guide/APIs/Data#Data model|a data model]] (<tt>YourDataModel</tt> in the example below) using <tt>ReadJsonFile</tt>. You can specify a relative path like <tt>data/content.json</tt>. This will return <tt>null</tt> if the file doesn't exist. | ||
− | < | + | <syntaxhighlight lang="c#"> |
YourDataModel data = contentPack.ReadJsonFile<YourDataFile>("content.json"); | YourDataModel data = contentPack.ReadJsonFile<YourDataFile>("content.json"); | ||
− | </ | + | </syntaxhighlight> |
===Write a JSON file=== | ===Write a JSON file=== | ||
Line 47: | Line 47: | ||
'''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. | '''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(); | YourDataModel data = new YourDataModel(); | ||
contentPack.WriteJsonFile("content.json", data); | contentPack.WriteJsonFile("content.json", data); | ||
− | </ | + | </syntaxhighlight> |
===Read content asset=== | ===Read content asset=== | ||
You can read [[Modding:Modder Guide/APIs/Content|a content asset]] from the content pack folder using <tt>LoadAsset</tt>. You can optionally specify a relative path to read from a subfolder. | You can read [[Modding:Modder Guide/APIs/Content|a content asset]] from the content pack folder using <tt>LoadAsset</tt>. You can optionally specify a relative path to read from a subfolder. | ||
− | < | + | <syntaxhighlight lang="c#"> |
Texture2D image = contentPack.LoadAsset<Texture2D>("image.png"); | Texture2D image = contentPack.LoadAsset<Texture2D>("image.png"); | ||
− | </ | + | </syntaxhighlight> |
If you need to pass an asset name to game code, you can use the <tt>GetActualAssetKey</tt> method: | If you need to pass an asset name to game code, you can use the <tt>GetActualAssetKey</tt> method: | ||
− | < | + | <syntaxhighlight lang="c#"> |
tilesheet.ImageSource = contentPack.GetActualAssetKey("image.png"); | tilesheet.ImageSource = contentPack.GetActualAssetKey("image.png"); | ||
− | </ | + | </syntaxhighlight> |
===Get translations=== | ===Get translations=== | ||
You can read translations from the content pack's <tt>i18n</tt> folder. This is identical to the [[Modding:Modder Guide/APIs/Translation|translation API]], but accessed through <tt>contentPack.Translations</tt>: | You can read translations from the content pack's <tt>i18n</tt> folder. This is identical to the [[Modding:Modder Guide/APIs/Translation|translation API]], but accessed through <tt>contentPack.Translations</tt>: | ||
− | < | + | <syntaxhighlight lang="c#"> |
string text = contentPack.Translation.Get("item-type.label"); | string text = contentPack.Translation.Get("item-type.label"); | ||
− | </ | + | </syntaxhighlight> |
===Create a fake content pack=== | ===Create a fake content pack=== | ||
In specialised cases, you can create a temporary content pack for a given directory path: | In specialised cases, you can create a temporary content pack for a given directory path: | ||
− | < | + | <syntaxhighlight lang="c#"> |
// create with random manifest data | // create with random manifest data | ||
IContentPack contentPack = this.Helper.ContentPacks.CreateFake( | IContentPack contentPack = this.Helper.ContentPacks.CreateFake( | ||
Line 86: | Line 86: | ||
version: new SemanticVersion(1, 0, 0) | version: new SemanticVersion(1, 0, 0) | ||
); | ); | ||
− | </ | + | </syntaxhighlight> |
Revision as of 18:21, 19 February 2021
- Get started
- Game fundamentals
- Test & troubleshoot
- Release
- API reference
- Basic SMAPI APIs:
- Advanced SMAPI APIs:
- Specific guides
A content pack is a special type of mod that isn't run by SMAPI directly, but contains files your own mod can read.
Content pack format
A content pack is a folder containing a manifest.json file which specifies your mod in its ContentPackFor field (see manifest). The format beyond that is up to you to define. For example, Content Patcher requires a content.json 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 Manifest field with the content pack's full manifest info):
foreach(IContentPack contentPack in this.Helper.ContentPacks.GetOwned())
{
this.Monitor.Log($"Reading content pack: {contentPack.Manifest.Name} {contentPack.Manifest.Version} from {contentPack.DirectoryPath}");
}
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.
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.
Check if a file exists
You can check if a file exists in the content pack folder using HasFile. You can specify a relative path like data/content.json.
if (!contentPack.HasFile("content.json"))
{
// show 'required file missing' error
}
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 a data model (YourDataModel in the example below) using ReadJsonFile. You can specify a relative path like data/content.json. This will return null if the file doesn't exist.
YourDataModel data = contentPack.ReadJsonFile<YourDataFile>("content.json");
Write a JSON file
You can write a JSON file in a content pack folder using WriteJsonFile, using a data model (YourDataModel in the example below). You can specify a relative path like data/content.json (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.
YourDataModel data = new YourDataModel();
contentPack.WriteJsonFile("content.json", data);
Read content asset
You can read a content asset from the content pack folder using LoadAsset. You can optionally specify a relative path to read from a subfolder.
Texture2D image = contentPack.LoadAsset<Texture2D>("image.png");
If you need to pass an asset name to game code, you can use the GetActualAssetKey method:
tilesheet.ImageSource = contentPack.GetActualAssetKey("image.png");
Get translations
You can read translations from the content pack's i18n folder. This is identical to the translation API, but accessed through contentPack.Translations:
string text = contentPack.Translation.Get("item-type.label");
Create a fake content pack
In specialised cases, you can create a temporary content pack for a given directory path:
// 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.CreateFake(
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)
);