Function (Power Type)

A reusable, parameterised entity action other powers call by id.

A named bundle of actions that other powers call by id, optionally with arguments. It does nothing on its own — holding this power has no effect until something runs it with apoli:run_function.

Type ID: apoli:function

It is the data-pack equivalent of an .mcfunction with macro arguments: write the behaviour once, call it from ten powers with different numbers.

Fields

FieldTypeDefaultDescription
entity_actionEntity ActionrequiredWhat the function does. Runs on whichever entity called it.
parametersArray of StringinferredThe argument names the body uses. Leave it out and it is read from the [name] placeholders in the body.

A placeholder is a parameter name in square brackets — [amount] — written anywhere inside entity_action. Declaring a parameter the body never uses, or using one that isn’t declared, is a load error.

Examples

A damage function with one argument:

{
    "type": "apoli:function",
    "entity_action": {
        "type": "apoli:damage",
        "amount": "[amount]",
        "damage_type": "minecraft:generic"
    }
}

Call it from anywhere:

{
    "type": "apoli:action_on_hit",
    "entity_action": {
        "type": "apoli:run_function",
        "function": "example:hurt",
        "arguments": { "amount": 3 }
    }
}

Placeholders substitute by value, not by text, so "amount": "[amount]" with "amount": 3 yields the number 3 — an int field stays an int. A placeholder that is only part of a larger string is spliced in as text instead:

{
    "type": "apoli:function",
    "entity_action": {
        "type": "apoli:execute_command",
        "command": "tag @s add form_[name]"
    }
}

Because substitution happens before the field is parsed, an argument can be anything that field accepts — including an expression:

{ "type": "apoli:run_function", "function": "example:hurt", "arguments": { "amount": "health / 4" } }

Notes

A function with no parameters is parsed once when the data pack loads, so calling it costs exactly what the action inside costs. A parameterised one is built on first use per distinct set of arguments and cached (8 variants, least-recently-used evicted) — the same approach vanilla uses for macro functions. Calling one function with hundreds of different numbers will rebuild it often; prefer an expression argument over many literal ones.

Recursion is capped at 16 nested calls. Past that the call is dropped and the server logs the function’s id once. A function that calls itself is a data-pack bug, not a supported loop — use apoli:loop or apoli:delay.

Only entity_action is supported. Bi-entity, block and item actions need context an entity action cannot supply, and are reachable anyway through the meta actions that do have it.