---
title: Adding Custom Molang Queries
hide_meta: true
---

<Callout variant="info">
    See [How to use Molang](../blockbench/animating_in_bb#how-to-use-molang) for how to use your custom Molang Queries, and the list of built-in queries. Variables and the expression syntax are covered [below](#variables).
</Callout>

# Overview

Custom Molang queries allow you to expose additional data to your animations. These queries can be registered and updated through your animator implementations.

## Defining Custom Queries

### Step 1: Define Query Constants

First, define your custom query constants in your mods main class:

```java
public static final String MY_CUSTOM_VALUE = MolangQueries.normalize("query.my_custom_value");
```

### Step 2: Register Variables

Create a method to register your variables, typically called during initialization. Register against the shared `MolangParser.INSTANCE` — don't create a new `MolangParser`, since doing so just re-runs its constructor setup for no benefit:

```java
private void registerXModsVariables() {
    MolangParser.INSTANCE.register(new LazyVariable(ModClass.MY_CUSTOM_VALUE, 0));
}
```

<Callout variant="warning">
    Register your variables during mod initialization, before resources load. Animations bind to a variable when they are loaded, so a variable registered (or re-registered) afterwards isn't seen by animations that are already loaded until the next resource reload.
</Callout>

### Step 3: Implement Query Updates

Override `applyMolangQueries` in your AzAnimator class to update your query values during animation. Create your suppliers once and have them read the entity currently being animated, rather than creating a new lambda every frame. Binding then allocates nothing:

```java
public class MyEntityAnimator extends AzEntityAnimator<MyEntity> {

    // Resolved once, instead of looking the query up by name every frame.
    private static final MolangVariableRef MY_CUSTOM_VALUE_REF = new MolangVariableRef(ModClass.MY_CUSTOM_VALUE);

    // The entity currently being animated, set in applyMolangQueries below.
    private MyEntity currentEntity;

    // Created once, when the animator is created.
    private final DoubleSupplier myCustomValue = () -> currentEntity.getChargeLevel();

    @Override
    protected void applyMolangQueries(MyEntity entity, double animTime, float partialTicks) {
        super.applyMolangQueries(entity, animTime, partialTicks);

        this.currentEntity = entity;
        MY_CUSTOM_VALUE_REF.setMemoized(myCustomValue);
    }

    // ... registerControllers, getAnimationLocation, etc.
}
```

## Adding Query Functions

A query function takes arguments, like `query.my_charge_level(1)`. Use one when a single query needs a parameter, such as a slot, an axis or a threshold.

### Step 1: Create the Function

Extend `ContextQueryFunction`. It gives you the current `MolangQueryContext`, which for AzureLib animators is an `AzMolangQueryContext` holding the entity being animated:

```java
public class ChargeLevel extends ContextQueryFunction {

    public ChargeLevel(IValue[] values, String name) throws Exception {
        super(values, name);
    }

    @Override
    public int getRequiredArguments() {
        return 1;
    }

    @Override
    protected double evaluate(MolangQueryContext context) {
        if (context instanceof AzMolangQueryContext azContext && azContext.entity() instanceof MyEntity entity) {
            return entity.getChargeLevel(intArg(0));
        }

        return 0;
    }
}
```

<Callout variant="warning">
    Extend `ContextQueryFunction` (or keep your class out of the `mod.azure.azurelib.core.molang.functions` package). Functions in that package are treated as pure math and are folded to a constant when animations load, so a game-state query would freeze at its load-time value.
</Callout>

### Step 2: Register the Function

Register it during mod initialization, before resources load, alongside your variables:

```java
MolangParser.INSTANCE.registerFunction("query.my_charge_level", ChargeLevel.class);
```

Animations can then call `query.my_charge_level(1)` or `q.my_charge_level(1)`. Unlike variable queries, functions are always written with parentheses.

## Registration Methods

### Memoized Values

The supplier runs at most once each time the value is bound: the first time an animation reads the query for that entity that frame. Every other read that frame reuses the result. Because you bind it again every frame, the value still updates every frame. This is the right choice for almost every query, especially ones that are expensive to calculate or used by several keyframes:

```java
MY_CUSTOM_VALUE_REF.setMemoized(() -> calculateValue());

private double calculateValue() {
    // Runs once per entity per frame, no matter how many keyframes read the query
    double baseValue = 10.0;
    double modifier = 1.5;
    return baseValue * modifier;
}
```

### Dynamic Values

The supplier runs every time an animation reads the query. Only use this when the value must be recalculated on each read rather than once per entity per frame:

```java
MY_CUSTOM_VALUE_REF.set(() -> getUpdatedValue());

private double getUpdatedValue() {
    // Runs on every read of the query
    double currentTime = System.currentTimeMillis() / 1000.0;
    return Math.sin(currentTime) * 10.0; // Creates a smooth oscillating value
}
```

### Static Values

For constant values:

```java
MolangParser.INSTANCE.register(new LazyVariable(ModClass.MY_CUSTOM_VALUE, 42.0));
```

## Using Your Queries in Animations

Queries can be written with either the full or the short prefix, so `query.my_custom_value` and `q.my_custom_value` are the same query. The same applies to `variable.`/`v.`, `temp.`/`t.` and `context.`/`c.`.

## Variables

Molang has three kinds of names you can store values in:

| Prefix                  | Lives                                                         | Typical use                                        |
|-------------------------|---------------------------------------------------------------|----------------------------------------------------|
| `variable.` / `v.`      | On each animatable, across frames and across every expression | State an animation keeps, values driven from code  |
| `temp.` / `t.`          | One evaluation of one expression; starts at 0 every time      | Intermediate results inside a longer expression    |
| `query.` / `q.`, `context.` / `c.`, `math.`, `array.` | Read-only                       | Game state, built-in functions and arrays          |

Each entity, block entity and item has its own set of `variable.*` values, so a value one entity assigns is never seen by another. A value assigned in one keyframe is readable in every other keyframe of that animatable, on the same frame and later frames.

Assigning to a query, a `context.*` or `math.*` name, or a constant is an error: the expression logs a message and evaluates to 0.

### Driving `variable.*` from Code

The simplest way to feed per-entity data to an animation, without registering a query, is to set a variable on the animatable's scope:

```java
@Override
protected void applyMolangQueries(MyEntity entity, double animTime, float partialTicks) {
    super.applyMolangQueries(entity, animTime, partialTicks);

    this.context().molangScope().set("v.charge", entity.getChargeLevel());
}
```

Animations read it as `v.charge` or `variable.charge`. The scope also has `get`, `isSet`, `remove` and `clear`.

Variables can hold strings, arrays and entity references as well as numbers. Set those with `setObject`:

```java
this.context().molangScope().setObject("v.mode", entity.isAngry() ? "angry" : "calm");
this.context().molangScope().setObject("v.skins", MolangArray.ofNumbers(0, 1, 2));
```

Entity references stored in a `variable.*` are held weakly, so a scope never keeps an entity alive. Once the entity is gone the variable reads as unset, and `v.target ?? ...` falls through.

<Callout variant="info">
    A `variable.*` name you register or drive globally with `MolangParser.INSTANCE.register`, `setValue` or `setMemoizedValue` still works the way it always has: every animatable reads that global value until it assigns its own. For per-entity data, prefer the scope above, or a query.
</Callout>

## Expression Syntax

Keyframe values can be a single expression or several statements separated by `;`:

```
t.wave = math.sin(q.anim_time * 360);
v.peak = math.max(v.peak ?? 0, t.wave);
return t.wave * 10;
```

| Syntax                                   | Meaning                                                                                       |
|------------------------------------------|-----------------------------------------------------------------------------------------------|
| `+ - * / % ^`                            | Arithmetic (`^` is power).                                                                    |
| `< <= > >= == !=`                        | Comparisons, giving 1 or 0.                                                                   |
| `&&`, `\|\|`, `!`                         | Logic. `&&` and `\|\|` stop early, so the right side isn't evaluated when it can't matter.      |
| `a ? b : c`                              | `b` if `a` is non-zero, else `c`.                                                             |
| `a ? b`                                  | `b` if `a` is non-zero, else 0.                                                               |
| `v.x ?? 1`                               | `v.x` if it has been given a value, else 1.                                                   |
| `name = value`                           | Assignment. Allowed anywhere an expression is; it evaluates to the assigned value.            |
| `{ ...; ...; }`                          | A block of statements, e.g. as the branch of a conditional.                                   |
| `return value`                           | Ends the expression with `value`.                                                             |
| `loop(count, { ... })`                   | Runs the block `count` times (at most 1024). `break` leaves the loop, `continue` skips ahead. |
| `'text'`                                 | A string. Case is kept; strings support only `==` and `!=`.                                   |
| `array[index]`                           | An array element. The index is floored, negative reads element 0, past the end wraps around.  |
| `for_each(t.e, array, { ... })`          | Runs the block once per element, assigned to `t.e` (or a `v.*`). Supports `break`/`continue`. |
| `entity->expression`                     | Evaluates `expression` against another entity, e.g. `t.e->q.health`. 0 if it isn't a live entity. |
| `this`                                   | The current value of the bone channel the keyframe sets. 0 outside keyframes.                 |
| `true`, `false`, `math.pi`               | 1, 0 and π.                                                                                   |

A conditional with blocks:

```
q.is_on_ground ? { v.air_time = 0; } : { v.air_time = (v.air_time ?? 0) + 1; };
return math.min(v.air_time, 20) * 2;
```

- Without a `return`, a multi-statement expression evaluates to its last statement.
- Names are case-insensitive; string contents are not.
- An expression the compiler can't parse is retried with AzureLib's older parser and logs a warning containing "Falling back to the legacy parser"; if that fails too, it evaluates to 0. Invalid Molang, such as `'a' + 1` or assigning to an array element, is rejected outright and evaluates to 0.

### Strings

```
q.get_equipped_item_name == 'bow'
q.is_item_name_any('slot.weapon.mainhand', 0, 'minecraft:crossbow')
q.equipped_item_any_tag('main_hand', 'minecraft:swords')
q.any(q.get_equipped_item_name, 'bow', 'crossbow')
```

A string read as a number is 0.

### Arrays and `for_each`

Arrays come from queries such as `q.get_nearby_entities(radius, 'minecraft:pig')`, from `array.*` names registered in code, or from a `variable.*` set with `setObject`. They are read-only and shared by reference.

```
t.babies = 0;
for_each(t.pig, q.get_nearby_entities(8, 'minecraft:pig'), {
    t.babies = t.babies + t.pig->q.is_baby;
});
return t.babies;
```

`q.count(array)` gives the number of elements. `q.get_nearby_entities` scans the level each time it is called, so store the result in a `t.*` if you need it twice. Register an `array.*` with:

```java
MolangParser.INSTANCE.registerArray("array.skins", () -> MolangArray.ofNumbers(0, 1, 2));
```

### The arrow operator

`entity->expression` evaluates the right side as if animating that entity. Its queries read the other entity, and its `variable.*` values are that entity's own if it has an AzureLib animator. A removed or non-entity value on the left gives 0 without evaluating the right side.

### `this`

In a keyframe, `this` is the value the bone channel currently holds, in the same units the keyframe uses: degrees offset from the bind rotation, position offset, or scale. That is the pose the bone finished the previous frame on, so this eases a bone toward 45° over several frames instead of snapping:

```
math.lerp(this, 45, 0.2)
```

### Targets

`q.has_target`, `q.target_x_rotation` and `q.target_y_rotation` read the mob's attack target. Vanilla doesn't sync a mob's target to the client, so on most mobs these read 0 until you implement `AzMolangTargetProvider` on your entity and return a target you sync yourself (for example an entity id in `SynchedEntityData`). The rotations are absolute, like `q.body_y_rotation`; use `math.min_angle(q.target_y_rotation - q.body_y_rotation)` for a body-relative angle.

### Items

While an item renders in an entity's hand, entity queries in its animations answer for the holder, like Bedrock attachables, and `q.is_first_person` is 1 when the item itself is drawn in a first-person hand.

## Best Practices

1. Always use `MolangQueries.normalize()` when defining query constants
2. Define query constants as `public static final` fields
3. Register variables during initialization using `MolangParser.INSTANCE` — never instantiate a new `MolangParser`
4. Use memoized values unless a query really needs recalculating on every read
5. In animators, bind through a `MolangVariableRef` and create suppliers once, reading the current entity from a field, instead of creating new lambdas every frame
6. Keep query names descriptive and consistent
7. For simple per-entity values, `context().molangScope().set("v.name", value)` avoids registering anything
8. Use `temp.*` for scratch values inside an expression and `variable.*` only for state that must persist or be shared between keyframes