-
Notifications
You must be signed in to change notification settings - Fork 17
Creating a Content Pack
A content pack for Alternative Textures (AT) allows for texture variation for most placeable objects (including from Json Assets and DGA), furniture, entities (farm animals and horses) and buildings (including those from Solid Foundations).
These content packs are compatible with other AT content packs, meaning multiple packs can modify the same object (e.g. multiple AT content packs can offer alternative textures for the Mini-Obelisk object).
The concept for adding a new texture variation is very similar to replacing a texture via Content Patcher's Load action.
-
Create a parent folder with the content pack's name.
-
Create and fill in
manifest.jsonas a content pack. -
Create a
Texturesfolder, add it under the content pack's main folder. -
Create a sub-folder under
Textureswith the name of the objecta. The name of the folder(s) under
Texturesdo not matter, but it is recommended to use the object's name for clarity. -
Create a
texture.jsonunder the created sub-folder, using the required fields found here. -
Create a
texture.pngunder the same sub-folder.a. This image file should be a modified version of the object's existing sprite.
b. You can use individual split textures (e.g.
texture_0.png,texture_1.png...) rather than a singletexture.png.c. If both split textures files and
texture.pngexist under the same folder,texture.pngwill be used instead.
An Alternative Textures content pack consists of the following structure:
[AT] Example Pack
├── manifest.json
│
└── Textures
├── Cask_Summer
│ ├── texture.json
│ └── texture.png
│
├── Suit_Of_Armor
│ ├── texture.json
│ ├── texture_0.png
│ └── texture_1.png
│
└── Sunflower
├── texture.json
└── texture.png
If this is your first time creating a content pack, it may be useful to read the Stardew Valley Wiki for creating a content pack.
The first step to making your content pack is to create a top level folder with the name of your content pack. For example: [AT] Example Pack.
After that, you'll want to create the manifest.json file under that folder. Detailed instructions can be found on the Stardew Valley Wiki. Additionally, you can check out the example manifest.json as a reference.
For example:
[AT] Example Pack
└── manifest.json
It is important to note that the manifest.json file must contain the following for it to be a content pack by Alternative Textures:
"ContentPackFor": {
"UniqueID": "PeacefulEnd.AlternativeTextures",
"MinimumVersion": "USE.LATEST.VERSION"
}Note: Replace "MinimumVersion": "USE.LATEST.VERSION" with the latest version number of Alternative Textures found here.
You will first need to create a Textures folder underneath your main content pack folder.
After creating the Textures folder you'll want to create a sub-folder for every object you want to modify, like so:
.
└── Textures
├── Poppy
│
├── Suit_Of_Armor
│
├── MiniObelisk_Summer
│
└── MiniObelisk_Winter
You can also have sub-folders under the Textures folder for organizing, like so:
.
└── Textures
├── Summer
│ ├── MiniObelisk
│ └── Poppy
│
└── Winter
└── MiniObelisk
To add an alternative texture to your content pack, the framework requires a texture.json under each sub-folder of Textures.
For example:
.
└── Textures
├── Poppy
│ ├── texture.json
│ └── texture.png
│
├── Suit_Of_Armor
│ ├── texture.json
│ ├── texture_0.png
│ └── texture_1.png
│
├── MiniObelisk_Summer
│ ├── texture.json
│ └── texture.png
│
└── MiniObelisk_Winter
├── texture.json
└── texture.png
The file texture.json determines what object to give alternative textures and what variations to apply.
An overview of the required properties for texture.json:
| Property | Description | Default | |
|---|---|---|---|
ItemName |
Optional1 | Name of the item which must match exactly to the item's name. See this page for more details |
N/A |
ItemId |
Optional1 | Id of the item which must match exactly to the item's ID. See this page for more details |
N/A |
CollectiveNames |
Optional1 | List of ItemName which allows for multiple items to be associated to the texture.See this section for more details |
[] |
CollectiveIds |
Optional1 | List of ItemId which allows for multiple items to be associated to the texture.See this section for more details |
[] |
Type |
Required | The type of the item (e.g. Crop for crops, Craftable for chests)See this page for more details |
N/A |
Keywords |
Optional | Used by paint bucket's search function to allow for easier searching of specific textures | ["UNIQUEID"] |
Seasons |
Optional | The specific seasons for the textures to appear (leaving blank will allow for all seasons) See this section for more details |
[] |
TextureWidth 2
|
Required | Width of the texture in pixels Note: This is the width of the item's vanilla texture, which may not match to texture.png's width |
N/A |
TextureHeight 2
|
Required | Height of the texture in pixels Note: This is the height of the item's vanilla texture, which may not match to texture.png's height |
N/A |
Variations |
Required | The number of variations within textures.png (i.e. rows of variations)Required if not using ManualVariations
|
1 |
DefaultVariation |
Optional | If specified, the framework will always use the given variation when randomly selecting from this pack. Overrides ChanceWeight for ManualVariations. |
N/A |
ManualVariations |
Optional | Overrides VariationsSee this section for more details |
N/A |
Animation |
Optional | A list of frames and durations, which allow for animation. Only supported for Furniture and Craftable objects.See this section for more details |
N/A |
IgnoreBuildingColorMask |
Optional | If set to true, the framework will ignore the paint mask texture required for certain buildings. Only applicable to Type.Building. |
N/A |
-
ItemName,ItemId,CollectiveNamesorCollectiveIdsmust be given for the texture to be valid.
-
TextureWidthandTextureHeightrequire the dimensions of the item being replaced, which may not exactly match the width or height oftexture.png.
a. Sunflowers would have aTextureWidthof 96 and aTextureHeightof 32.
b. Mini-Obelisks would have aTextureWidthof 16 and aTextureHeightof 32.
c. Apple Sapling would have aTextureWidthof 432 and aTextureHeightof 80.
d. Loom would have aTextureWidthof 16 and aTextureHeightof 32.
e. Gate would have aTextureWidthof 48 and aTextureHeightof 224.
f. Wood Fence would have aTextureWidthof 48 and aTextureHeightof 128.
g. Brown Couch would have aTextureWidthof 128 and aTextureHeightof 96.
h. Sprinkler would have aTextureWidthof 16 and aTextureHeightof 32.
Note: The framework expects all available frames for items with animations, such as the Loom. See the example pack for reference.
This is a simple texture.json, which adds a two texture variations for the Sunflower object.
You can see Variations was given the value of 2. This value reflects the amount of rows within texture.png, which is divided by the given value in TextureHeight.
In this example, each texture variation has a ~33% chance of occurring (one third for each of the two variations and one third for the default game texture).
The corresponding texture.png

