Skip to main content

Build the Aura Environment

Define Aura and Realms left you with one zone that covers the whole Overworld with the same amount of aura. This page makes the world matter: denser regions, spirit stone veins, items you can burn while meditating, and the client-side presentation that tells a player where they are standing.

The previous tutorial must be finished first — everything here extends the same example:qi resource.

How the Numbers Fit Together

Two different numbers are involved, and confusing them is the usual source of surprise:

NumberWhere it livesWhat it means
Chunk inventoryThe mxt:aura chunk attachmentWhat can actually be consumed at this position. Shared by every player in the chunk, regenerated by regen_per_tick.
Environment concentrationComputed from the matching zoneWhat the template says is here. Fluctuation and noise act on it, and it is what the client shows.

When a chunk is initialised, each resource starts at max(0, (amount + noise) / 10 - 5), where noise is the Perlin value of the template (or 0 when noise is off). The bare amount is therefore a base value ten times larger than the concentration it produces — a template with amount: 200 starts around 15. Capacity comes from max, which is resolved from that initial value unless you write a fixed number.

Cultivation progress and the aura a player gains are multiplied by the concentration multiplier at their position: concentration / maximum for a finite maximum, and concentration / (concentration + 1) for {"type": "mxt:unlimited"}.

Step 1 — A Denser Biome Zone

Two overlapping templates are resolved level by level: biome < dimension < permanent manual area < formation. A later level replaces the aura values, element values, rules and display template of the earlier one entirely. Inside one level, the highest priority wins, and equal priorities are broken by taking the template with the lower ID, so the result is always reproducible.

That is why the two zones here are both biome-level: the forest template simply outranks the general one where it applies.

// data/example/mxt/aura_zone/misty_valley.json
{
"aura": {
"example:qi": {
"amount": 400,
"max": {"type": "mxt:initial_multiplier", "multiplier": 1.5},
"regen_per_tick": 0.1,
"color": "#7FE3C4"
}
},
"aura_kinds": ["example:common_aura"],
"biomes": ["#minecraft:is_forest"],
"priority": 10,
"distribution": "realm_weighted",
"cultivate_condition": {
"type": "mxt:aura_range",
"aura": {"example:qi": {"min": 5, "max": 100000}}
},
"fluctuation": {
"enable": true,
"cycle_type": "day",
"amplitude": 0.3,
"offset_tick": 0
},
"noise": {
"enable": true,
"seed": 739430,
"scale": 640.0,
"amplitude": 5.0
},
"element_fit_bonus": 0.25,
"element_conflict_penalty": 0.2,
"client_render": {
"fog_color": "#7FE3C4",
"render_distance": 64,
"fog_strength": 0.35
},
"client_hud": {
"stored_aura": {"maximum": 60.0, "bar_index": 1, "anchor": "left", "order": 4},
"sensed_concentration": {"maximum": 60.0, "bar_index": 2, "anchor": "left", "order": 5}
}
}
FieldEffect
auraPer-resource inventory: amount, max, regen_per_tick and the environment color. max accepts a number, mxt:fixed, mxt:initial_multiplier or mxt:unlimited.
aura_kindsThe aura kinds present here. They are matched as a set against cultivate_action.aura_kinds and alchemy_recipe.aura_kinds; they are markers, not sources of value.
priorityUsed only against other templates of the same level.
distributionrandom, equal or realm_weighted; it decides who gets how much when the chunk inventory cannot satisfy everyone. realm_weighted uses aura_share_weight from each player's realm stage.
cultivate_conditionAn entity condition the environment must satisfy for cultivation. Note that mxt:aura_range requires max on every resource entry.
fluctuationMultiplies the concentration by 1 + amplitude * sin(2π * (time + offset_tick) / cycle), with a 24000-tick day cycle or a 192000-tick moon cycle. It only affects the queried concentration, never the stored inventory.
noiseA seeded, reproducible Perlin offset so the map has gradients instead of hard borders. scale around 640960 is recommended; amplitude: 5 gives roughly a -5..5 disturbance before the / 10 - 5 transform.
element_fit_bonus / element_conflict_penaltyMultipliers applied when a player's spirit root element matches or clashes with the environment.
client_renderFog colour, the distance it is applied over (8..256) and how strongly it replaces the vanilla fog (0..1). The strength is also scaled by the concentration, so thin aura looks fainter.
client_hudTwo optional bars: stored_aura reads the chunk inventory, sensed_concentration reads the environment template. They are drawn above the resource bars of the same side.

