Gameplay / villagers

Villagers & transfer papers

Two people who trade in horses, and the item that lets a horse be sold without either of them touching it. The cowboy lives in a barn on the edge of a plains village, never gets off their horse, and sells their herd as transfer papers; the horseman is an ordinary villager profession selling tack and gene goods from a workstation. This page is the source of truth for all three. The items themselves are listed on Items & recipes; the genetics of the horses the cowboy breeds are ordinary breed founders.

Not verified in game

Everything on this page compiles, registers, and boots a dedicated server clean. None of it has been seen in a world. The checklist is verification §0-AC.

Transfer papers

A horse changes hands by paper, not by proximity. There are two items and three moments.

A signed paper is drawn as the horse it names — the mod's HD horse mesh in that horse's own coat, shrunk into an item slot (client/TransferDeedRenderer), in the merchant window and everywhere else the item appears. That is what makes a bearer instrument usable: the paper is a claim you have to walk out and collect, and six papers that differ only by a name in a tooltip are six papers you cannot tell apart from the animals they name. The deed carries the horse's genetic and epigenome codes for it, so the picture needs neither the horse loaded nor the server asked, and survives the horse being sold on or shot.

MomentWhat happensWhere
Crafted Eight paper around one horse hair makes one blank transfer paper, and the bench stamps the crafter's name and UUID onto it. TransferPaperHandler.onCrafted
Signed The bound player right-clicks a horse they currently own; the blank becomes a signed paper naming that horse. TransferPaperHandler.sign
Redeemed Whoever is holding the signed paper right-clicks the horse it names. The horse becomes theirs; the paper is spent. TransferPaperHandler.redeem

Why redemption is a walk, not a click

A signed paper is a bearer instrument. It carries no binding at all — the binding is on the blank, so that only someone with the standing to write a paper can write one — and redeeming it does not require being the person who signed it, or the person who bought it. Buying one from the cowboy moves nothing: the horse is still standing in their paddock, and you have to go out and find it.

That is the whole reason the item exists in this shape rather than as “pay the cowboy, receive a horse”. A claim the bearer has not collected yet is an object worth trading — it can be handed to another player, sold on at a markup, or lost in a creeper hole with the horse still standing there waiting for whoever picks it up.

What a transfer never changes

bredBy is untouched by every path in the system. A horse bred by Jesse Calloway is still bred by Jesse Calloway after four owners, and HorseRecord.attribution() — which prefers the breeder over the tamer — keeps saying so in the family tree. The signed paper carries a snapshot of the breeder purely so a buyer can read whose line the animal comes from; it is never written back.

tamedBy is only ever filled in when it is blank. It records who first got a rope on the animal, which also does not change when the animal is sold. In practice the only horses it gets written to are the cowboy's, because their stock has never been tamed by anyone.

The genome, the names, the pedigree, the generation and the breed label are not touched either. Ownership is the only thing that moves.


The cowboy

A horse breeder who is generated with a barn on the outskirts of a plains village, and who is always on a horse. Their name is drawn from frontier given and family name tables (PersonNameGenerator.cowboys()), and that name is what the game says when it says who bred one of their horses.

Why they are not a villager profession

They are a custom AbstractVillager, not a VillagerProfession. A profession is acquired from a job site by a villager whose brain runs vanilla's daily schedule, and that schedule would dismount them every morning to go and stand at a workstation. Everything that makes this character themselves — always mounted, home is a barn and not a bed, stock is a live herd and not a trade table — is a fight with that brain. Extending AbstractVillager keeps the parts that are worth keeping (the merchant screen, the villager silhouette, the trading goals) and none of the schedule.

The horseman is a real profession, for the opposite reason: a shopkeeper who walks to a workstation, restocks, gossips and goes to bed is exactly what that brain is for.

Where they set up

The structure places them bare in the middle of the barn and CowboyHandler builds them on their first server tick. Their home is that spot — the block their routine rides back to and the centre of the box the door code works on — but they do not found there. The barn's interior is eleven blocks by five with walls on every side and a horse is nearly a block and a half wide, so a string of them made around the barn's centre came out with half its members standing in the walls.

