Spell¶
Represents a running Lua script in the game, providing methods for interacting with the world, entities, and events.
Example: Turning all barrels nearby into chests, keeping their items
for _, barrel in ipairs(spell:findBlockEntities({ block = "barrel", maxradius = 16 })) do
local items = barrel.nbt.Items
barrel:removeNbt("Items") -- or else a barrel spills its items when it's replaced
spell.pos = barrel.pos
spell.block = Block("chest")
spell.blockEntity:putNbt({ Items = items })
end
Fields¶
age: number — Read-Only¶
The age of the spell in game ticks.
biome: string — Read-Only¶
The biome ID at the spell’s current position (e.g., "plains", "forest", "ocean"). The value reflects the biome at spell.pos and changes as the spell moves.
block: Block — Read/Write¶
A copy of the block at the spell's position.
blockEntity: BlockEntity — Read-Only¶
A reference to the block entity at the spell's position, if any.
facing: CompassDirection — Read-Only¶
The compass direction this spell is facing.
forceChunk: boolean — Read/Write¶
Specifies whether the chunk containing this spell should stay loaded and ticking, as /forceload would keep it. The two rings of chunks around it are loaded too, the inner one with its blocks ticking, the outer one without any ticking; their blocks can be read and searched. Default is true.
forceChunkRadius: number — Read/Write¶
The number of chunks around this spell's chunk that stay loaded and ticking like the chunk itself, an integer from 0 to 8. The two loaded rings lie beyond them. It only has an effect while forceChunk is true, and it moves along with the spell. Only the spell's own chunk is loaded at once; the others load over the next ticks. Default is 0.
id: number — Read-Only¶
The ID of the spell.
lookVec: Vec3 — Read-Only¶
A copy of the direction vector in which the spell is looking.
name: string — Read/Write¶
The name of the spell.
owner: Entity — Read-Only¶
A reference to the entity that owns or cast this spell.
pitch: number — Read/Write¶
The pitch rotation angle of the spell.
pos: Vec3 — Read/Write¶
A copy of the position of the spell in the world.
server: Server — Read-Only¶
A reference to the Minecraft server.
tags: string[ ] — Read/Write¶
A copy of the tags of this spell, in the order they were added. Assigning a list replaces all tags. findSpells can search spells by tag. Default is none.
tickLimit: number — Read/Write¶
The per-tick execution budget for this spell, measured in Lua operations. When the budget is exhausted, the spell automatically yields and resumes next tick. Default is 50000. Increasing the value lets a spell do more work in one tick (potential TPS impact); lowering makes it yield more often for smoother pacing.
velocity: Vec3 — Read/Write¶
A copy of the velocity of the spell.
visible: boolean — Read/Write¶
Specifies whether this spell is visible to players. Default is false.
world: World — Read/Write¶
A reference to the world in which the spell exists.
yaw: number — Read/Write¶
The yaw rotation angle of the spell.
Methods¶
addTag(tag: string) → added: boolean¶
Adds a tag to this spell. Tags mark spells that belong together, e.g. all spells of a kind, so
that findSpells can find them.
Example
Parameters
- tag: string — The tag to add.
Returns
- added: boolean —
trueif the spell did not have the tag yet.
collect(...: string|string[ ]) → queue: EventQueue¶
Collects events matching the specified names into an event queue.
A queue gets an event after the interceptors of all spells have handled it, so with what they changed, whichever spell was cast first. A canceled event doesn't reach any queue.
Example
local queue = spell:collect("ChatMessageEvent", "PlayerJoinedEvent")
while true do
local event = queue:next()
if event then
print("Collected event:", event.name)
end
sleep(20)
end
Parameters
- ...: string|string[ ] — The names of events to collect, or lists of them.
Returns
- queue: EventQueue — The event queue collecting matching events.
copyStructure(oppositeCorner: Vec3, includeEntities?: boolean, ignoreBlockId?: string) → structure: Structure¶
Copies a box-shaped region of the world as a structure.
The region is defined by the spell's position and the opposite corner.
The copied structure can be pasted into the world, or saved with Structure:save.
Example: Copy and paste a structure
local oppositeCorner = spell.pos + Vec3(10, 5, 10)
local struct = spell:copyStructure(oppositeCorner)
spell.pos = spell.pos + Vec3(0, 0, 15)
spell:pasteStructure(struct)
Example: Copy and save a structure
local oppositeCorner = spell.pos + Vec3(10, 10, 10)
local struct = spell:copyStructure(oppositeCorner)
local filepath = struct:save("mickkay:arena")
print("Structure saved at " .. filepath)
Parameters
- oppositeCorner: Vec3 — The corner position opposite to the spell's current position. Defines the region to copy.
- includeEntities?: boolean — Copy entities within the region. Default is false.
- ignoreBlockId?: string — Block ID to ignore when copying. Default is none.
Returns
- structure: Structure — The copied structure object.
evaluate(text: string) → result: string¶
Evaluates the given text using the Placeholder API.
This function requires the Placeholder API jar to be present in the mods folder.
Example
local text = "Number of players online: %world:player_count%"
local value = spell:evaluate(text)
print(value)
Parameters
- text: string — The text to evaluate using the Placeholder API.
Returns
- result: string — The evaluated text with placeholders replaced.
execute(command: string, trace?: Trace) → result: number¶
Executes a Minecraft command on behalf of this spell.
By default, the command's output is sent to the spell's command source.
To inspect the output programmatically instead, you can pass a Trace object to capture it.
The return value is the command result value as defined by the Minecraft command system: usually the number of entities or blocks affected by the command.
Example
Example with Trace
local trace = Trace()
local result = spell:execute("/data get entity @p", trace)
print("Command returned: " .. result)
print("Command output:\n" .. trace.content)
Parameters
- command: string — The command to execute.
- trace?: Trace — A
Traceobject to collect the command's output.
Returns
- result: number — The command result value, usually representing the number of entities or blocks affected.
executeSilent(command: string, trace?: Trace) → result: number¶
Executes a Minecraft command silently on behalf of this spell.
In contrast to spell:execute, this version does not forward the command's output to the spell’s command source.
You can use a Trace object to capture the output programmatically.
The return value is the command result value as defined by the Minecraft command system: usually the number of entities or blocks affected by the command.
Example
Example with Trace
local trace = Trace()
local result = spell:executeSilent("/data get entity @p", trace)
print("Command returned: " .. result)
print("Command output:\n" .. trace.content)
Parameters
- command: string — The command to execute.
- trace?: Trace — A
Traceobject to collect the command's output.
Returns
- result: number — The command result value, usually representing the number of entities or blocks affected.
findBlockEntities(criteria: FindBlockEntitiesCriteria) → list: BlockEntity[ ]¶
Finds the block entities within a sphere around this spell, nearest first, optionally only those whose block matches the given block.
Block entities are the blocks that hold more than a block state, like chests, furnaces, signs or
spawners. Only loaded chunks are searched; see findBlocks. The distance is measured to the
center of the block.
Example: The nearest chest or barrel
local storage = spell:findBlockEntities({ block = { "chest", "trapped_chest", "barrel" }, maxradius = 16, limit = 1 })
if #storage > 0 then
print("Storage at " .. str(storage[1].pos) .. ": " .. str(storage[1].nbt.Items))
end
Parameters
- criteria: FindBlockEntitiesCriteria — The search criteria.
Returns
- list: BlockEntity[ ] — References to the block entities found, nearest first.
findBlocks(criteria: FindBlocksCriteria) → positions: Vec3[ ]¶
Finds the positions of the blocks within a sphere around this spell that match the given block, nearest first.
Only loaded chunks are searched: the blocks of a chunk nobody keeps loaded are not found. A spell
keeps the chunks around itself loaded (see forceChunk and forceChunkRadius), so moving the
spell to where to search is usually enough.
The distance of a block is measured from the spell's position to the block's center. Blocks at the same distance come in a fixed order, so the same search always gives the same result.
Example: The nearest log
local logs = spell:findBlocks({ block = "#minecraft:logs", maxradius = 32, limit = 1 })
if #logs > 0 then
spell.pos = logs[1]
print("The nearest log is a " .. spell.block.type.name)
end
Example: All iron ore nearby
for _, pos in ipairs(spell:findBlocks({ block = "#minecraft:iron_ores", maxradius = 16 })) do
print(pos)
end
Parameters
- criteria: FindBlocksCriteria — The search criteria.
Returns
- positions: Vec3[ ] — Copies of the positions of the blocks found, nearest first. Their coordinates are whole numbers, as in
BlockHitResult.blockPos.
findEntities(selector: string) → list: Entity[ ]¶
Finds and returns a list of entities matching the specified selector.
Example
local nearbyZombies = spell:findEntities("@e[type=zombie,distance=..10]")
for _, entity in ipairs(nearbyZombies) do
print("Found entity:", entity.name)
end
Parameters
- selector: string — The selector used to find entities (e.g., "@e[type=zombie,distance=..10]").
Returns
- list: Entity[ ] — A table of references to entities that match the selector criteria.
findSpells(criteria?: SpellCriteria) → list: Spell[ ]¶
Finds and returns a list of spells that match the given search criteria.
Example: Search by name:
local spellsByName = spell:findSpells({ name = "My Spell" })
for _, s in ipairs(spellsByName) do
print("Found spell:", s.name)
end
Example: Search within a radius by owner:
local nearbySpells = spell:findSpells({ owner = "MickKay", maxradius = 50, excludeSelf = true })
for _, s in ipairs(nearbySpells) do
print("Nearby spell owned by MickKay:", s.name)
end
Example: Search by spell ID:
local specificSpell = spell:findSpells({ sid = 1029 })
if specificSpell[1] then
print("Found spell with ID 1029:", specificSpell[1].name)
else
print("No spell found with ID 1029.")
end
Parameters
- criteria?: SpellCriteria — The search criteria. Defaults to none, which finds all spells.
Returns
- list: Spell[ ] — A table of references to spells that match the criteria.
fire(name: string, data?: table) → proceed: boolean¶
Fires a custom event with the specified name and optional data.
This method triggers a CustomEvent that can be intercepted or collected by other spells.
If any interceptor returns false, the event is considered canceled, and this method returns false.
If the optional data table is provided, it is passed by reference to all receivers. That means
interceptors and collectors can directly mutate its contents, and the changes will be reflected
in the original table after the event is fired.
Example: Event without data
local proceed = spell:fire("CustomSpellEvent")
if proceed then
print("Event handled without cancellation.")
else
print("Event was canceled.")
end
Example: Event with shared data
local payload = { message = "Hello World!", count = 1 }
local proceed = spell:fire("CustomSpellEvent", payload)
if not proceed then
print("Event was canceled.")
end
print("Modified count:", payload.count)
Receiver example
In this example, after spell:fire(...), the payload.count will be incremented by the receiver.
Parameters
- name: string — The name of the custom event.
- data?: table — A table passed to event handlers; can be modified by them.
Returns
- proceed: boolean —
trueif the event was not canceled;falseotherwise.
intercept(names: string|string[ ], callback: function) → interceptor: EventInterceptor¶
Intercepts events matching the specified names and handles them using a callback.
To cancel an event, return false from within the callback.
The interceptor stays active only while the spell is running. If the spell ends, the interceptor stops automatically.
The interceptors of all spells get an event before any event queue does, in the order the spells were cast. Once one has canceled the event, nothing else gets it.
The callback runs at once, in the middle of what fired the event, before the game goes on, so
that it can still cancel it. It can't wait (no sleep), and what it does there, like writing in
the chat, running a command or breaking a block, fires further events at once, which other
interceptors get before the callback has returned. An event that the callback causes itself,
directly or through other events, doesn't reach it again while it is still handling an event of
that name: so a callback that answers each chat message in the chat doesn't call itself without
end. To react to an event rather than decide about it, spell:collect is the better choice: the
spell gets the events from the queue when it is its turn, one after the other, and may wait.
Example
local interceptor = spell:intercept("BeforePlayerBlockBreakEvent", function(evt)
local blockName = evt.block.type.id
if blockName == "short_grass" then
spell.pos = evt.pos:floor() + Vec3(0.5, 0, 0.5)
spell:summon("pig")
return false
end
return true
end)
-- Keep the spell running so the interceptor remains active
while true do
sleep(20)
end
Parameters
- names: string|string[ ] — The name of the event to intercept, or a list of names.
- callback: function — A function that handles events. Return
trueto allow,falseto cancel.
Returns
- interceptor: EventInterceptor — The reference to the interceptor that manages the event interception.
kill()¶
Terminates this spell immediately.
Example: Stopping all spells of a name
lookAt(target: Entity|Vec3)¶
Turns the spell so that it looks at the target: sets its yaw and pitch. A raycast from
the spell then leads there. Looking straight up or down, the spell keeps its yaw.
Example
spell:lookAt(spell.owner.eyePos)
local hit = spell:raycastBlock(20)
print(hit and "A block is in the way." or "Nothing between us.")
Parameters
move(direction: MoveDirection, distance?: number)¶
Moves this spell's position in the specified direction by a given distance.
Accepts absolute directions ("north", "south", "east", "west", "up", "down") and relative directions ("forward", "back", "left", "right"). Relative directions use the spell's current yaw rotation.
The distance is measured in blocks. If omitted, the spell moves by 1 block.
Example: Move 5 blocks north
Example: Move up by 2 blocks
Example: Move forward in the direction the spell is facing
Parameters
- direction: MoveDirection — The direction to move.
- distance?: number — The distance to move. Defaults to 1 block.
pasteStructure(structure: Structure, originPos?: Vec3, ignoreBlockIds?: string[ ])¶
Pastes a structure into the world at the spell's position.
By setting originPos, you choose which block in the structure’s internal coordinate system will be placed at the spell’s position.
If not provided, (0, 0, 0) is used.
Before placement, the structure is rotated clockwise around originPos to match the spell’s facing property:
"south" = 0°, "east" = 90°, "west" = -90°, "north" = 180°.
Example: Paste a loaded structure (default origin)
Example: Paste using a different origin block
-- Use the block at (5, 0, 0) in the structure as origin and pivot, placing it at spell.pos
spell:pasteStructure(struct, Vec3(5, 0, 0))
Example: Ignore certain blocks when pasting
Parameters
- structure: Structure — The structure to paste.
- originPos?: Vec3 — Block in the structure to use as the origin and rotation pivot. Default is Vec3(0,0,0).
- ignoreBlockIds?: string[ ] — The ids of the blocks in the structure to leave out, like "air" or "minecraft:structure_void". Raises an error for an unknown id. Defaults to none.
raycast(maxDistance: number) → hit: HitResult?¶
Issues a raycast from this spell’s position and returns the first block or entity hit. See also Entity:raycast.
Example
Parameters
- maxDistance: number — The maximum distance to cast the ray.
Returns
- hit: HitResult? — The result of the raycast, indicating the first block or entity hit, or
nilif nothing was hit.
raycastBlock(maxDistance: number) → hit: BlockHitResult?¶
Issues a raycast from this spell’s position and returns the first block hit. See also Entity:raycastBlock.
Example
local hit = spell:raycastBlock(20)
if hit then
spell.pos = hit.blockPos
spell.block = Block("glowstone")
end
Parameters
- maxDistance: number — The maximum distance to cast the ray.
Returns
- hit: BlockHitResult? — The result of the raycast, indicating the block hit, or
nilif no block was hit.
raycastEntity(maxDistance: number) → hit: EntityHitResult?¶
Issues a raycast from this spell’s position and returns the first entity hit. See also Entity:raycastEntity.
Example
Parameters
- maxDistance: number — The maximum distance to cast the ray.
Returns
- hit: EntityHitResult? — The result of the raycast, indicating the entity hit, or
nilif no entity was hit.
removeTag(tag: string) → removed: boolean¶
Removes a tag from this spell.
Example
Parameters
- tag: string — The tag to remove.
Returns
- removed: boolean —
trueif the spell had the tag.
setYaw(direction: CompassDirection)¶
Sets the spell's yaw so that it faces the given compass direction.
The spell’s yaw property will be updated to the angle corresponding to the direction.
Example
Parameters
- direction: CompassDirection — The compass direction.
summon(id: string, nbt?: table) → entity: Entity¶
Summons an entity with the given entity ID at the spell's position. Optionally, merges a subset of NBT data into the newly created entity.
As with /summon, a mob summoned without NBT gets the random traits of a natural spawn (a
sheep's color, a zombie's equipment, a baby now and then), and a mob summoned with NBT does not:
then the NBT decides, and what it leaves out stays at the defaults.
Example
local pig = spell:summon("pig", { CustomName = { text = "Grumpy Pig", italic = true, color = "gold" } })
print("Summoned entity:", pig.name)
Parameters
- id: string — The ID of the entity to summon.
- nbt?: table — NBT data to merge into the entity.
Returns
- entity: Entity — A reference to the summoned entity. The returned entity may be a subclass of Entity.