03. Visiting Villagers – Trade Configuration Guide (JSON)
This page details the structure of the Visiting Villagers trade JSON files, explaining the syntax of fixed items, dynamic families (family), random lists (one_of), special types, and the reload system without restarting the game.
📂 File Location and Structure
The visitor trade catalogs are stored in the folder: config/visitingvillagers/trades/
- 23 Default Files: On first startup, the mod copies 23 default
.jsonfiles (one for each adult visitor and wanderer variant) into this folder. - Edition Preservation: The mod never overwrites an existing file in the
config/folder. To restore a variant’s default, simply delete its corresponding.jsonfile and restart the game.
✅ Valid Variant Keys (file names)
The file name (without .json) must match one of the 23 keys known to the mod. Files with names outside this list are discarded on load (the mod falls back without applying the catalog):
| Adult Visitors | Wanderers |
|---|---|
miner | wandering_plains |
beekeeper | wandering_forest |
lumberjack | wandering_cave |
good_pillager | wandering_mountain |
glassworker | wandering_snow |
railwright | wandering_swamp |
relic_scavenger | wandering_desert |
piglin_trader | wandering_master |
beachcomber | |
enchant_smith | |
redstone_engineer | |
pyrotechnic | |
mycologist | |
hunter | |
default (profession-less variant) |
📄 Internal JSON Structure
Each .json file represents a variant and is divided into two independent pools: buys (NPC purchases) and sells (NPC sales).
{
"variant": "miner",
"buys": {
"select": 3,
"trades": [
{
"cost": { "id": "minecraft:dandelion", "count": 12 },
"result": { "id": "minecraft:emerald", "count": 1 },
"max_uses": 8,
"xp": 2,
"price_multiplier": 0.05
}
]
},
"sells": {
"select": 3,
"trades": [
{
"cost": { "id": "minecraft:emerald", "count": 10 },
"result": { "id": "minecraft:diamond", "count": 1 }
}
]
}
}📋 Main Fields
| Field | Required | Description |
|---|---|---|
variant | No | Variant ID. If omitted, the mod uses the file name itself (without .json). |
type | No | Defines a special type with a random result (in place of result). |
buys / sells | No | Independent offer pools whose directions are defined by cost / result. |
select | No | Number of offers rolled per visit (0 disables; omitted uses the entity’s default). |
cost | Yes* | Item required by the visitor and delivered by the player. |
cost_b | No | Second cost item for trades that require two items. |
result | Yes* | Item delivered by the visitor to the player. |
max_uses | No | Usage limit before the offer runs out (Default: 4). |
xp | No | Experience granted to the player on the vanilla scale (Default: 2). |
price_multiplier | No | Price change multiplier (Default: 0.05). |
*Note: For special types (type), the type field replaces result.
📦 Item Formats in Offers (cost, cost_b and result)
A) Fixed Item (id)
Defines a specific item with an exact quantity (from 1 to 99) with support for native 1.21.1 Data Components:
{
"id": "minecraft:diamond_sword",
"count": 1,
"components": {
"minecraft:custom_name": "Ancient Relic",
"minecraft:damage": 120
}
}- Costs with Components: In buy offers (
cost), the player must deliver exactly the item with the specified components (same name, enchantment, or damage).
B) Dynamic Families (family)
Instead of listing dozens of items individually, the family selector rolls one concrete item from the family per offer at each restock:
{ "family": "log", "count": 16 }
{ "family": "wool", "colors": ["white", "black"], "count": 16 }
{ "family": "sapling", "variant": "cherry", "count": 1 }- No Filter: The mod uses the automatic default list (e.g.: the 16 colors for
wool/dye/stained_glass, registered wood types forlog/planks, 7 species forsapling, or it scans the registry forpottery_sherdandarmor_trim_smithing_template). - With Filter: Allows restricting the roll using
color/colors(color families) orvariant/variants(wood/species families).
How the mod validates a family (all possible families)
There is no fixed list of family names — validation is dynamic against the game’s item registry using the naming pattern minecraft:<prefix>_<family>:
- Color families: the family is valid if
minecraft:<color>_<family>exists for all 16 dye colors (e.g.:wool,carpet,bed,banner,terracotta,stained_glass,candle,shulker_box,dye,concrete_powderetc.). - Wood/species families: valid if
minecraft:<type>_<family>exists for the requested types — the 11 vanilla wood sets (oak, spruce, birch, jungle, acacia, dark_oak, mangrove, cherry, bamboo, crimson, warped) or the 7saplingspecies (oak, spruce, birch, jungle, acacia, dark_oak, cherry). - Other groups (
pottery_sherd,armor_trim_smithing_template): resolved by scanning all registered items ending with_<family>.
💡 Tip: if a family name does not follow the naming pattern, use the
one_ofselector with full IDs — that is the recommended escape hatch. A missing item in a family (missingColor/missingVariant) causes a validation error in the log.
C) Random Selection Without Suffix (one_of)
For item groups that do not share a common name suffix (such as foods, flowers or seeds), define a list of full IDs:
{
"cost": {
"one_of": [
"minecraft:dandelion",
"minecraft:poppy",
"minecraft:blue_orchid",
"minecraft:lily_of_the_valley"
],
"count": 12
},
"result": { "id": "minecraft:emerald", "count": 1 }
}- Rolls a single item from the list per generated offer and supports items from other mods registered at runtime.
🎲 Special Types (Results Generated on Sale)
Four original types roll the resulting item at the exact moment of the transaction. For these types, the type field replaces result and the cost must be in emeralds:
type | Result Description |
|---|---|
random_enchanted_book | Book with random enchantment and level (price calculated like vanilla). |
random_suspicious_stew | Suspicious stew with a random beneficial effect. |
random_firework_star | Firework star with random shape, color, and effects. |
random_rocket | Firework rocket with random duration, shape, and effects. |
{
"type": "random_enchanted_book",
"cost": { "id": "minecraft:emerald", "count": 5 },
"max_uses": 12,
"xp": 15
}🔄 Real-Time Trade Reload
To apply changes to the JSON files without restarting the server or the game:
- Edit or create the
.jsonfiles in theconfig/visitingvillagers/trades/folder. - In the in-game chat, run the administrator command (permission level 2):
/visitors reloadtrades
- Effect: The mod reloads the files, validates the syntax, and clears the offer cache of loaded visitors that are not in an open trading session. New offers will be generated on the next interaction with the NPC.
🛡️ Early Validation and Fallback System
All JSON file validation is performed during server loading (ServerStartingEvent):
- Rigorous Checking: The loader (
TradeJsonLoader) validates whether IDs exist in the game registry, whether the quantity (count) is within the allowed range (1–99), whether the color/variant filters are valid, and blocks property conflicts (e.g.: definingidandfamilyin the same object). - Crash Protection (Fallback): If any JSON file contains a syntax error or invalid ID, the mod prints a clear log message (
WARNING) indicating the error and performs an automatic reversal (fallback) to the original file embedded in the.jar, ensuring the server keeps running safely.