Rules

The rules object adds environment policy:

"rules": {
"cultivate_suppress": false,
"tribulation_modify": 0.15
}

cultivate_suppress aborts cultivation that is already running, and tribulation_modify injects the formula variable aura_tribulation_modifier into tribulation formulas. The other three fields — spirit_plant_bonus, alchemy_env_bonus and natural_spawn_herb — are parsed but not yet connected to a consumer, so treat them as not implemented.

Step 2 — Aura From Blocks

A spirit stone vein should be worth more than the ground it sits in.

// data/example/mxt/block_aura/spirit_stone_ore.json
{
"blocks": ["mxt:spirit_stone_ore", "mxt:spirit_stone_block"],
"aura": {
"example:qi": {"amount": 5.0, "max": 5.0, "regen_per_tick": 0.01}
},
"aura_kinds": ["example:common_aura"]
}
  • blocks takes block IDs and block tags; every matching block in a chunk contributes once.
  • The contribution does not consume the environment maximum: it raises the chunk's effective capacity by the same amount. An environment maximum of 30 with 30 points of ore becomes 60.
  • Queries look at a 7x7x7 range of sub-chunks: the inner 3x3x3 uses real block positions, the outer ring approximates with sub-chunk centres, and all of it decays by 1 / max(1, distance²).
  • The cache is rebuilt when a chunk loads, when a block changes and when the data tables are loaded, and the interval is aura.block_aura_tick_interval in config/mxt-server.json (default 10 ticks, 1..1200).

A common pattern is to make the natural template almost empty and let blocks provide the aura:

"aura": {
"example:qi": {"amount": 0, "max": {"type": "mxt:unlimited"}, "regen_per_tick": 0}
},
"noise": {"enable": true, "seed": 739430, "scale": 640.0, "amplitude": 5.0}

With amount: 0, most chunks sit at 0 after the / 10 - 5 transform, and only places with actual aura-emitting blocks stand out.

Step 3 — Aura From Items

item_aura turns an item into cultivation fuel: while the player cultivates, the stack is drained tick by tick and its aura is released into the resource bar of the current realm.

// data/example/mxt/item_aura/spirit_stone.json
{
"items": ["mxt:spirit_stone", "#example:spirit_fuel"],
"type": "example:qi",
"aura": 100,
"consume_speed": "0.5 + caster_level * 0.05",
"release_speed": 2,
"exhausted_action": {"type": "mxt:no_op"}
}
  • items is the usual item matcher, so one file can cover a whole tag of fuel items.
  • type is the resource that receives the released aura — not an element.
  • aura is the total per item, written into a server-side mxt:item_aura component on the stack when processing starts; the whole stack moves into the mxt:float_holding_item attachment for the duration.
  • Each tick the definition matched at that moment subtracts consume_speed × stack size from the remaining aura and charges release_speed × stack size into the realm's resource bar. Holding more items drains faster but lasts the same number of ticks.
  • A half-used stack is resumed before a fresh one is taken, and fresh stacks are taken in main hand, off hand, inventory order. When cultivation stops, the player logs out or dies, the stack is returned unchanged.
  • On exhaustion the item is removed and result_stack (if configured) is given back. Items implementing SpiritItemAccess behave differently: they are charged and drained in place instead of being consumed.
note

The client does not draw a fuel bar, and never consumes items on its own.

Step 4 — Where It Shows Up

