v3.10.1 · released 12 days ago · MIT

Minecraft datapacks, generated from Python

A beet framework: declare an item once, and its models, recipes, loot tables, translations and in-game manual page are written on every build.

Get startedTry it in the browser
  • 2.6kPyPI downloads a month
  • 23public projects built with it
  • 51GitHub stars
definitions/additions/equipments.py
Block(
	id="life_crystal_block",
	vanilla_block=VanillaBlock(id="minecraft:glass"),
	manual_category="equipment",
	components={
		"item_name": {"text": "Life Crystal Block"},
		"lore": [{"text": "Break it to get the crystal back"}],
	},
	no_silk_touch_drop=NoSilkTouchDrop(id="life_crystal"),
	recipes=[CraftingShapelessRecipe(
		category="equipment", result_count=1,
		ingredients=8 * [Ingr("minecraft:glass")]
			+ [Ingr("life_crystal")],
	)],
)
build/
14 of 16 files
└
└
└
└silk touch, else the crystal
└the recipe, NBT-aware
└world gen
└
└
└its manual page
└
└
└
└
└
└
└translation keys

Placement, destruction, the Silk Touch branch, the recipe and its drawn crafting grid, world generation, models and textures. The manual page and the translation keys come with it.

Your datapack documents itself

Every item you define gets a manual page: its recipe drawn from the ingredients you declared, its description, and clickable navigation between categories. Players craft the book in game and it is already up to date.

  • Recipes rendered from your definitions, not screenshotted by hand
  • New item today, new manual page on the next build
  • Custom pages, hooks and button layouts when you need them

Your commands, checked in your editor

A command inside a Python string is still a command. The StewBeet extension for VS Code reads them as such, gives .bolt files their own language, and links every block to the function your build wrote from it.

  • Completion, hover and errors on the commands, as you type
  • Ctrl+click from a write_function call to the generated file, and back
  • The Bolt language, with computed paths still resolving

Maintain one definition, not eight files

One custom block written by hand is eight files across two packs in four formats. Miss one and nothing errors: the block just never drops. StewBeet rebuilds all eight from your definition on every compile, and does the same for everything below.

By hand

8files to keep in sync

  • function/place.mcfunctionplacement
  • function/destroy.mcfunctiondestruction
  • loot_table/block.jsondrops
  • recipe/block.jsonvanilla recipe
  • function/calls/crafter.mcfunctionNBT recipe
  • items/block.jsonitem definition
  • models/item/block.jsonmodel
  • lang/en_us.jsontranslation key

With StewBeet

1definition to maintain

definitions/blocks.py

The other eight are derived from it on every build, so they cannot drift apart.

A definition is a name, some values and a list of recipes. If you can read datapack JSON, you can read one.

Every item is givable, immediately

Each defined item gets a loot table, plus a _give_all function that hands you the entire pack in named chests for testing.

One material, the whole tier

Name an ingot and what it is equivalent to. Tools, armour, ore, blocks and nuggets are registered from the textures you dropped in, recipes included.

the whole tier from one entry

ORES_CONFIGS: dict[str, EquipmentsConfig | None] = {
    "solarium_ingot": EquipmentsConfig(
        # Solarium behaves like diamond,
        equivalent_to=DefaultOre.DIAMOND,
        # but the pickaxe lasts three times longer
        pickaxe_durability=3 * DIAMOND_PICKAXE["durability"],
        attributes={"attack_damage": 1, "armor": 0.5},
    ),
}
generate_everything_about_these_materials(ORES_CONFIGS)

Textures become models without JSON

Drop top, side and front PNGs into assets/textures and the block is recognised. An _on suffix gives you the powered state for free.

└electric_furnace_top.pngtop face
└electric_furnace_side.pngsides
└electric_furnace_front.pngfront face
└electric_furnace_front_on.pngpowered state

electric_furnace_on.json, written because a _front_on texture exists

{
  "parent": "block/orientable",
  "textures": {
    "front": "simplenergy:item/electric_furnace_front_on",
    "side": "simplenergy:item/electric_furnace_side",
    "top": "simplenergy:item/electric_furnace_top"
  }
}

A missing library tells the player what to download

