Addons
Addons are separate data packs that add cards, recipes, food, gear, machines, and raiders to Packs & Pillagers. Don't edit the main pack. Add to its storage from the load hook instead.
The example addon shows most of this working: a Golden Carrot, a Sift, raw metals, and a Crushing Press machine. Download the example addon and its resource pack.
Load Hook
Packs & Pillagers rebuilds all its data every time it loads, so anything added from minecraft:load gets wiped. Use #pnp:load instead. It runs right after the pack finishes loading.
In data/pnp/tags/function/load.json:
{
"values": ["yourpack:register"]
}
Cards
Write the card into pnp:cards defs.<id>, then call add_card:
data modify storage pnp:cards defs.golden_carrot set value {id:"golden_carrot",name:"Golden Carrot",kind:"food",food:6,meal:6,heal:4,sell:12,give:"minecraft:golden_carrot",gn:1,desc:"Food: 6. A carrot dipped in gold.",l1:"Food: 6. A carrot",l2:"dipped in gold.",atlas:"minecraft:items",sprite:"item/golden_carrot"}
function pnp:api/add_card {id:"golden_carrot",category:"c2"}
add_card fills in anything you leave out and adds the card to the Cardopedia, plus supper if it's food. Only id, name, and kind are required. The rest:
desc: the Cardopedia descriptionl1tol4: tooltip lines, about 22 characters eachhp,atk: health and attacksell: sell price in quarter emeralds, so 4 is 1 emeraldheal: health it gives a hurt villagergive,gn: the vanilla item and count it turns into when exportedsprite,atlas: the icon next to its name (atlasdefaults tominecraft:items)food,meal,eat_order: see Food belowtraits,cooldown,eq,loot: see Fighters below
Kinds: res, food (eaten at supper), unit (fights for you), enemy (monster), animal (wanders around), struct, node (renewable source), tool, weapon, armor, and trinket. The other kinds are for built-in cards.
Categories: c1 Resources, c2 Food, c3 Nature, c4 Buildings, c5 People, c6 Gear, c7 Monsters, c8 Ideas, and c9 Adventure.
Card ids are shared between addons, so give generic ones a prefix. You can change built-in cards the same way, like data modify storage pnp:cards defs.bread.food set value 6. For a custom Cardopedia tooltip, set pnp:pedia2 tip.<id> after calling add_card.
Card Text and Translations
Card text can be translated. Put these keys in a lang file in your resource pack, in any namespace folder, like assets/yourpack/lang/en_us.json:
pnp.card.<id>.name,pnp.card.<id>.type, andpnp.card.<id>.descpnp.card.<id>.line1topnp.card.<id>.line4for the tooltip
The text in your defs shows whenever a key is missing. For your own messages, use {translate:"yourpack.key",fallback:"Text"} so they can be translated too. The example addon comes with English and Spanish.
Art
Two files in a resource pack. First assets/pnp/items/card/golden_carrot.json:
{
"model": {
"type": "minecraft:model",
"model": "pnp:card/golden_carrot"
}
}
Then assets/pnp/models/card/golden_carrot.json:
{
"parent": "pnp:card/template_food_item",
"textures": {
"art": "minecraft:item/golden_carrot"
}
}
The parent is the card frame: pnp:card/template_<kind>_item, or template_<kind>_block for block art. art can be any texture.
Recipes
data modify storage pnp:cards recipes append value {r:1001,in:{villager:1,carrot:1,gold_ingot:1},n:3,time:80,use:["carrot","gold_ingot"],out:["golden_carrot"],il:[{c:"villager",n:1},{c:"carrot",n:1},{c:"gold_ingot",n:1}]}
data modify storage pnp:cards free.r1001 set value 1b
r: the recipe number. Packs & Pillagers uses numbers under 1000, so pick your own range above that, like 1000 to 1099.in: the cards needed.nis the total, and the stack has to match it exactly. Recipes don't need a villager: the example smelts Raw Iron with just a Furnace and Coal.time: in tenths of a second, so 80 is 8 seconds.use: cards that get used up, once per copy. Anything not listed stays.out: the cards it makes, or"@name"for a random pick frompnp:cards pools.<name>.il: the same cards asin, written as a list. It's used for hints.
free.r<number> makes the recipe known from the start. You can add it to an idea's r list instead (pnp:cards ideas.<idea>.r), but anyone who already learned that idea won't get it.
Pools look like {t:10,e:[{c:"carrot",w:6},{c:"potato",w:4}]}, where t is the total weight. An entry with c:"nothing" gives nothing, for a chance of coming up empty.
Food
Use kind:"food" with:
food: the points it's worth. Villagers eat 2, and babies eat 1.meal: how much of it counts as cooked. Villagers get Well Fed when at least half of what they ate was cooked. Use the same number asfoodfor cooked food, and 0 for raw.eat_order: optional. The lowest gets eaten first. It defaults tofood.
Barrels holding it count automatically.
Smelting
data modify storage pnp:cards smelt.raw_iron set value "iron_ingot"
A linked Furnace then smelts that card on its own. Add a Furnace recipe as well so it can be smelted by hand.
Fighters
Use kind:"enemy" or kind:"unit" with hp and atk, plus any of these:
traits: any ofranged,beam,knock,fast,undead(burns in daylight), andboss, like{ranged:1b,undead:1b}cooldown: ticks between special attackseq: starting gear, withtfor a weapon or tool,afor armor, andsfor special, like{t:"bow"}loot: cards it drops, like["bone"]
Gear
Make a card equippable with pnp:cards slot.<id>: "t" for the weapon or tool slot, "a" for armor, or "s" for the talisman slot. Then say what it does in pnp:cards gear.<id>:
data modify storage pnp:cards slot.copper_sword set value "t"
data modify storage pnp:cards gear.copper_sword set value {atk:2,role:"swordsman"}
data modify storage pnp:cards slot.sling set value "t"
data modify storage pnp:cards gear.sling set value {atk:1,role:"archer",ranged:1b,cd:18}
data modify storage pnp:cards slot.lucky_clover set value "s"
data modify storage pnp:cards gear.lucky_clover set value {talisman:"rabbit_foot"}
atk,hp: attack and health it addsrole: the job it gives, the same jobs the built-in tools give:swordsman,miner,lumberjack,farmer,shepherd,fisher,smith,cleric,scholar,explorer,builder,archer,guard,brute, orlancertalisman: works like a built-in talisman:totem,clock,compass,rabbit_foot,bone,prismarine_shard,echo_shard, orpumpkinranged:1b: attacks from the back row, like a Bowpierce:1b: hits a second enemy, like a Crossbowreach:1b: hits from further away, like a Spearguard:1b: draws attacks and blocks some, like a Shieldmace:1b: hits everything around the target, like a Macecd: ticks between attacks. The default is 20, a Bow is 16, and a Mace is 30.
Machines
There are two ways to add a machine. The quick one makes your card work exactly like a built-in machine, ports and all:
data modify storage pnp:cards machine.big_barrel set value "barrel"
That works with barrel, copper_barrel, hopper, dropper, furnace, sell_box, bundle, oak_tree, rock, berry_bush, forest, mountain, cave, farm, chicken, cow, sheep, and pig.
For a machine that does something new, describe it in pnp:cards machines.<id> and write its functions yourself:
data modify storage pnp:cards machines.crushing_press set value {in:1,out:1,storage:16,accepts:["cobblestone","iron_ore","gold_ore","copper_ore"],on_tick:"pnp_example:press/tick",on_use:"pnp_example:press/use"}
in,out: how many input and output ports it gets, from 1 to 4. Both default to 1.storage: how many cards can wait inside. The default is 64.accepts: the cards it takes. Leave it out to take anything.on_input: a function that runs when a card goes in, dropped or pipedon_tick: a function that runs once a secondon_use: a function that runs when a player right-clicks it
Players can drop cards on it or pipe them in with the Wrench, and its label shows what's waiting. Your functions run as the machine card, at its position, and can use these:
pnp:api/machine/take: takes the next waiting card and puts its id inpnp:machine io.c. It fails if nothing is waiting.pnp:api/machine/emit {c:"<id>"}: sends a card out of the output port, or drops it beside the machine if nothing is linked.pnp:api/machine/store {c:"<id>"}: adds a card to the ones waiting.pnp:api/machine/count: returns how many cards are waiting.pnp:api/machine/progress {p:<0 to 100>}: shows a progress bar under the card. 0 hides it.
The Crushing Press starts a job like this, then finishes it 4 ticks later:
execute unless function pnp:api/machine/take run return 0
data modify entity @s item.components."minecraft:custom_data".pj set value {t:0}
data modify entity @s item.components."minecraft:custom_data".pj.c set from storage pnp:machine io.c
function pnp:api/machine/progress {p:1}
Raids
data modify storage pnp:cards raiders append value {c:"husk",from:3,n:2}
Every raid from raid from to raid to brings n more of that enemy, on top of the usual raiders. from defaults to 1, to to forever, and n to 1. Any enemy card works, including your own.
PvP Stealing
pnp:cards steal lists the cards invaders go for, in order. Each invader that survives takes the first card on the list it can find on the table it raided. Use prepend to put yours first, or append to put it last:
data modify storage pnp:cards steal prepend value "golden_carrot"
The built-in list starts with Emerald Blocks, Diamonds, and Emeralds, and ends with Oak Logs and Cobblestone.
Need Something Else?
If your addon needs a hook that isn't here, open an issue on GitHub.