So they walk out first, to a paddock 12–24 blocks off, and the herd is made around them there. The bearing is taken from the village bell to the barn and sampled in a half-plane around it, so “out of town” is literal: they set up on the grass past the last house rather than in somebody's turnip field. If that half-plane has no room in it the search widens to the whole circle rather than fall back to the barn.

A candidate has to be ground, and the surface heightmap is not enough to know that: in a village the highest solid block in a column is very often a roof, which is where the first cowboy to walk out ended up standing — on a house that was not even theirs. So a paddock must also sit within 3 blocks of the barn's own height and have 3 blocks of solid ground beneath it. Either test alone is fooled: the height test passes a low porch or a wall top, and the depth test passes the flat top of a hill fifteen blocks up. Together they mean “ground, at about the height the barn is at”, which is what a paddock is.

Every placement — their and every horse's, at founding and at every restock — now asks the level whether a horse-sized box fits, rather than whether a one-block column is clear. A clear column next to a wall still puts a horse's shoulders through it, which is exactly how the barn filled up with embedded horses.

Their herd

What they sell

One offer per herd horse. A horse costs one to three emeraldsHorsePrices.DEFAULT_PRICE, and what almost every horse in the game costs. They are the early-game purchase this mod is built around: you buy a horse before you have a farm, not after you have a trading hall.

Which breeds they can deal in at all is the breed's own source checklist: they draw from the breeds of the country round the barn that allow cowboy, and falls back to every breed that allows it when the local list is empty. So “no dealer has ever had one” is a thing a breed file can actually say, and it is a different claim from “none run wild here”.

A breed that should be dear names its own range in its file ("price": [min, max]); anything that does not gets the default. A range rather than a number, because two horses of a breed are not worth the same and a stall listing six papers at exactly two emeralds each reads as a vending machine — the roll inside the range is taken from the horse's own UUID, so it is stable across every look at the merchant screen. The default and the roll live in server/HorsePrices, deliberately on the Minecraft side and off common/, for the same reason RarityItems is: how much a horse costs in emeralds is a gameplay-economy decision. What a breed gets to say is only “mine are dear”.

This replaced a table priced off the breed's Commonness tier that ran from ten emeralds to forty, which made the cowboy a shop you walked past for a week. No breed sets a range yet, so every horse they sell is currently 1–3.

The offer list is rebuilt every time someone looks at them, because the herd is a live thing — a horse can be killed by a wolf between one customer and the next. A horse leaves the list for good the moment its paper is bought, whether or not that paper is ever redeemed. They are not a levelling villager: no XP, no tiers, no vanilla restock timer — what they do instead is breed replacements.

Restocking and rotation

CowboyHandler.restock looks over their string about once a minute (jittered, so two cowboys loaded on the same tick do not stay in lockstep) and does two slow things.

A horse is never retired with a player within 48 blocks of it — the rotation is meant to be something you notice by coming back to a different string, not something you watch happen; a horse vanishing in front of you reads as a bug however well it is documented. And “their string” here is exactly the set the merchant screen offers (alive, loaded, untamed, not their mount, not already papered), because “how many have they got?” and “how many can you buy?” have to be the same number or they restock to fill a shelf nobody can see. Tamed horses are dropped from the herd list entirely, so it cannot grow without bound over a long world.

Their day

They do not ride

They did, for about a day, and it cost more than every other part of this character put together. A mob rider cannot steer, so the itinerary had to live on the horse; the horse's own goals all exist for the “someone is on my back” case and fought it; a villager has no seated pose, so they had to be sunk into the saddle to stop looking like they were standing on it; and getting a mounted man and eleven horses through a barn door at dusk was never made to work at all. Five rounds of fixes, each exposing the next.

