Repository navigation
API Block 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
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
}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
}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
}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
}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
}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
}Notifies a neighboring change. Adds integer neighborId; mutable context.
onNeighborChanged = {
action = function(ctx)
local powered = ctx.redstone:isPowered()
end
}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
}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
}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
}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
}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
}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
}See Block ticks for declarations and their distinct world-access methods.
See Input changes for per-face input snapshots.
Examples: Lifecycle callbacks, interactions and queries.
- Installation
- Install scripts
- Getting started
- VS Code and LuaLS
- Examples
- Reload and compatibility
- Troubleshooting
- Changelog
Scripts and shared values
- Script lifecycle
- Packaged Lua mods
- Modules
- References and stacks
- Queries
- Overrides
- Minecraft constants
- Chat and positions
- Structured data
- Script configuration
- Particles
Blocks and items
- Multiblocks
- Blocks
- Block state and placement
- Block shapes and rendering
- Block callbacks
- Block ticks and redstone
- Items
- Fluids
- Item callbacks
- Tools and armor
- Materials
- Textures
Entities
- Entities
- Entity access and movement
- Entity lifecycle and data
- Entity health and loot
- Entity inventories and relationships
- Projectiles and pickups
- Entity presentation and sounds
- Living entities and AI
- Entity parts and sensors
Assets and audio
- Assets
- Models and animations
- Built-in Minecraft models
- Model appearances
- Blockbench workflow
- Audio
- Texture-pack overrides
Events and world actions
World generation
World systems
Inventories and screens
Recipes