Skip to content

Spell

Represents a running Lua script in the game, providing methods for interacting with the world, entities, and events.

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

spell:addTag("miner")
for _, s in ipairs(spell:findSpells({ tag = "miner" })) do
  print(s.name)
end

Parameters

  • tag: string — The tag to add.

Returns

  • added: boolean — true if the spell did not have the tag yet.

collect(...: string) → queue: EventQueue

Collects events matching the specified names into an event 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 — The names of events to collect.

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 to the server's filesystem.

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 = spell.server:saveStructure("arena", struct)
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

spell:execute("say Hello, World!")

Example with Trace

local trace = Trace:new()
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 Trace object 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

spell:executeSilent("say Hello, World!")

Example with Trace

local trace = Trace:new()
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 Trace object 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

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

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

spell:intercept({ "CustomSpellEvent" }, function(event)
  event.data.count = event.data.count + 1
end)

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 — true if the event was not canceled; false otherwise.

intercept(names: table, 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.

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", { Pos = evt.pos, Saddle = true })
      return false
  end
  return true
end)

-- Keep the spell running so the interceptor remains active
while true do
  sleep(20)
end

Parameters

  • names: table — A table of event names to intercept.
  • callback: function — A function that handles events. Return true to allow, false to cancel.

Returns

  • interceptor: EventInterceptor — The reference to the interceptor that manages the event interception.

kill()

Terminates this spell immediately.

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

spell:move("north", 5)

Example: Move up by 2 blocks

spell:move("up", 2)

Example: Move forward in the direction the spell is facing

spell:move("forward", 3)

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)

local struct = spell.server:loadStructure("arena")
spell:pasteStructure(struct)

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

spell:pasteStructure(struct, nil, { "minecraft:air" })

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". 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.

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.

raycastBlock(maxDistance: number) → hit: BlockHitResult?

Issues a raycast from this spell’s position and returns the first block hit. See also Entity:raycastBlock.

Parameters

  • maxDistance: number — The maximum distance to cast the ray.

Returns

  • hit: BlockHitResult? — The result of the raycast, indicating the block hit.

raycastEntity(maxDistance: number) → hit: EntityHitResult?

Issues a raycast from this spell’s position and returns the first entity hit. See also Entity:raycastEntity.

Parameters

  • maxDistance: number — The maximum distance to cast the ray.

Returns

  • hit: EntityHitResult? — The result of the raycast, indicating the entity hit.

removeTag(tag: string) → removed: boolean

Removes a tag from this spell.

Example

spell:removeTag("miner")

Parameters

  • tag: string — The tag to remove.

Returns

  • removed: boolean — true if 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

spell:setYaw("north")
print(spell.yaw) -- prints 180

Parameters

lookAt(pos: Vec3)

Turns the spell so that it looks at the position: 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

  • pos: Vec3 — The position to look at.

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.

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.