The herd follows the man now. They are an ordinary villager who walks, and CowboyHerdGoal points their horses at them instead of at a lead horse. That deleted CowboyMountGoal, CowboyRemountGoal, CowboyRoutine, CowboyDoors, HerdCollision, the saddle sink, the patrol, the shelter and the flee — roughly a thousand lines for a character nobody could tell had them. They keep ten times a villager's health (Cowboy.HEALTH), which is what the night cost in the end.

So there is no routine to document. They float, trades, panics, strolls and looks at players — the goals every villager has, plus one of their own below. Their horses trail them at 14 blocks and settle at 7 by day, tightening to 4 after dark so the string gathers on them rather than strung out across a field.

They can work a door, in daylight, with both hands

CowboyDoorGoal. Until it existed they could not open a door at all — not for want of trying, but because a mob needs two unrelated things to use one and they had neither. The goal is what swings it; the navigator's canOpenDoors is what makes the pathfinder score a shut wooden door as a way through rather than as wall. On its own, either is useless: no goal and they plan a route they cannot take, no flag and they never plan the route at all.

None of it is a routine — they open a door they have walked into, which is vanilla's own cheap trigger, and nothing sends them at one on purpose. What it buys is that the barn is now a building the outfit can actually get inside. Gap 63 is the part that is designed rather than measured.

They do not go indoors, and does not need to

They cannot. Walking into a house and getting into a bed lives in vanilla's villager brain, and a Cowboy is an AbstractVillager — the same base as a wandering trader, chosen precisely so that no schedule drags them away from their horses. A wandering trader does not go indoors either. Giving them somewhere to sleep is what the entire barn-shelter subsystem was, and it is written up in gap 55 as the thing that could not be made to work.

So the night is survived rather than avoided, on two numbers and no behaviour:

Enemy rather than Monster on purpose: it is the interface that means “this thing is hostile”, and it catches the few hostiles that are not Monster subclasses. Players are not covered and can still hit them. Their horses are not covered either — they are ordinary animals, a wolf getting one is a thing that happens, and that is what the restocking is for.

The barn, and how it lands on the outskirts

cowboy_barn.nbt is the whole homestead in one piece: a hand-built stable — hay-bedded floor, water cauldrons, two double doors at each end, the cowboy generated at its centre — with the house behind it along the street, and a walk running down the front of both.

The walk, and the course it lies in

Worth knowing before editing the bake, because it is the one thing about the piece's geometry that is not obvious from looking at it. Layer 0 of a building is not the ground — it is the course that rests on the ground. The street's road block is the layer below it, outside the piece entirely, which is why a plains house sits one block proud of the road with a step up into the doorway.

So a path laid in layer 0 is a block-high curb you walk over, which is what the lane between the two buildings was. The piece now carries a ground course beneath the foundation: everything lifts by one and the jigsaw lifts with it, so nothing about where the homestead lands changes, and the new bottom layer falls in the road's own course. The walk runs down it.

It has a column of its own, west of both buildings, because it has to be in front of the steps and there is nowhere else for it to go. One column further west is the street's own connector block; a piece whose box reaches over that overlaps the street piece and is thrown out by the placer, so the homestead would simply never generate. And it cannot run under the steps either: DirtPathBlock will not survive a solid block overhead and ticks back to plain dirt, so a walk beneath the stair skirt would be a walk made of dirt. In front of the steps, nothing is covered and nothing converts.

Terminators are the edge of the village

The barn is appended to minecraft:village/plains/terminators. A terminator is what the village generator places when a street connector has nowhere left to go: both village/plains/streets and village/plains/houses name it as their fallback. So the terminator slots are, by construction, the ends of the village — the last piece on a road that ran out of room. Putting the barn there is the closest the jigsaw system comes to expressing “on the outskirts” without hand-placing the building and owning terrain fitting ourselves.

The barn's own connector is a minecraft:street jigsaw on its west face, in the step in front of the north pair of doors. The generator rotates the whole piece so that connector faces back at whatever it attached to.

