Macros

Macros allow dynamic command arguments that are substituted at runtime. Added in Minecraft 1.20.2, they enable creating reusable functions with parameters. For basic command usage, see Commands.

Using Macros

To define a macro, use the macro() function:

say("I'm gonna use the macro ${macro("foo")}")
Kotlin

Inside a Minecraft function:

function("my_function") {
	say("This is my macro: ${macro("bar")}")
}
Kotlin

When called, this will substitute the actual text of the macro.

You can also evaluate a list of macros and have fully dynamic commands:

eval("command", "arg1", "arg2")
// equals to minecraft code:
// $$(command) $(arg1) $(arg2)
Kotlin

Calling functions with macros

You can call a function with macros by using the new arguments argument.

function("my_function", arguments = nbt { this["bar"] = "baz" })
Kotlin

That can also be a DataArgument (block position/entity selector/storage).

function(
	"my_function",
	arguments = allEntities {
		type = EntityTypes.MARKER
		name = "test"
	},
	path = "data.test" // optional path is available
)
Kotlin

Defining Macro Classes

For more complex macro usage, you can create a Macros subclass to define your macros:

class MyMacros : Macros() {
	val myMacro by "my_macro"
}
Kotlin

Then pass an instance to your function:

function("my_function", ::MyMacros) {
	say(macros.myMacro)
} 
Kotlin

Now you can access the macros on the macros property.

This also allows validating macros that are required when calling the function with an NBT Compound.

Exemple:

class TeleportMacros : Macros() {
	val player by "player"
}

datapack {
	val teleportToSpawn = function("teleport_to_spawn", ::TeleportMacros) {
		teleport(player(macros.player), vec3())
	}

	load {
		function(teleportToSpawn, arguments = nbt { this["name"] = "jeb_" }) // Will throw an error because function expects "player" macro

		function(teleportToSpawn, arguments = nbt { this["player"] = "jeb_" }) // Works fine
	}
}
Kotlin

Best Practice

When using macros, you can create a function with arguments that calls the function with the macros:

fun main() {
	dataPack {
		function("teleport_to_spawn") {
			teleport(player(macro("player")), vec3())
		}
	}
}

fun Function.teleportToSpawn(player: String) {
	function("teleport_to_spawn", arguments = nbt { this["player"] = player })
}
Kotlin

Then you can call this function with your argument as a macro:

teleportToSpawn("jeb_")
Kotlin

Limitations

  • Macros can only be used in functions.
  • Macros aren't variables, they are just text substitutions, you can't do operations on them.
  • Macros are not type-checked.
  • It would be very difficult and long for Kore to allow macros as any argument of commands because of the wide variety of argument types and contexts in Minecraft commands.