User:MouseyPounds/Content Patcher/Modding Images

From Stardew Valley Wiki
Jump to: navigation, search
Note: This is a work in progress for future expansion of the Content Patcher Documentation in the Modding area

Changing sprites and textures is one of the most common modding tasks. This tutorial will develop a mod which changes the exterior of the farmhouse into a giant blueberry. Our fictitious modder goes by Tutorial Terry and the mod will be called Blueberry Farmhouse. Terry has already extracted Content/Buildings/houses.xnb and edited the resulting houses.png with their changes.

Replacing an Entire Image File

The easiest type of Content Patcher mod is one that simply replaces an entire content file, so that's where we'll start. First, we need to make a new folder for our mod within the Mods subfolder of the game folder. A fairly standard convention is to begin the name of a Content Patcher mod's folder with [CP] so we will name this folder [CP] Blueberry Farmhouse. As for what to put in that folder, a Content Patcher mod has 3 important pieces:

  1. The manifest.json which tells SMAPI about the mod.
  2. The content.json which tells Content Patcher what things to change.
  3. Any images or other support files the mod needs; these are commonly called "assets."

The manifest.json

The manifest file is pretty much boilerplate that will have very minimal changes from mod to mod. Here is our manifest file, which will remain basically the same for the entire tutorial.

{
   "Name": "Blueberry Farmhouse",   // Change this to your mod's full name
   "Author": "Tutorial Terry",      // Change this to your name or username
   "Version": "1.0.0",              // Change this when you release a new version
   "Description": "A new, blue look for the farmhouse exterior.",
   "UniqueID": "TutorialTerry.BlueberryFarmhouse",  // Standard is YourName.ModName
   "MinimumApiVersion": "2.8",      // Minimum SMAPI version, use whatever is current
   "UpdateKeys": [],
   "ContentPackFor": {
	  "UniqueID": "Pathoschild.ContentPatcher",
	  "MinimumVersion": "1.5.0" // Minimum Content Patcher version, use whatever is current
   }
}

Some important notes about the various fields are below. For more details, see the full documentation.

  • The Name and Author fields can contain spaces and punctuation, but the UniqueID (which is recommended to take the form <AuthorName>.<ModName>) should not have any white-space or special characters.
  • The MinimumApiVersion refers to SMAPI itself and the MinimumVersion under ContentPackFor refers to Content Patcher. These are the earliest versions which support your mod and generally should be whatever the current versions are.
  • The UpdateKeys are for SMAPI's automatic update-checking. While this mod may not be published (and therefore wouldn't use it), having a blank update key field in the standard manifest can be a good reminder to add such keys for mods which will be released publicly.

The content.json

The content file defines all the changes that we need Content Patcher to make. In this case, we want to replace the Content/Buildings/houses.xnb file with our edited PNG image. Here is our initial content file:

{
   "Format": "1.5",
   "Changes": [
       {
           "Action": "Load",
           "Target": "Buildings/houses",
           "FromFile": "assets/houses.png",
       },
   ]
}

That's it! As before, some important notes about the various fields are below, and more details can be found in the full documentation.

  • The Format refers to a Content Patcher version number and should match whatever was set as the minimum version in the manifest. As a general rule, just use the most current version.
  • The Load action is used for simply replacing a file; only 1 mod at a time can use this action on a particular file, and if more than 1 tries to do so, Content Patcher will log a warning message and leave that file unchanged.
  • The Target should not include the base Content/ directory or the .xnb extension. Since these are basically always present, Content Patcher automatically supplies them.
  • The FromFile refers to a local file within our mod directory, which leads us to the final piece...

Mod asset files

The assets are anything else the mod needs. Generally these are image, map, or text files which are being used to replace the game's original content. A standard convention is to group them all into an assets subfolder. However, this is not mandatory and a mod could use subfolders that match the game's content hierarchy, its own custom hierarchy, or even just keep everything in the base directory. Our mod will use an assets subfolder, and we will place our edited houses.png file within it.

The entire mod folder is now complete (see hierarchy below) and we are ready to use it in-game.

   [CP] Blueberry Farmhouse/
       manifest.json
       content.json
       assets/
           houses.png

Replacing Only Part of an Image

You may have noticed that Content/Buildings/houses.xnb contains not only the farmhouses, but also the greenhouse. Since our mod only actually edits the farmhouses, replacing the entire file is overkill. So our next step will be to change the mod so that it only actually replaces the textures we are editing.

Using EditImage

Pixel coordinates and measurements (image shows a 16 pixel grid)

Editing only part of an image requires the use of the EditImage action, instead of Load. And in order to tell Content Patcher what part of the image to change, we will need to get appropriate coordinates. Image coordinates are measured in pixels and start at (0,0) in the upper-left corner. Although there is some blank space to the left of the farmhouses, we are going to use (0,0) as our origin point to keep everything aligned on a 16-pixel square grid. Since the farmhouses end at 159, our width will be 160, and the height is the full height of the image (432 pixels). Note that we could crop our houses.png to just that area if we wished, but for now we are keeping that image unchanged.

This results in the following new content.json:

{
   "Format": "1.5",
   "Changes": [
       {
           "Action": "EditImage",
           "Target": "Buildings/houses",
           "FromFile": "assets/houses.png",
           "ToArea": { "X":0, "Y":0, "Width":160, "Height":432 },
           // FromArea entry could be removed if image was cropped
           "FromArea": { "X":0, "Y":0, "Width":160, "Height":432 },
       },
   ]
}

There are no changes needed for the manifest.json, although we'll bump the version to 1.1.0 since this is an update containing a small optimization that should be transparent to the player.

Seasonal Variations