The texture.png should (in most cases) be a "copy" of the original sprite in terms of TextureWidth.
See the example pack for references on how to create your textures.
The framework normally expects a single texture.png that contains all the variations of the particular object for its respective texture.json.
Individual texture files can be used instead of a single file, if the following rules are observed:
- Each individual texture file must use the naming scheme of
texture_#.png. - The first split texture variation of an object should always be the name of
texture_0.pngortexture_1.png. - If you mix both
texture.pngand split textures (i.e.texture_#.png), the former will be used instead.
See this example of an object with split texture variation files.
The corresponding split texture image files:
texture_1.png

texture_2.png

This is an example texture.json, which shows variations for the animated machine Loom object.
{
"ItemName": "Loom",
"Type": "Craftable",
"TextureWidth": 16,
"TextureHeight": 32,
"Variations": 2
}You can see Variations was given the value of 2. This value reflects the amount of rows within texture.png, which is divided by the given value in TextureHeight.
The corresponding texture.png

The texture.png should (in most cases) be a "copy" of the original sprite in terms of TextureWidth.
Note: The Loom is one of the exceptions for how texture.png is to be used.
The optional Seasons property accepts an array of season names. If specified, the framework will limit the texture's appearance to only occur during those specified seasons. This is useful if you want to display different textures for different seasons, such as with fences.
If your content pack does not have a match to a season (and you specified other seasons for the object), the framework will display the default vanilla texture.
For example, consider the following summer texture variation:
{
"ItemName": "Apple Sapling",
"Type": "FruitTree",
"Seasons": ["Summer"],
"TextureWidth": 432,
"TextureHeight": 80,
"Variations": 2
}In the above example, the framework would only use that texture if the sapling was planted during the summer (and if it was picked from the available pool of apple sapling summer textures).
Once the season becomes fall, the framework will temporarily revert it back to the vanilla texture until the summer season reoccurs.
However, if you included another apple sapling texture variation within the same content pack like so:
{
"ItemName": "Apple Sapling",
"Type": "FruitTree",
"Seasons": ["Spring", "Fall", "Winter"],
"TextureWidth": 432,
"TextureHeight": 80,
"Variations": 2
}The framework would then utilize those texture variations when the seasons changed from summer, instead of the default vanilla textures.
You'll notice the sunflower example used the Variation property with a given value of 2 with an even chance of occurring for any of the variations.
If you want to give each texture variation a different chance of occurring, then you can utilize the ManualVariation property like so:
{
"ItemName": "Sunflower Seeds",
"Type": "Crop",
"TextureWidth": 96,
"TextureHeight": 32,
"ManualVariations": [
{
"Id": -1, // Note: -1 is the default vanilla texture. It is not required, but it allows better control of when the vanilla texture appears
"ChanceWeight": 0.9 // This is an optional value which determines the chance of this variation appearing (see details below)
},
{
"Id": 0,
"Name": "Custom Name Here", // This is an optional value which overrides how the framework displays its name (see details below)
"ChanceWeight": 0.1
},
{
"Id": 1,
"ChanceWeight": 0.5
}
]
}Note: The Id field is zero-indexed, meaning the first texture has an Id of 0, the second texture is 1 and so on.
Additional Note: If you specify an Id of -1, you can override the probability of the vanilla texture being chosen.
The optional Name property is a text value which will override how the texture's name is displayed in the various UI's available in the framework (Paint Bucket, Scissors).
If the property is not given, the framework will display the name as the content pack's UniqueID and the texture's variation (i.e. it'll be displayed as UniqueID -> Variation #).
The optional ChanceWeight property is a decimal value from 0 to 1.0 which determines the likelihood of a texture being selected when the object or entity is created. This property is only available if using ManualVariations.
Each variation under ManualVariations has its own independent probability of appearing via ChanceWeight. This means if two variations use a ChanceWeight of 0.75, then both have a 75% chance of occurring (assuming the vanilla texture isn't picked).
As this property is optional, omitting will result in a ChanceWeight value of 1.0.
The Keywords property is used by the paint bucket tool to allow users to more easily search for specific textures for the selected item.
By default, the Keywords property is populated with the content pack's UniqueId value in manifest.json.
Example Keywords usage:
{
"ItemName": "Sunflower Seeds",
"Type": "Crop",
"TextureWidth": 96,
"TextureHeight": 32,
"Keywords": [ "Test", "Other test", "Etc." ],
"Variations": 2
}Manual variations are also capable of utilizing the Keywords property with some slight differences:
- The top-level parent
Keywordsshares its values with allManualVariations. -
Keywordslisted inManualVariationsaren't shared with the top-level parentKeywords. -
Keywordslisted inManualVariationsaren't shared with other variations.
Example ManualVariations Keywords usage:
{
"ItemName": "Sunflower Seeds",
"Type": "Crop",
"TextureWidth": 96,
"TextureHeight": 32,
"Keywords": [ "This is shared with all ManualVariations" ],
"ManualVariations": [
{
"Id": -1, // Note: -1 is the default vanilla texture. It is not required, but it allows better control of when the vanilla texture appears
"ChanceWeight": 0.9
},
{
"Id": 0,
"ChanceWeight": 0.1,
"Keywords": [ "This is not shared with top-level", "This is not shared with other variations" ]
},
{
"Id": 1,
"ChanceWeight": 0.5
}
]
}The Animation property allows for custom animation of Craftable and Furniture objects. Each Frame should be an adjacent to the sprite within the texture image file.
The Frame field refers to the "column" to use in the texture, with 0 being the leftmost sprite.
The Duration field takes a value in milliseconds, which determines how long that particular frame lasts before moving on.
Example Animation usage:
{
"ItemName": "Tree of the Winter Star",
"Type": "Furniture",
"TextureWidth": 16,
"TextureHeight": 32,
"Variations": 1,
"Animation": [
{
"Frame": 0,
"Duration": 1000
},
{
"Frame": 1,
"Duration": 1000
},
{
"Frame": 2,
"Duration": 1000
}
]
}The associated texture.png for the above texture.json:

Manual variations are also capable of utilizing the Animation property, so each variation can have its own animation (or not at all).
Example ManualVariations Animation usage:
{
"ItemName": "Recycling Machine",
"Type": "Craftable",
"TextureWidth": 16,
"TextureHeight": 32,
"ManualVariations": [
{
"Id": 0,
"Animation": [
{
"Frame": 0,
"Duration": 500
},
{
"Frame": 1,
"Duration": 1500
},
{
"Frame": 2,
"Duration": 1500
},
{
"Frame": 3,
"Duration": 1500
}
]
},
{
"Id": 1,
"Keywords": [ "Blue" ],
"Animation": [
{
"Frame": 0,
"Duration": 500
},
{
"Frame": 1,
"Duration": 1500
},
{
"Frame": 2,
"Duration": 500
},
{
"Frame": 3,
"Duration": 1000
}
]
}
]
}The associated texture_0.png and texture_1.png for the above texture.json:


Frames can be filtered to only play when certain conditions are true.
The full list of FrameTypes are as follows:
| Property | Description |
|---|---|
Default |
Always plays |
MachineIdle |
Plays when the machine is idle (i.e. when the machine is not processing items). Only applicable to machines. |
MachineActive |
Plays when the machine is active (i.e. when the machine is processing items). Only applicable to machines. |
{
"ItemName": "Cask",
"Type": "Craftable",
"TextureWidth": 16,
"TextureHeight": 32,
"ManualVariations": [
{
"Id": 0,
"Animation": [
{
"Frame": 0,
"Duration": 500,
"Type": "Default"
},
{
"Frame": 1,
"Duration": 500,
"Type": "MachineActive"
},
{
"Frame": 2,
"Duration": 500,
"Type": "MachineActive"
},
{
"Frame": 3,
"Duration": 500,
"Type": "MachineActive"
},
{
"Frame": 4,
"Duration": 500,
"Type": "MachineIdle"
},
{
"Frame": 5,
"Duration": 500,
"Type": "MachineIdle"
}
]
}
]
}
The associated texture.png for the above texture.json:

Some objects are not supported for animations, which are listed below:
- Torch
The optional Tints property is used by the framework to determine which overlay to apply to manual variations. It accepts a list of int[] values, which the framework will pick from randomly.
Note: Tints is only usable for ManualVariations and only supports the following Type textures:
Crop
Example Tints usage:
{
"ItemName": "Poppy Seeds",
"Type": "Crop",
"TextureWidth": 112,
"TextureHeight": 32,
"Variations": 5,
"ManualVariations": [
{
"Id": -1, // Note: -1 is the default vanilla texture. It is not required to give it, though allows user to
"ChanceWeight": 0.9
},
{
"Id": 0,
"Tints": [
[ 255, 255, 255, 255 ] // Use this color (white) to have the game skip applying a tint to the flower
],
"ChanceWeight": 0.1
},
{
"Id": 1,
"Tints": [
[ 100, 125, 255, 255 ]
],
"ChanceWeight": 0.5
},
{
"Id": 2,
"ChanceWeight": 0.5
},
{
"Id": 3,
"ChanceWeight": 0.5
},
{
"Id": 4,
"ChanceWeight": 0.5
}
]
}The CollectiveNames or CollectiveIds property can be used in place of ItemName and ItemId respectively to allow textures to be usable across multiple objects.
Note: Items listed in CollectiveNames and CollectiveIds should be of the same size to avoid any display issues.
Example CollectiveNames usage, which makes a texture available to all vanilla chairs:
{
"CollectiveNames": [
"Oak Chair",
"Walnut Chair",
"Birch Chair",
"Mahogany Chair",
"Red Diner Chair",
"Blue Diner Chair",
"Breakfast Chair",
"Pink Office Chair",
"Purple Office Chair",
"Green Office Stool",
"Orange Office Stool",
"Dark Throne",
"Dining Chair",
"Green Plush Seat",
"Pink Plush Seat",
"Winter Chair",
"Groovy Chair",
"Cute Chair",
"Stump Chair",
"Metal Chair",
"Green Stool",
"Blue Stool",
"King Chair",
"Crystal Chair"
],
"Type": "Furniture",
"TextureWidth": 48,
"TextureHeight": 64,
"Variations": 2
}If you're looking for examples, see the examples page.
If you'd like to utilize Content Patcher to modify the texture.png based on conditions, see Content Patcher integration.
{ "ItemName": "Sunflower Seeds", "Type": "Crop", "TextureWidth": 96, "TextureHeight": 32, "Variations": 2 }