Skip to content

API Block Callbacks

Piggo41 edited this page Oct 12, 2026 · 8 revisions

Block callbacks

Lua API / Blocks / Callbacks

Each declaration below is an optional table with a required action = function(ctx) ... end. The argument is a block action context. Queries cannot mutate gameplay. Handler errors are reported and disable that handler for its current registration; query fallbacks preserve engine behavior, and failed interactions are denied.

Custom blocks dispatch their own callbacks. Callback overrides on existing Minecraft or mod content require the Java agent. Overrides additionally expose ctx:base().

On this page

onActivate

Runs when a player activates the block. Mutable context with player and possibly held stack. Return betamoon.callbackResults.handled to consume the interaction, callbackResults.pass/nil to continue, or callbackResults.deny to refuse and suppress fallback item use. The equivalent strings remain accepted.

onActivate = {
    action = function(ctx)
        return betamoon.callbackResults.handled
    end
}

onClick

Runs when a player clicks the block to begin mining. Mutable context with player. Use canBreak to control mining permission.

onClick = {
    action = function(ctx)
        betamoon.chat:send("Clicked block %d", ctx.id)
    end
}

canPlace

Queries whether placement at this location/face is permitted after static placement checks. Return boolean, or nil for the default result. Context is read-only; face is the clicked face.

canPlace = {
    action = function(ctx)
        return ctx.y < 100
    end
}

onPlaced

Notifies after placement by a living entity and orientation setup. Mutable context; entity identifies the placer and player is available for a player placer.

onPlaced = {
    action = function(ctx)
        betamoon.chat:send("Placed at %d", ctx.y)
    end
}

onAdded

Notifies when the block is added to the world. Mutable context; no player is implied.

onAdded = {
    action = function(ctx)
        betamoon.chat:send("Added block %d", ctx.id)
    end
}

onRemoved

Notifies removal/replacement. Identity and metadata may describe the old block. State reads can use captured metadata; writes requiring the original block fail after replacement.

onRemoved = {
    action = function(ctx)
        betamoon.chat:send("Removed block %d", ctx.id)
    end
}

onNeighborChanged

Notifies a neighboring change. Adds integer neighborId; mutable context.

onNeighborChanged = {
    action = function(ctx)
        local powered = ctx.redstone:isPowered()
    end
}

canBreak

Queries whether a player may break the block. Read-only context; return boolean or nil for default. This is a mining permission check, not the post-break notification.

canBreak = {
    action = function(ctx)
        return not ctx.player:isSneaking()
    end
}

onBroken

Notifies player destruction; describes the broken block and its captured metadata. Mutable context, but writes to a replaced block are invalid.

onBroken = {
    action = function(ctx)
        betamoon.chat:send("Broken block %d", ctx.id)
    end
}

onExploded

Notifies destruction by an explosion. No player is implied. Use getDrops for queried drops. A BetaMoon-created explosion adds ctx.explosion, a detached request snapshot with position, strength, resolved option values, and source when a live native source exists. Native Minecraft explosions leave this field nil.

onExploded = {
    action = function(ctx)
        local strength = ctx.explosion and ctx.explosion.strength or 0
        betamoon.chat:send("Exploded block %d at strength %.1f", ctx.id, strength)
    end
}

onEntityWalk

Notifies an entity walking over the block. Adds entity access; a player entity also supplies player access. Mutable.

onEntityWalk = {
    action = function(ctx)
        if ctx.entity:isPlayer() then
                ctx.entity:setVelocity(0, 0.4, 0)
            end
    end
}

onEntityCollide

Notifies an entity intersecting the block. Adds entity access. Mutable. Can run repeatedly while collision continues.

onEntityCollide = {
    action = function(ctx)
        local velocity = ctx.entity:getVelocity()
    end
}

getDrops

Queries replacement drops. Read-only context. Return any supported block-drop declaration, {} for no drops, or nil for declared/vanilla drops. This includes legacy entries, { table = ... }, and { pools = ... }. Do not spawn items from this query.

getDrops = {
    action = function(ctx)
        return { { item = 4, min = 1, max = 2 } }
    end
}

onTick and onDisplayTick

See Block ticks for declarations and their distinct world-access methods.

redstone.onInputChanged

See Input changes for per-face input snapshots.

Examples: Lifecycle callbacks, interactions and queries.

Clone this wiki locally