Cookbook
This page collects practical patterns you can lift into a real Kore datapack. It does not try to replace the full reference pages; instead, it shows how several documented features fit together.
If your main goal is migrating an already mature datapack architecture, pair this page with From Datapacks to Kore.
Recipe 1 - A clean pack bootstrap
Use a dedicated setup function for one-time registration and a tick function for recurring gameplay logic.
Use this pattern when you want a clear separation between initialization and runtime logic.
Related pages:
Recipe 2 - Reuse logic by exposing named functions from Function
Sometimes you want a helper that can be called from multiple places while still generating a normal datapack function. An ergonomic pattern is to attach it directly to Function:
This is totally fine even if several call sites end up recreating the same named function declaration. Kore is heavily optimized for this kind of reuse, so regenerating the same function is effectively instant and keeps your code much cleaner than manually caching every FunctionArgument yourself.
Use this when the code should remain callable as a proper datapack function, for example for scheduling, tags, cross-function reuse, or debug visibility.
Related pages:
Recipe 3 - Reuse code inline without creating a function
Not every reusable snippet needs its own generated function. If you just want to share a small block of commands, regular Function extensions are often enough:
Prefer this pattern when the reused logic is small and should stay inlined at the call site instead of becoming a separate /function entry.
Related pages:
Recipe 4 - Gate gameplay with selectors and scores
Keep complex target selection in reusable values instead of repeating long selector builders.
This keeps wave logic readable and centralizes the rules that define an eligible player.
Related pages:
Recipe 5 - Define a custom item and validate it later
Combine item components with predicates when the item should remain recognizable after being moved between inventories.
Use this when a datapack needs both rich item metadata and reliable runtime checks.
Related pages:
Recipe 6 - Schedule delayed actions instead of duplicating code
Wrap delayed logic in a named function and schedule it instead of inlining the same command sequence multiple times.
This pattern is a good default for cutscenes, telegraphs, cooldowns, and delayed effects.
Related pages:
Recipe 7 - Choose between core, helpers, and oop early
When a system starts simple, keep it in kore. Add helpers for reusable glue. Move to oop once gameplay objects need long-lived identities.
- Use
korefor raw commands, data-driven JSON, tags, functions, and lightweight selectors. - Use
helpersfor rendering pipelines, geometry, scheduler utilities, or state delegates. - Use
oopfor players, teams, boss bars, timers, spawners, scoreboards, and state machines.
That decision alone prevents many documentation and architecture mistakes later.
Related pages:
Recipe 8 - Import an existing datapack, then wrap it with Kotlin
Use bindings when you already have a datapack and want typed access to its resources instead of stringly typed calls.
Typical flow:
- Configure a binding source
- Generate Kotlin wrappers
- Call imported functions/resources from your own pack
This is especially useful for large internal libraries or third-party datapacks that your project depends on.
Related pages:
How to use this page
Treat these recipes as starting points:
- Extract repeating code into small reusable helpers
- Move cross-cutting conditions into selectors or predicates
- Favor typed arguments over handwritten command strings
- Keep links to the relevant reference pages nearby while you iterate