It sits at y=0 — the barn's own foundation course — and getting that wrong is what sank the building. A jigsaw pair lands its two blocks at the same world height, and the street connector it meets is at the street piece's y=1, one above the road block. So whichever local layer carries this jigsaw is the layer that ends up resting on the ground. It was y=1 at first, on the reasoning that vanilla terminators put theirs one above their ground block — which is true of terminators and the wrong piece to copy. The result was the foundation landing in the road's own layer: the stair skirt round both doorways was buried flush with the ground instead of stepping up onto it, and the barn read as half-dug-in.

Vanilla houses are the shape to copy. A plains house puts its building_entrance jigsaw in its own foundation layer, and so sits one block proud of the road with a step up into the doorway. At y=0 the barn does the same, and its steps are steps again.

The jigsaw block replaces one of those step blocks, so the bake reads whatever was drawn there out of the source and writes it back as the jigsaw's final_state — no hand-copied block state to go stale, and re-exporting the barn with something else in that spot just works.

It goes in at weight 3 against the four vanilla terminators of weight 1 each, so roughly three terminator slots in seven. That is not how often it appears. A village has a handful of terminator slots, and the piece is 15×15 where a terminator is 2×3 — so most of the draws that pick it then fail the bounding-box check and fall through to a small terminator instead. The weight is set high to compensate for exactly that: it was 1 while the piece was 15×7 and carried the barn alone, and taking the house in doubled the depth, and so doubled the ground it has to find. The effect aimed at is “most plains villages, where there was room”.

Why the pool is edited in code

A datapack can only replace terminators.json, never add to it. Replacing it would freeze today's four vanilla terminators into this mod and silently delete any other mod's additions to the same pool. BarnPoolInjector appends instead, on ServerAboutToStartEvent, which needs the live pool object's element lists — and that is what this repo's first access transformer is for.

The cowboy comes with the building

They are carried in the structure template's entities list, which is the same mechanism vanilla uses to put villagers in village/plains/villagers/*.nbt. A template can only place an entity, not roll one, so they arrive bare — nothing but their id — and CowboyHandler builds them on their first server tick: name, home, herd.

That founding runs on EntityTickEvent.Post and not on the join event, for exactly the reason HorseFoundingTickHandler documents at length: founding spawns horses, spawning a horse ends in an Attributes.SCALE write, and a scale write runs a collision scan that can force-load a chunk. Doing that from the join event or a server.execute task re-enters the chunk system's ticket pass and crashes it.

One cowboy per village

The jigsaw generator has no way to say “at most one of this element per structure”, so a village that rolls two barns gets two barns. The second one is just a barn: of the cowboys within 128 blocks of each other exactly one founds, and the rest discard themselves before spawning anything. The tie-break is the lowest UUID — the same rule HerdManager uses to elect a wild herd's lead, and for the same reason: every candidate has to reach the same answer without talking to the others.

Re-baking the piece

Two sources, one output. tools/barn/cowboy_barn.source.nbt is the raw structure-block save of the stable; tools/barn/cowboy_house.source.nbt is a byte copy of vanilla's village/plains/houses/plains_small_house_1. Both are kept only so the buildings can be edited in game and re-exported; the mod never reads either. After a re-export, run:

python neoforge-26.1.2/tools/barn/bake-barn.py

which adds everything a structure-block save cannot carry — the ground course, the jigsaw connector, the headroom over the doorways, the reshaped house, the walk along the front, the work posts and the villagers — and writes data/horsegenetics/structure/cowboy_barn.nbt. Commit all three.


The horseman

The roadmap's “Horse Master”: an ordinary villager profession that sells horse tack and horse-genetics goods from a Horse Trader's Post. Five tiers on vanilla's ladder — Novice, Apprentice, Journeyman, Expert, Master — not the design document's, which invented an “Adept” rung that does not exist.

Two posts, one texture

Cowboy Hitch and Horseman’s Table: the same block twice, on the same three-face texture set, with different names and different jobs. The hitch is 2 hair cloth + 3 braided rope + 2 fence; the table is 3 hair cloth + 2 leather + 2 fence. Both shapeless. Neither does anything yet beyond marking a spot — turning them into real workstations, a hitch you tie a horse to and a table you work leather at, is open work.

