Custom Components via Datapacks
Build a Spell loads its spell effects, modifiers, delivery methods, and combos from datapacks. Every built-in component ships as bundled JSON in exactly the format described here, so a datapack can retune a built-in or author a brand-new component with the same files the mod uses itself.
Component data is server-authoritative: the server loads the definitions and syncs the display metadata (icon, colour, cost, name) of any datapack-authored effects down to each client so they appear in the Spell Builder. Actual behaviour always runs on the server.
Editing a component’s behaviour requires a server reload (/reload) or a restart.
Removing a datapack that defined a component you’ve already used in a saved spell
is safe: the unknown id is skipped (and logged) rather than crashing the save.
File layout
Place definitions under your namespace in one of the four component folders:
data/<namespace>/spell_effects/<id>.json
data/<namespace>/spell_modifiers/<id>.json
data/<namespace>/spell_deliveries/<id>.json
data/<namespace>/spell_combos/<id>.json
The file name (minus .json) is the component’s id. To override a built-in,
reuse its namespace and id (for example data/buildaspell/spell_effects/damage.json).
To add a new component, use your own namespace
(for example data/mypack/spell_effects/frost_nova.json).
Behaviour primitives
A component’s behaviour is an ordered list of primitives: small, typed units
the mod knows how to execute. Each entry is dispatched on its type field:
{ "type": "buildaspell:builtin_effect", "effect": "damage" }
Two primitive types ship today:
| Type | Param | Does |
|---|---|---|
buildaspell:builtin_effect |
effect — a built-in effect id |
Runs that built-in effect’s behaviour unchanged |
buildaspell:builtin_combo |
combo — a built-in combo id |
Runs that built-in combo’s behaviour unchanged |
These bridges are how every shipped component routes through the datapack system while its Java behaviour stays identical. You author a new effect today by composing existing built-in behaviours: the list runs top to bottom.
Fully decomposed primitives (standalone area_damage, apply_mob_effect,
knockback, summon, particles, sound, …) are planned, which will let new
components be built from scratch rather than only by reusing built-in behaviours.
Spell effects
spell_effects/<id>.json: a behavior list (required) and an optional display
block.
A built-in effect simply references itself:
{
"behavior": [
{ "type": "buildaspell:builtin_effect", "effect": "damage" }
]
}
A new effect composes built-in behaviours and supplies display metadata so the builder can render and price it:
{
"behavior": [
{ "type": "buildaspell:builtin_effect", "effect": "damage" },
{ "type": "buildaspell:builtin_effect", "effect": "ignite" }
],
"display": {
"icon": "minecraft:blaze_powder",
"color": -3407872,
"cost": 25.0,
"name": "effect.mypack.smite"
}
}
Datapack-authored effects (those whose id is not a built-in) are always available in the Spell Builder: they bypass the rune-unlock progression that gates the built-in effects.
Modifiers and delivery methods
spell_modifiers/<id>.json and spell_deliveries/<id>.json share the same shape:
an optional params map of numeric scalars and an optional display block.
{
"params": { "range_per_stack": 1.0 },
"display": { "icon": "minecraft:firework_star", "cost": 15.0 }
}
params carries the numbers a modifier or delivery feeds into spell stats: for
example range_per_stack for an area modifier. An empty file ({}) is valid and
falls back to the mod’s configured values. Most built-ins ship as {} and read
their tuning from the server config.
Behaviour for brand-new modifiers and deliveries is not yet data-authored: only
their stats (params) and display are. Built-in modifier/delivery behaviour can
be retuned via params/config, but creating a wholly new modifier behaviour still
requires the planned primitive set.
Combos
spell_combos/<id>.json defines a combo’s match requirements and behaviour:
| Field | Required | Meaning |
|---|---|---|
required_effects |
yes | The exact set of effect ids the spell must contain |
min_components |
yes | Minimum total component count to qualify |
behavior |
yes | Primitives to run when the combo matches |
required_modifiers |
no | Minimum count of each named modifier (default none) |
modifier_caps |
no | Per-modifier hard caps used for mana refunds (default none) |
{
"required_effects": ["<effect_id>", "<effect_id>"],
"min_components": 3,
"required_modifiers": { "<modifier_id>": 1 },
"modifier_caps": { "<modifier_id>": 2 },
"behavior": [
{ "type": "buildaspell:builtin_combo", "combo": "<combo_id>" }
]
}
Combos are matched against the spell’s exact effect set, so order doesn’t matter but the set must match precisely. When several combos could match, they are evaluated in id order and the first match wins.
The recipes for the built-in combos are intentionally left undocumented: discovering them is part of the game. The format above is everything you need to author your own; fill in your own effect, modifier, and combo ids.
The display block
Every display field is optional; omit any you don’t need.
| Field | Type | Falls back to |
|---|---|---|
icon |
item id | minecraft:paper |
color |
ARGB integer | the per-type accent colour |
cost |
number (base mana) | 0 |
name |
translation key | the component id |
Applying a datapack
Drop the pack into a world’s datapacks/ folder (or use a global datapack loader
such as OpenLoader to apply it to every world), then run /reload. On reload the
server reparses the definitions and resyncs datapack effects to connected clients;
the new or changed components appear in the Spell Builder immediately.