PlaceWhat it shows
client_hud.stored_auraThe chunk inventory, as a real value that goes up and down with cultivation.
client_hud.sensed_concentrationThe environment template at the current position, including fluctuation and noise.
Resource bars with "context": "mxt:environment_concentration" / "mxt:actual_concentration"The same two numbers, but labelled after the resource, so resource.example.qi becomes environmental or actual aura concentration.
Fogclient_render, scaled by concentration.
ParticlesThe optional particle object on the template, refreshed every 5 ticks.

actual includes every source — template, chunk inventory, block aura and formations — while environment is only the template. The server syncs the position aura every aura.sync_interval ticks (config/mxt-server.json, 5 by default) and the client only draws the snapshot.

On the command line:

/mxt aura query → every resource at your feet, with its element marker
/mxt aura query example:qi → one resource
/mxt aura vein → the size and tier of the connected spirit stone vein you stand on
/mxt aura cache clear 8 → rebuild the cached aura of nearby chunks (radius in chunks, 0..32)

Step 5 — Areas From a Script

Biomes and dimensions cover the static world. For anything that has to be created at runtime — a blessing placed by a quest, a sect's territory, a temporary field — use the KubeJS bridge:

// kubejs/server_scripts/mxt_areas.js
const area = MxtAura.addBox(
player.level, 'example:misty_valley',
0, 64, 0, // minimum corner
64, 128, 64, // maximum corner
10 // priority
)
console.info(`Created aura area ${area}`)

// Read the resolved aura at a position, including every source.
const aura = MxtAura.get(player.level, player.blockPosition)
console.info(`Concentration: ${aura.concentration()}, maximum: ${aura.maximum()}`)

// Later, or from another script:
// MxtAura.remove(player.level, area)

addBox needs a server level and a loaded aura_zone ID, and it returns the generated area ID. Manual areas are saved to the world, are the level above dimension bindings, and among themselves are resolved by priority. MxtAura.get is read-only and works on the client too, where it returns whatever state the client has received.

MxtEvents.auraZone fires with enter, leave, tick and override; override is the formation hand-off and can be cancelled to refuse it:

MxtEvents.auraZone(event => {
if (event.getKind() === 'override' && event.getConcentration() < 20) event.cancel()
})

Formations can also carry their own zone, which is the top level of the resolution order:

{
"structure_template": "example:gathering_array",
"radius": 8,
"max_bonus": {"example:qi": 50},
"aura_zone": "example:misty_valley"
}

Step 6 — Verify

Load the world again — these are data pack registries, so /reload does not pick them up — then run:

(load the world again)
/mxt registries validate
/mxt aura query example:qi → a forest should read higher than a plains
  1. Stand in a forest during the day and check /mxt aura query; sleep to night and check again. The value moved by up to ±30%, because of fluctuation.
  2. Walk a few hundred blocks in one direction. The value drifts smoothly, because of noise.
  3. Stand on spirit stone ore and run /mxt aura vein, then compare /mxt aura query before and after mining it out. The removable part is the block contribution.
  4. Cultivate while holding spirit stones. The bar fills noticeably faster than with empty hands, and the stack shrinks.
  5. If the fog is invisible, remember that fog_strength is multiplied by the concentration — a weak zone produces weak fog.

Common Mistakes

SymptomCause
The zone never appliesIts biomes/dimensions are empty, and nothing references it. An empty list means "only through a manual area or a formation".
A specific zone is ignoredA dimension-level template outranks every biome-level one. Give the specific zone the same level as the general zone and a higher priority.
Aura is ten times weaker than amount suggestsamount is a base value: the initial concentration is amount / 10 - 5 before noise.
Block aura seems to do nothingIt adds capacity, not a visible concentration, to a chunk whose environment maximum is already high. Lower the template's amount and let blocks carry the difference.
Aura keeps resetting to the template valueFluctuation, noise and regeneration all recompute the template; the stored inventory only changes through cultivation, item fuel and regeneration.

Next