BlockHands outHow
Horseman’s Table the horseman An ordinary job site. It backs the horsegenetics:horsemans_table POI, which is added to vanilla’s acquirable_job_site and village tags — tags merge across datapacks, so adding to vanilla’s is safe where overriding a worldgen file would not be. One villager per table.
Cowboy Hitch the cowboy Not a job site at all. A cowboy is an entity, not a profession — they have a herd, a stock target and a merchant screen that sells papers rather than goods, none of which fits on a Villager — so there is nothing for a profession to point at and no POI to claim. server/CowboyHitchHandler looks for the block instead: every two seconds, an unemployed villager within 6 blocks of a hitch that has no cowboy within 32 is taken on.
Why two blocks and not one

One block tried to do both, handing out a cowboy first and a horseman second by alternating. It could not. Converting the villager meant either discarding them — which silently holds their job-site ticket for ever, because Villager.releaseAllPois is private and runs on death, so the post produced one cowboy and then nothing while the rest of the village stood unemployed — or demoting them and trusting vanilla to re-assign them, which is two more moving parts than a second block.

A post each is far less clever and simply works. The hitch makes cowboys, the table makes horsemen, and neither has to know the other exists. Discarding the villager is safe at the hitch for exactly the reason it was not safe at the shared post: they never claimed the hitch, because the hitch is not a job site.

One cowboy per hitch, guarded by looking rather than remembering: a hitch with a cowboy already within 32 blocks is spoken for. That is self-correcting — kill them and the next villager past the hitch takes over — where a “used” flag on the block would need saving and would go stale the moment they died.

Both of them stand at the house

They flank the house's front step, one either side of it, with a villager on the walk in front of each. A villager takes the post they are standing on — one becomes the horseman, the other the cowboy.

They were on the barn, and moving them is what fixed the house. Not a question of where they look right: the house has to exist before either post does, and while the house was built at runtime by the cowboy, the posts had to be somewhere the cowboy already was. That ordering is what finally sank the runtime house — the posts are what make a cowboy, so a cowboy cannot be what builds the thing the posts stand on. With both buildings in one baked piece there is no order left to get wrong, and the posts can go where they belong: on the doorstep of the house whose family works them.

Baked into the structure rather than placed at runtime, because a job-site POI is indexed off the block — putting the block in the world is the whole mechanism — and because a shop front is architecture. Neither villager is given a profession: letting them take the jobs the ordinary way is the only test there is of the part that has ever been in doubt, which is whether the POI registered and whether the tag merged. Two nitwits standing there for ever is a real answer to a real question.

One family per village

Whoever is hired first names the family, and everyone after joins it. Both handlers ask the same question — HorsemanHandler.familySurname — which looks round the village for a cowboy or a horseman who already has a surname and takes their; finding nobody, it coins a new one. So a village reads as one outfit in the horse trade: Wade Hargreave at the hitch, Frank Hargreave behind the table.

Order-independent on purpose. The hitch and the table hand out their jobs entirely separately, and which villager gets round to which first is down to where they happen to be standing — so neither role can be the one that owns the name. An earlier version had the cowboy coin it and the horseman inherit, which is fine right up until the horseman is hired first and there is nobody to inherit from.

The nearest namesake wins, which only matters in a village with two outfits in it: a second hitch across town founds the Adamses, and a table put up beside it joins the Adamses rather than the Hargreaves at the far end. It counts the two roles this mod names and nothing else — a player who renames their own farmer “Bob” has not founded a horse family.

The horseman keeps vanilla's brain, and gets a house

Nothing in this mod touches how the horseman behaves. They are a completely ordinary villager with a profession, so going indoors at night, panicking in a raid, hiding from a zombie, restocking and gossiping are all free — that is the whole reason they are a profession where the cowboy is not.

