03 – Trade Configuration Guide (JSON)
Visitor trades live in the config/visitingvillagers/trades/ folder — each .json file represents one NPC variant. The folder and the 23 default files are copied by the mod on first launch; from then on, they’re all yours.
Overwrites: the mod never overwrites a file you already have in the config folder. To go back to the default of a variant, delete that variant’s file and restart the game: the mod recreates the bundled JSON automatically.
1. File Structure
The whole file is an object with the variant id and two independent pools — buys (what the NPC buys from the player) and sells (what the NPC sells) — each with a select and the trades list:
{
"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 }
}
]
}
}
| Field | Required | Description |
|---|---|---|
variant | no | Variant id; if omitted, the mod uses the file name (without .json) |
type | no | Special type with a random result (section 5); when present, result is not used |
buys / sells | no | Two independent pools; the trade direction comes from each offer’s cost/result |
select | no | How many offers are shuffled from the pool per visit; 0 disables the pool and -1 is the same as omitting |
cost | yes* | Item the player hands over |
cost_b | no | Second cost item (two-item trades) |
result | yes* | Item the visitor hands over |
max_uses | no | Uses before the offer runs out (default 4) |
xp | no | Trade XP, on the vanilla scale (default 2) |
price_multiplier | no | Offer price multiplier (default 0.05) |
* Required in normal trades; in the special types (section 5), type takes the place of result in the entry.
Default amounts when select is omitted
| Entity | Variant | buys | sells |
|---|---|---|---|
| Adult visitor | default | 3 | 3 |
| Adult visitor | default | 3 | 2 |
| Adult visitor | piglin_trader | 5 | 4 |
| Wanderer | default | 4 | 4 |
| Wanderer | wandering_master | 6 | 6 |
2. Item Types in Offers (cost, cost_b and result)
A) Fixed item (id)
A specific item, with an exact amount:
{ "id": "minecraft:emerald", "count": 5 }
countaccepts 1 to 99, defaulting to 1 (limit of the vanilla codec).componentsis optional and accepts any vanilla data component (enchantments, name, damage…) — see examples in the Examples Guide.- In costs, the component is part of the charge: the player must deliver exactly that item (same damage, same name, same enchantment).
B) Full family (family)
The mod shuffles one concrete item from the family per offer (reshuffled at every restock/reload), so a single entry covers the whole group instead of one entry per item:
{ "family": "log", "count": 16 }
- Without a filter, the family default is automatic, in this order: the 16 colors (
wool,banner,terracotta…), the wood types with a registered item (log= 8,planks= 11), the 7saplingtypes, or — for families with no color/type suffix — every registeredminecraft:*_<family>item (e.g., 23 pottery sherds, 18 smithing template trims on 1.21.1). - With a filter, restrict via
color/colors(color families) orvariant/variants(wood/species families). The two sets are mutually exclusive.
{ "family": "wool", "colors": ["white", "black"], "count": 16 }
{ "family": "log", "variants": ["oak", "spruce", "birch"], "count": 16 }
{ "family": "stained_glass", "color": "red", "count": 8 }
- No family needs a whitelist: any suffix that forms valid ids works (
dye,carpet,bed,candle,leaves,shulker_box…). - In buy trades, the player delivers the item shown on the offer (the vanilla 1.21.1 cost doesn’t accept tags) — no “any color works”.
C) one_of (list of full ids)
For groups that don’t share a name suffix (foods, flowers, seeds…), list the full ids and the mod shuffles one of them per offer — it also works with items from other mods, as long as the id is registered in the modpack:
{ "one_of": ["minecraft:dandelion", "minecraft:poppy",
"minecraft:blue_orchid", "minecraft:lily_of_the_valley"],
"count": 12 }
- Each id is validated at parse time; an empty list or unknown id is an error (see below). Mutually exclusive with
id,family, and color/variant filters.
3. How the Mod Validates (and what happens when something goes wrong)
All validation happens at server boot, with the world’s registries active:
- An error in an entry (
idwithfamilytogether,countoutside 1–99, unknown color or variant, mixing color with variant,one_ofwith an unknown id or an empty list…) produces a log warning with the failing entry and id. - The game doesn’t crash: the variant with the problem simply falls back to the default JSON bundled in the jar.
- Variants without a file in the config folder also use the bundled JSON.
- Files are not re-validated in real time; rereads happen at boot or via
/visitors reloadtrades.
4. How to Apply Changes In Game
No need to restart the game: edit the JSON files in config/visitingvillagers/trades/ and run in the server chat:
/visitors reloadtrades
The mod rereads the folder and clears the already-shuffled offers of loaded visitors that aren’t in the middle of a trade; new offers are shuffled on the next interaction. The command requires operator level 2 (like /gamemode).
Keep in mind: files already copied to the config don’t follow mod updates — delete the variant’s file and restart to get the new version.
5. Special Types (random results)
Four original trades shuffle the result at sale time. In the files, they appear with type in place of result:
type | Result |
|---|---|
random_enchanted_book | Book with a random enchantment and level, priced like the vanilla one |
random_suspicious_stew | Suspicious stew with a random beneficial effect |
random_firework_star | Firework star with a random shape/color/effects |
random_rocket | Rocket with random duration, shape, color and effects; the price varies with the shuffle |
{ "type": "random_enchanted_book", "xp": 15 }
In all of them the cost must be emeralds — the cost’s count is the base price in emeralds — and max_uses/xp follow the same rules as the other types.
6. Variant Ids (file names)
One file per id, saved as config/visitingvillagers/trades/<id>.json:
- Adults (
VisitorEntity):miner,beekeeper,lumberjack,good_pillager,glassworker,railwright,relic_scavenger,piglin_trader,beachcomber,enchant_smith,redstone_engineer,pyrotechnic,mycologist,hunter,default. - Wanderers (
WanderingVisitorEntity):wandering_plains,wandering_forest,wandering_cave,wandering_mountain,wandering_snow,wandering_swamp,wandering_desert,wandering_master.
Accepted aliases: the enum’s internal name (e.g., texture3) and, for wanderers, the id with or without the wandering_ prefix. When in doubt, always use the names from the lists above.
📄 Practical examples with the filters: Examples Guide ⚙️ The other half of the config (spawn in TOML): Spawn Configuration Guide