Datapack Generators
Table of Contents
- Datapack Generators
- Kore – Kotlin Datapack Generator Extraordinaire
- Why Kore leads the pack
- Minimal example
- Example: item components without the JSON pain
- Example: timeline builder for environmental control
- Already using another tool?
- Why Kore is better long-term for big projects
- Sandstone – TypeScript Datapack Framework
- Example: a simple function with variables and tags
- Example: generate a loot table via JSON helpers
- Beet / StewBeet – Python Pack Pipeline and Automation
- Example: define a custom block (StewBeet)
- Example: Beet pipeline hook (Python)
- JMC – Compact Scripting Language
- Example: loop + score logic
- Conclusion – Why Kore is still the best bet
Datapacks are no longer a pile of handcrafted JSON. With the Game Drops cadence, new registries (like timeline or world_clock) and the widespread use of item components, manual authoring quickly becomes fragile and expensive. That is exactly why the ecosystem pivoted to datapack generators and frameworks that treat packs like real software (Rationale - Beet documentation).
This article focuses on the most used tools today, with a clear priority: put Kore front and center. The goal is simple: show why Kore is the best option even if you are already invested in Sandstone, Beet/StewBeet, or JMC.
(Note: this article intentionally focuses on code-based generators. If your only goal is to quickly create simple JSON files, tools like Misode’s Datapack Generators are still perfect.)
Kore – Kotlin Datapack Generator Extraordinaire
Kore is an open-source Kotlin library that turns a datapack into a real software project: a typed DSL, readable builders, and stable generation of Minecraft JSON/functions. In short: you write clean Kotlin, compile, and get a reliable pack.
Why Kore leads the pack
- Type safety and readability: Kotlin typing prevents silent errors (invalid tags, misspelled components, wrong registry keys). Autocomplete and compile-time errors save hours.
- Broad coverage: commands, functions, macros, predicates, loot tables, recipes, advancements, worldgen, dialogues, item components, timelines. Kore tracks new features without forcing you back into raw JSON.
- Built-in helpers: scheduler, inventory manager, display entities, mannequins, scoreboard utilities, and more. Repetitive patterns are already modeled.
- Flexible build outputs: generate to a folder, ZIP, or JAR using
.generate(),.generateZip(), and.generateJar(). - Interoperability: experimental bindings for importing existing datapacks and compatibility with pipelines that combine assets and logic.
- Clear requirements: Java 21+ and a Kotlin environment, with official docs to get you started quickly.
Minimal example
fun main() {
dataPack("example") {
function("display_text") {
tellraw(allPlayers(), textComponent("Hello World!"))
}
}.generateZip()
}
Example: item components without the JSON pain
val midasSword = item(Items.GOLDEN_SWORD) {
display {
name = textComponent("Midas Sword")
}
components {
attackRange(base = 5.0, correction = 0.5)
weapon {
kinetic(damage = 4.0)
shockwave(radius = 1.5, destructible = false)
}
customData {
"kore_rpg" {
"id" put "midas_sword"
"tier" put 5
}
}
}
}
Example: timeline builder for environmental control
timeline("blood_moon_cycle") {
interpolated(0..24000) {
keyframe(6000, SkyColor(0x87CEEB))
keyframe(12000, SkyColor(0xFF4500)) {
easing = Easing.CUBIC_IN
}
keyframe(18000, SkyColor(0x8B0000))
keyframe(23000, SkyColor(0x87CEEB))
}
}
Already using another tool?
Kore does not force you to throw everything away. Keep your asset pipeline (Beet/StewBeet), import existing datapacks via bindings, and migrate your critical logic gradually to code that is more maintainable and safer.
Why Kore is better long-term for big projects
- Scales with complexity: as systems grow (classes, progression, AI, world events), Kore’s typed DSL keeps changes local and reduces cascading breakage.
- Refactor-friendly: Kotlin refactors (rename, extract, inline) are reliable, and the compiler catches dead paths and mismatched types that would silently fail in JSON.
- API coverage keeps you moving: when new game features land, Kore’s typed builders prevent the “stringly-typed” regressions that add tech debt in large packs.
- Maintainable collaboration: Kotlin + Gradle supports code review, CI, and consistent formatting. Large teams benefit from clear abstractions and tests around generators.
- Longevity: big packs live for years. Kore minimizes “tribal knowledge” by baking knowledge into types and helpers instead of scattered JSON conventions.
(Documentation and examples: Kore site and Kore docs.)
Sandstone – TypeScript Datapack Framework
Sandstone targets web developers: TypeScript, NPM, and ergonomics that feel like a front-end project. It is great for fast prototyping and leveraging the JavaScript ecosystem (tools, libraries, hot reload). The tradeoff is that typing is less strict than Kotlin, and the newest features can arrive with a short delay.
Example: a simple function with variables and tags
import { MCFunction, tag, raw } from "sandstone";
MCFunction("join_announce", () => {
raw("scoreboard objectives add joined dummy");
raw("scoreboard players set @a joined 1");
raw("tellraw @a {\"text\":\"Welcome!\",\"color\":\"gold\"}");
});
tag("minecraft:tick", "join_announce");
Example: generate a loot table via JSON helpers
import { LootTable } from "sandstone";
LootTable("chests/ruby_cache", {
pools: [
{
rolls: 1,
entries: [{ type: "item", name: "minecraft:emerald", weight: 3 }],
},
],
});
When to choose it? If your team is fully JavaScript/TypeScript and wants a native Node workflow. When to prefer Kore? When stability, completeness, and long-term maintenance matter most.
Beet / StewBeet – Python Pack Pipeline and Automation
Beet is a pack development kit: a Python library and toolchain that unifies datapack and resource pack tooling into a single pipeline. It provides primitives to read, edit, and merge packs, and a plugin system to build custom workflows.
StewBeet is a framework built on top of Beet focused on automation for datapacks. It ships templates and a large set of generators so you can define content and let the framework produce the boilerplate.
Key StewBeet capabilities (from the project docs/README):
- Automatic resource pack file generation (models, textures, sounds) with the ability to override assets.
- Versioned load and clock functions (tick/second/minute).
- Loot tables for definitions and a generated
_give_allhelper. - Automatic interactive in-game manual and language file generation.
- Function headers and vanilla-style recipe unlocking helpers.
- Integrations with Smithed Custom Blocks/Crafter/Furnace NBT Recipes, Bookshelf, Smart Ore Generation, ItemIO, and Common Signals.
- Merging packs with Smithed Weld and support for external library datapacks.
Example: define a custom block (StewBeet)
# setup_definitions.py
Block(
id="super_stone",
vanilla_block=VanillaBlock(id="minecraft:cobblestone", apply_facing=False),
recipes=[
# Examples of crafting recipes (shaped and shapeless), no need to specify result -> will default to the Item id
CraftingShapedRecipe(category="blocks", shape=["XXX", "XXX", "XXX"], ingredients={"X": Ingr("minecraft:stone")}),
CraftingShapelessRecipe(category="blocks", ingredients=9 * [Ingr("minecraft:deepslate")]),
# Example of recipe with vanilla result (not custom item)
SmeltingRecipe(experience=0.1, cookingtime=200, category="blocks", ingredient=Ingr("super_stone"), result=Ingr("minecraft:diamond")),
BlastingRecipe(experience=0.1, cookingtime=100, category="blocks", ingredient=Ingr("super_stone"), result=Ingr("minecraft:diamond")),
],
)
Example: Beet pipeline hook (Python)
from beet import Context
def beet_default(ctx: Context):
ctx.require("beet.contrib.render")
ctx.data["minecraft:tags/functions/tick.json"] = {
"values": ["my_pack:tick"]
}
When to choose it? Use Beet when you want a flexible Python pipeline to assemble packs and integrate generators. Choose StewBeet if you want a batteries-included automation layer for assets, loot, manuals, and integrations. Why it complements Kore: Kore can handle game logic in Kotlin while Beet/StewBeet can cover asset and pipeline automation.
JMC – Compact Scripting Language
JMC is a language that compiles to mcfunction. Its main value: write cleaner functions with loops, variables, and conditions without adopting a full framework. It is lightweight and quick to learn, but limited to command logic (no rich API for other datapack files).
Example: loop + score logic
scoreboard objectives add timer dummy
function tick() {
timer = timer + 1
if (timer >= 20) {
tellraw @a "One second passed"
timer = 0
}
}
When to choose it? For fast prototypes or simple packs centered on functions. When to prefer Kore? As soon as the project grows or you want to centralize all resources and systems in one strongly typed codebase.
Conclusion – Why Kore is still the best bet
The ecosystem offers several solid options, but Kore stands out for completeness, safety, and its ability to absorb game changes without forcing you back into fragile JSON. It combines the rigor of a real language, powerful helpers, and clear documentation.
For long-term, large-scale projects, Kore’s biggest advantage is maintainability: a typed API that survives refactors, shared abstractions that scale to large teams, and a workflow that supports CI, reviews, and consistent style. When your pack turns into a real product with ongoing updates, those qualities make the difference between constant firefighting and predictable growth.
If you already use Sandstone, Beet/StewBeet, or JMC, you do not need to throw everything away: adopt Kore first for critical logic, then expand gradually. This smooth transition is exactly why Kore is a credible choice even for teams already equipped with other tools.