What that brain needs is a bed POI to claim, and a barn on the outskirts can easily be out of range of the nearest house's. Beds went into the barn first and came straight back out: the barn is a building made of doors. Four double doors and a two-block gap at either end, and a villager only ever shuts the one they walked through — so a bed in there is a bed in a corridor with three doors standing open.

So they get a house, and it is part of the same structure piece as the barn. It is a copy of vanilla's plains_small_house_1, copied rather than referenced because it needs changing and because a vanilla template is not ours to rely on keeping its shape. tools/barn/bake-barn.py reshapes it:

It is set down beside the barn with a lane of dirt_path between them, the same block the village's own streets are made of, running along the front of both and up to each door. Two buildings on the edge of a village with nothing between them read as two things that happen to be near each other.

It used to be built at runtime and it never once appeared. CowboyHouseBuilder hunted the far side of the barn for a patch that was flat, clear and untouched — every column of the footprint agreeing on its surface height — on the reasoning that no house is a great deal better than a house dropped through somebody's roof. In a real village that test never passed once. Baking the house into the piece answers the same worry better than the test did: the jigsaw generator's own bounding-box check is a far more careful version of “is there room here”, and it runs before anything is placed at all. The price is a piece twice as deep, paid for in pool weight.

The cowboy will not use a bed — an AbstractVillager has no schedule at all — which is why they get ten times the health and hostile mobs that ignore them instead.

The trade table

TierBuysSells
1 Novice16 horse hairHair bundle, saddle, leads
2 Apprentice8 hair bundlesBasic whistle, blank tickets, iron horse armour
3 Journeyman4 braided ropeThe four general breeding carrots, a common breed spawn egg (22 em)
4 Expert2 hair clothA random common gene carrot, a random uncommon one, a random common/uncommon research paper, an uncommon breed egg (38 em)
5 Master1 stallion seed jarA random rare gene carrot, a random epic one, a random rare/epic paper, diamond horse armour, a rare breed egg (58 em, one use)

Each tier draws three of its pool, so two horsemen in different villages are not the same shop. Hair buying is the early-game emerald tap and therefore the number most likely to want retuning; it is one JSON file per trade.

A random carrot, without a custom listing

Villager trades are datapack registries in 26.1.2 (minecraft:villager_trade and minecraft:trade_set), and a trade's given_item_modifiers are loot functions that run when the offer is generated. That is exactly the semantics the roadmap argued for: “a random rare carrot” is rolled once per restock and then sits in the window at a fixed price, rather than re-rolling under the player's cursor. So the whole “custom listing that rolls when the offer is generated” requirement is met by a stock vanilla mechanism plus one loot function:

{ "function": "horsegenetics:set_random_gene",
  "target": "carrot",          // or "paper"
  "min_rarity": "uncommon",
  "max_rarity": "uncommon" }

The pool is computed, not listed: a gene is a candidate if it is registered, has a gene carrot, and its GeneRarity falls inside the window. A third-party gene therefore joins automatically, and legendary and mythic are never sold because no window reaches them — a comparison rather than a blacklist that can go stale. Within a window, draws are weighted by GeneRarity.lootWeight(), the same weighting the chest-loot papers use, so the price ladder and the find-it-in-the-wild ladder agree.

An empty window returns an empty stack, which VillagerTrade.getOffer reads as “no offer” and drops — so a rarity tier with no genes in it costs a trade slot rather than putting a blank item on sale.

Breed spawn eggs are the same trick with a second function, horsegenetics:set_random_breed, which takes a commonness window instead of a rarity one:

{ "function": "horsegenetics:set_random_breed",
  "commonest": "rare",
  "rarest": "very_rare" }

The membership test is the breed's own source checklist — a breed is a candidate if it allows spawn_egg — so a breed a player drops into .minecraft/phc/breeds/ joins the horseman's stock by being registered, and one that opts out disappears from it, with nothing edited either way. Within a window, draws are weighted by the breed's own spawnWeight. Two functions rather than one parameterised thing, for the reason there are two loot modifiers: a paper is knowledge and an egg is an animal, and a datapack ought to be able to retune one without the other.

What the roadmap asked for and this does not do