- Kotlin 58.1%
- Pkl 41.4%
- Just 0.5%
| .forgejo/workflows | ||
| examples | ||
| gradle/wrapper | ||
| src/main | ||
| .gitignore | ||
| build.gradle.kts | ||
| CHANGELOG.md | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| justfile | ||
| LICENSE | ||
| PklProject | ||
| PklProject.deps.json | ||
| README.md | ||
| settings.gradle.kts | ||
pkl4mc
First mod to bring the PKL lang to Minecraft.
[DISCLAIMER] This was originally a dumb idea I had and built for self use and to learn more about PKL runtime and JVM. If it's useful to you too, great.
Unfinished docs -> nothingseries.org/pkl4mc/
What the hell is PKL?
PKL (Pickle) is a typed, composable configuration language by Apple in 2024. It gives autocomplete, type checking and reusable schemas.
Why PKL?
Minecrafts datapack files are JSON. JSON has no variables, no comments, no types and no reuse. Typo a field name? Silent failure, you will probably find out when your loot table doesn't drop anything, or your ore doesn't generate.
PKL kinda fixes this, it will catche the typo before the world loads and lets you define shared logic once.
Here is a smelting recipe in JSON:
{
"type": "minecraft:smelting",
"category": "misc",
"ingredient": { "item": "minecraft:sea_pickle" },
"result": "nothingcore:cooked_sea_pickle",
"experience": 0.7,
"cookingtime": 200
}
And here in PKL:
import "pklmc:recipe.pkl" as recipe
local r: recipe.SmeltingRecipe = new {
category = "misc"
ingredient { item = "minecraft:sea_pickle" }
result = "nothingcore:cooked_sea_pickle"
experience = 0.7
cookingtime = 200
}
output { renderer = new JsonRenderer {}; value = r }
Type a field wrong in PKL and it tells you immediately.
Features
Virtual Datapack
Drop .pkl files in config/pkl4mc/data/ and they get evaluated and injected into the data system on world load. No datagen, kinda like KubeJS.
Zip & Folder Datapacks
Same structure as vanilla world/datapacks/, just with .pkl files inside instead of JSON.
config/pkl4mc/
data/ ← loose .pkl files (KubeJS-like)
<namespace>/
recipes/
loot_tables/
datapacks/
pack.zip ← zip datapack with .pkl files inside
pack/ ← folder datapack with .pkl files
<namespace>/
recipes/
loot_tables/
Commands
| Command | Description |
|---|---|
| /pkl errors | PKL evaluation errors since last reload |
| /pkl reload | Reload all PKL datapacks without restarting |
| /pkl convert namespace:path | Convert any loaded JSON resource to PKL |
The convert command is a migration tool which dumps any vanilla or mod JSON as PKL to config/pkl4mc/data/. Good starting point if you're porting anything.
/pkl convert minecraft:recipes/stick
/pkl convert minecraft:loot_tables/chests/ancient_city
/pkl convert nothingcore:cooked_sea_pickle
Schemas
PKL schemas for vanilla data formats ship inside the jar. IDE autocompletes and type validations work via PKL's language server. (schema coverage is still a wip btw)
Amends style (set fields directly)
| Schema | Usage |
|---|---|
| Recipes | amends "@pkl4mc/recipe.pkl" |
| Advancements | amends "@pkl4mc/advancement.pkl" |
| Tags | amends "@pkl4mc/tag.pkl" |
| Dimension types | amends "@pkl4mc/dimension_type.pkl" |
| Biomes | amends "@pkl4mc/biome.pkl" |
| Placed features | amends "@pkl4mc/placed_feature.pkl" |
| Structures | amends "@pkl4mc/structure.pkl" |
| Structure sets | amends "@pkl4mc/structure_set.pkl" |
| Noise settings | amends "@pkl4mc/noise_settings.pkl" |
| Loot tables | amends "@pkl4mc/loot_table.pkl" |
| Configured features | amends "@pkl4mc/configured_feature.pkl" |
Import style (pick a typed class):
| Schema | Usage |
|---|---|
| Configured carvers | import "@pkl4mc/configured_carver.pkl" as carver |
Config API
So... now that your datapacks are already in PKL, why go back to TOML for configs? For mod devs evaluate PKL files directly to typed Kotlin (or Java) objects.
@Serializable
data class MyConfig(val tickRate: Int, val enabled: Boolean)
val config = PklConfig.load<MyConfig>(
FMLPaths.CONFIGDIR.get().resolve("mymod/config.pkl")
)
So who is this for?
Probably for modpack or datapack devs, who wanna try something new and maybe hate json for some reason. Also for mod devs who wanna depend on pkl4mc as a library and use PklConfig.
Stack
| Version | |
|---|---|
| Minecraft | 1.20.1 Forge |
| Kotlin for Forge | 4.12.0 |
| pkl-core | 0.31.1 (shaded, ANTLR relocated) |
License
- OSL-3.0 (pkl4mc)
- Apache 2.0 (pkl-core)