StewBeet reads your functions, works out which libraries you used, fetches them and writes the version check. Load without one and the chat names it, with a link.

One recipe, every crafting system

Declare a recipe on the item. The vanilla recipe, the Smithed Crafter NBT recipe and the furnace variant all come out of that single declaration.

calls/smithed_crafter/shapeless_recipes.mcfunction

# The backslashes are ours so it fits: the real file is one line per recipe.
execute \
  if score @s smithed.data matches 0 \
  store result score @s smithed.data \
  if score count smithed.data matches 2 \
  if data storage smithed.crafter:input {"recipe": [ \
    {"id": "minecraft:iron_ingot", "count": 1}, \
    {"components": {"minecraft:custom_data": \
      {"stardust": {"stardust_fragment": true}}}, "count": 8} \
  ]} \
  run function stardust:calls/smithed_crafter/apply_recipe \
  {"command":"loot replace block ~ ~ ~ container.16 loot
   stardust:i/stardust_ingot"}

Translation keys extracted from your code

Write your text once in Python. en_us.json is generated from what you actually wrote, so the lang file never drifts from the items.

what you wrote

tellraw @s [{text:"Entities: ",color:"gray"}, \
    {score:{name:"#entities",objective:"simplenergy.data"},color:"gold"}]

what is built: the text became a translate key

tellraw @s [{"translate":"simplenergy.entities",color:"gray"}, \
    {score:{name:"#entities",objective:"simplenergy.data"},color:"gold"}]

and the keys it collected

{
  "simplenergy.entities": "Entities: ",
  "simplenergy.electric_furnace": "Electric Furnace"
}

23 public projects are built with StewBeet

Two of them at scale, with the source you can read.

Every item in Stardust Fragment, drawn from its build

A large progression pack: custom ore tiers, blocks, paintings and a full in-game manual.

5,738 lines of Python (no comments) produce

.mcfunction
774
.mcfunction
.json
1,331
.json
textures
971
textures
Every item in SimplEnergy, drawn from its build

An energy and machine library other packs depend on, with cables, generators and machines.

1,422 lines of Python (no comments) produce

.mcfunction
270
.mcfunction
.json
805
.json
textures
434
textures
See the full list on GitHub

From nothing to a built pack in four commands

terminal

$ python --version

Python 3.14.7

Prefer uv? Every template ships a pyproject.toml, so uvx stewbeet init then uv run stewbeet build covers all four steps, Python included.

Pick a template

Three starting points. If you are unsure, take Basic.

Minimal

source

for learning beet

One stewbeet plugin and nothing else, so you can see what beet does on its own.

or download the .zip
Recommended

Basic

source

for most projects

Every plugin configured and commented, with no example content to delete afterwards. You add only what your project needs.

or download the .zip

Extensive

source

for reading real examples

A working project using every feature: ore tiers, custom blocks, paintings, a manual.

or download the .zip

New to beet? Here is who makes what

StewBeet sits on top of beet, a build tool made by another team, together with its bolt and mecha plugins. If all four names are new to you, this is how they fit.

beet, bolt, mecha and StewBeet beet runs the build. Everything else plugs into it. bolt and mecha are made by the beet team. StewBeet is a separate project by Stoupy. pip install stewbeet brings beet, bolt and mecha along. beet, bolt, mecha and StewBeet Who does what when you build a Minecraft pack beetThe build tool: runs the plugins in order and writesthe datapack and the resource pack. datapack + resource pack, ready for Minecraft boltPython-like syntax (loops,variables) inside functions mechaParses, checks and compilesevery command you write mcbeet, the beet team StewBeetA framework made of beet plugins. Declare an item in Pythonand get its models, recipes, loot tables and manual page.independent projectruns inside beet, as plugins IN SHORT beet runs the build.Everything else plugs into it.bolt and mecha are made bythe beet team. StewBeet is aseparate project by Stoupy.pip install stewbeet bringsbeet, bolt and mecha along. stewbeet.paralya.fr

Share it:PNG, darkSVG, dark, animatedPNG, lightSVG, light, animated

Define a block. Build the pack.

The Basic template wires up every plugin with commented configuration and no example content to delete.

Read the getting started guide

MIT licensed · Python 3.14+ · no account needed