Our next update will provide (slightly) different graphics for each season. Content Patcher supports seasonal variations through its token system, and the season tokens are probably the easiest to use.

The {{Season}} Token

The {{Season}} token is a special placeholder which Content Patcher will automatically change to match the current season name. So if we have a patch that references the file assets/houses_{{Season}}.png, Content Patcher will interpret that as assets/houses_spring.png during the Spring, assets/houses_summer.png during the Summer, and so on. Thus we only need a minor change in the content.json to enable this behavior. Here is our new, improved content file:

{
   "Format": "1.5",
   "Changes": [
       {
           "Action": "EditImage",
           "Target": "Buildings/houses",
           "FromFile": "assets/houses_{{Season}}.png",
           "ToArea": { "X":0, "Y":0, "Width":160, "Height":432 },
           "FromArea": { "X":0, "Y":0, "Width":160, "Height":432 },
       },
   ]
}

Literally the only thing to change was adding the token to the end of the filename. Of course, our modder still has to make the textures, meaning we'll have 4 new files. Terry has changed the dirt underneath the blueberry to a seasonal grass texture, placed a small decoration to the left of the house, and added some additional hanging decorations. Because we might have a use for the original version later, we are going to leave that one alone and make the four seasonal textures from copies. The result is the following file hierarchy:

   [CP] Blueberry Farmhouse/
       manifest.json
       content.json
       assets/
           houses.png (This is the original which is currently not used)
           houses_spring.png
           houses_summer.png
           houses_fall.png
           houses_winter.png


As with the previous update, the only thing we will do with the manifest.json is to increment the version. Terry has decided to call it version 2.0.0 since this is a new feature that adds functionality to the mod.

User Configuration

So why did we leave the original houses.png file in the mod? Terry was thinking that some people might not want the seasonal variations and would prefer to use the original one if we gave them the option, and that's what we will do next. By adding a ConfigSchema section to our content file, Content Patcher will create a config.json file for our mod the first time it loads. The player can then change any options which we supply and we can use those preferences to change how the mod behaves.

Creating the Configuration Options

To make things easier for the player, we want to give our configuration option an intuitive name. We will call it UseSeasonalTextures and let it be set to either true or false. For clarity, we will also explicitly mark true as the default since we think most players would use that option. That section will look like this:

   "ConfigSchema": {
       "UseSeasonalTextures": {
           "AllowValues": "true, false",
           "Default": "true",
       },
   },

In this case, the different fields should be self-explanatory, but there is more detailed documentation available.

Enabling a Patch with a Configuration Token

Since this is a true/false option, we can use its value directly to tell Content Patcher whether or not to enable a particular patch. The way we will approach this is to always load the original non-seasonal graphic as a default case, and then have our seasonal version override that if the player has set the option to do so. This is done by adding an Enabled field to the seasonal patch and setting it to a token named the same as the configuration option. The content file is a good deal larger now with the addition of the configuration option and the need for two patch definitions. Here it is:

{
   "Format": "1.5",
   "ConfigSchema": {
       "UseSeasonalTextures": {
           "AllowValues": "true, false",
           "Default": "true",
       },
   },
   "Changes": [
       {
           "LogName": "Default non-seasonal farmhouse",
           "Action": "EditImage",
           "Target": "Buildings/houses",
           "FromFile": "assets/houses.png",
           "ToArea": { "X":0, "Y":0, "Width":160, "Height":432 },
           "FromArea": { "X":0, "Y":0, "Width":160, "Height":432 },
       },
       {
           "LogName": "Optional seasonal farmhouse",
           "Action": "EditImage",
           "Target": "Buildings/houses",
           "FromFile": "assets/houses_{{Season}}.png",
           "ToArea": { "X":0, "Y":0, "Width":160, "Height":432 },
           "FromArea": { "X":0, "Y":0, "Width":160, "Height":432 },
           "Enabled": "{{UseSeasonalTextures}}",
       },
   ]
}

Terry snuck one other little change into our content file: a LogName entry on each patch definition. These let us briefly describe the patches and are primarily for troubleshooting since Content Patcher will use these names when logging errors or debug information. However -- especially when they are placed first in the patch definition -- they also serve as a comment that makes the content a little easier to read.

Overlays and Additional Conditions

The final part of this tutorial involves further conditional texture changes. First, Terry thought that since the blueberry has a large indentation at the top, it would probably fill with water during rain storms. So our first step is to implement such a change.

An Overlay Patch

With rain naturally occurring in multiple seasons, it might seem like we need to make multiple rain textures. However, Content Patcher allows us to create an Overlay patch which is just drawn on top of another image. So by using an overlay, 1 rain texture could be applied on top of the basic house, regardless of which version of the house is underneath it. The image itself contains only the pool of rain on top of the house, with everything else transparent so that the base house texture shows through. The patch looks very similar to previous patch definitions we've used, with an additional Patchmode entry:

       {
           "LogName": "Rain Overlay",
           "Action": "EditImage",
           "Target": "Buildings/houses",
           "FromFile": "assets/RainOverlay.png",
           "PatchMode": "overlay",
           "ToArea": { "X":0, "Y":0, "Width":160, "Height":432 },
           "FromArea": { "X":0, "Y":0, "Width":160, "Height":432 },
           "When": { "Weather": "Rain, Storm" }
       },

Conditions and "When"

The other big addition was the When entry. This causes the patch to be applied only on days where it is raining (including thunderstorms). There are a wide variety of possible conditions to use including days and dates, event completions, mail flags, and relationship status. For example, the house could have special decorations on particular festival days, or for a particular NPC spouse.

Footer here - Previous would be Getting Started Next would be Modding Text