Skip to content

Templates

Templates are essentially compile-time macros. They allow you to define a command, that when called, will be replaced with the code defined in the Template. This is useful for defining complex sequences of commands that are used multiple times in a script, or for modfiying the behavior of vanilla commands.

Note

Templates can only be defined inside of .mcbt files.

Creating a Template

To create a template, you use the template keyword followed by the name of the template. Inside the template block, you define the code that will be executed when the template is called.

template <template_name> {
    <template_definition>
}

Defining Call Signatures

Defining a template call signature is done using the with keyword followed by a list of arguments, then a code block.

template my_super_template {
    with [args] {
        <mcb_code>
    }
}

Call signatures are checked in the order of definition, so it's best to order them from most specific to least specific.

Example

Ordering Signatures for Specificity

Definition
template my_template {
    with check this first {
        say Very specific
    }
    with a:word b:word c:word {
        say Less specific
    }
    with a:raw {
        say Least specific
    }
}

Arguments

Each argument is defined as a name followed by a type. The type is optional, and if not provided, the argument will be treated as a literal.

Arguments can be referenced inside of Script blocks by name.

Argument Types

  • block - This will match a Block (Brackets only, no keyword, name, or function arguments).
  • float - This will match any number.
  • int - This will match any integer.
  • js - This expects an inline JavaScript block and will pass the computed value.
  • literal - Special, matches the argument name exactly, and is the default if no type is provided.
  • raw - Collects all remaining input as a string.
  • word - Matches anything up until the end of the input or the next space.
Examples

Simple Template

Definition
template my_template {
    with string:raw {
        say <%string%>
    }
}
Usage
my_template Hello, World!
Output
say Hello, World!

Warning

If you pass a Script Block to anything other than a js argument, it will be interpreted before being passed to the template.

Examples

Passing a Script Block to a non-js Argument

Definition
template my_template {
    with a:int {
        say <%a%>
    }
}
Usage
my_template <%1+1%>

Because a is not a js argument, the JS block will be evaluated before being passed to the template. So the argument recieves the value 2 instead of the block <%1+1%>.

Output
say 2

Calling a Template

To call a template, you first need to import it. This is done using the import keyword followed by the path to the .mcbt file containing the template.

Relative Imports

The path to the template file is relative to the file that is importing it.

Example

If your project was structured like this:

/src
    main.mcb
    /templates
        my_template.mcbt

And you wanted to import the my_template.mcbt file into main.mcb, you would do so like this:

import ./templates/my_template.mcbt

For more info on imports, see the Imports.

import ./<template_path>.mcbt

Once imported, you can call the template either via template <template_name> or <template_name> followed by the arguments.

[template] <template_name> [args]

Warning

If your template name is the same as an MC-Build keyword, you must use the template keyword to call it.

Top-Level Templates

A normal with signature is called from inside a function, and its body is commands. A tld with signature is called at the top level of a .mcb file (outside any function). Its body can contain anything a .mcb file can: functions, directories, JSON files, tags, clocks, compile-time loops and other top-level template calls.

template <template_name> {
    tld with [args] {
        <top_level_mcb_code>
    }
}

A template can have both tld with and with signatures. MC-Build uses the tld with signatures for top-level calls and the with signatures for calls inside functions. A top-level call inside a directory block puts everything it creates in that directory.

Examples

Generating Functions and Files

Definition
template counter {
    load {
        scoreboard objectives add counters dummy
    }
    tld with name:word {
        function <%name%>_inc {
            scoreboard players add #<%name%> counters 1
        }
        damage_type <%name%> { "message_id": "generic", "scaling": "never", "exhaustion": 0 }
    }
    with name:word {
        function ./<%name%>_inc
    }
}
Usage
import ./counter.mcbt

counter kills
dir stats {
    counter deaths
}

function on_kill {
    counter kills
}

This creates the functions kills_inc and stats/deaths_inc and the damage types kills and stats/deaths. The on_kill function uses the with signature, so it contains function <namespace>:kills_inc.

Generating Code with JavaScript

In a tld with body, emit.mcb() in a multi-line Script block takes top-level code.

Definition
template numbered {
    tld with name:word count:int {
        <%%
            for (let i = 0; i < count; i++) {
                emit.mcb(`function ${name}_${i} {\nsay ${name} ${i}\n}`);
            }
        %%>
    }
}
Usage
numbered step 3

This creates the functions step_0, step_1 and step_2.

Tick and Load

Templates can define tick and load blocks, which are functions that will be appended to the minecraft:tick and minecraft:load function tags respectively.

template <template_name> {
    load {
        <mcb_code>
    }
    tick {
        <mcb_code>
    }
    with [args] {
        <mcb_code>
    }
}

Note

Templates can only define one load and one tick block each

Warning

The tick and load blocks are not appended to the minecraft:tick and minecraft:load functions unless the template is called at least once.

Examples

A simple Clock Template

Definition
template clock {
    load {
        scoreboard objectives add i dummy
        scoreboard players add #clock.ticks i 0
        scoreboard players set #clock.20 i 20
    }
    tick {
        scoreboard players add #clock.ticks i 1
    }
    with get ticks player:word objective:word {
        scoreboard players operation <%player%> <%objective%> = #clock.ticks i
    }
    with get seconds player:word objective:word {
        scoreboard players operation <%player%> <%objective%> = #clock.ticks i
        scoreboard players operation <%player%> <%objective%> /= #clock.20 i
    }
}