Runtime Logic
This is the single most important concept to understand when moving from raw datapacks (or any imperative language) to Kore. Get this right and everything else clicks into place.
The two worlds
When you write Kore, your code runs in two completely separate worlds at two different times:
| Compile-time (build) | Runtime (in-game) | |
|---|---|---|
| When | When you run your main function to generate the pack |
When Minecraft executes the generated functions |
| Language | Kotlin | Minecraft commands (.mcfunction) |
val / var |
Real Kotlin variables | Do not exist - use scoreboards / storage |
if / else |
Real Kotlin branches | Do not exist - use execute if / predicates |
for / while |
Real Kotlin loops | Do not exist - use recursion / schedule / macros |
| Knows | Everything in your Kotlin code | Only the live world state |
Kotlin val, var, if, for, while are generation-time tools. They decide what commands get written into your datapack. They are gone by the time the pack runs. They never look at the player, the world, or a score.
To react to the live game (a player's score, a block in the world, an entity that exists right now), you need runtime tools: scoreboards, data storage, the execute command, predicates, and macros.
Compile-time: Kotlin builds your commands
Standard Kotlin runs once, when you generate the pack. Use it to remove repetition and assemble functions.
The generated .mcfunction is just three flat lines:
There is no loop left in the output. The for was a code generator, not in-game behavior. The same goes for if:
Runtime: variables
In-game you cannot store a value in a Kotlin var. The two runtime containers are scoreboards (for integers) and data storage (for any NBT: strings, lists, compounds, decimals).
Scoreboards - integer variables
See Scoreboards for the full command reference.
For arithmetic between scores, use operation, or reach for Scoreboard Math when you need trigonometry/algebra.
Data storage - everything else
See Data Storage for the full guide. Storage holds strings, lists and compounds that scores cannot:
Runtime: conditions (if / else)
There is no in-game if. You branch with the execute if / execute unless chain ( see Execute) or by referencing a Predicate.
Emulating if / else
Minecraft has no else. The cleanest pattern is two mirrored checks (if then unless), or an early return so the second branch only runs when the first did not.
For reusable, complex conditions, build a Predicate once and reference it:
Runtime: loops
There is no in-game for or while. The three runtime looping patterns are function recursion, schedule, and iterating an entity selector.
Recursion (loop a fixed/conditional number of times)
A function that calls itself loops once per tick step. Use a score as the counter and execute if/unless as the guard so it stops.
schedule (loop over time)
schedule re-runs a function after a delay - ideal for spacing work across ticks instead of hammering every tick. See Time for the .ticks / .seconds helpers.
Iterating entities
To "loop over all players", run the body as each matched entity - the selector does the iteration:
Macros: when text must be dynamic
A score holds a number, storage holds NBT, but sometimes you need to inject a runtime value into a part of a command that is normally fixed text (a name, a coordinate). That is what Macros are for - runtime string substitution. They are not variables: you cannot do math on them, only paste them into the command text.
Mental model cheat sheet
- Need to remove repetition while writing the pack? Use Kotlin
for/if/ functions. (compile-time) - Need to remember a number in-game? Scoreboard. (runtime)
- Need to remember text / a list / decimals in-game? Data storage. (runtime)
- Need to branch on live world state?
execute if/unlessor a predicate. (runtime) - Need to repeat in-game? Recursion,
schedule, or an entity selector. (runtime) - Need to paste a runtime value into command text? Macro. (runtime)
See also
- Execute - the runtime control-flow command
- Data Storage - the runtime NBT variable container
- Scoreboards - runtime integer variables
