Skip to content

Events Reference

Ceremony scripts react to the game world through events. Every time a block breaks, a player joins, an entity dies, or a Cobblemon is captured, an event fires. Your scripts subscribe to these events with callbacks, and Ceremony handles the rest.


Use Events.on() to subscribe to an event. It returns a subscription ID that you can later pass to Events.off() to unsubscribe.

// Subscribe to an event
const id = Events.on('blockBreak', (player, pos, state, level) => {
Logger.info('Block broken by {} at {}', player.getName().getString(), pos);
});
// Later, unsubscribe
Events.off(id);

Many events come in pairs: a before variant and an after variant.

PatternTimingCancellableExample
eventNameBeforeBefore the action happensYesblockBreakBefore
eventNameAfter the action happenedNoblockBreak
eventNameCanceledAfter a before-event was cancelledNoblockBreakCanceled

Before events let you prevent the action from happening by returning false (or a falsy value) from the callback:

Events.on('blockBreakBefore', (player, pos, state, level) => {
// Prevent breaking diamond ore
if (state.getBlock().toString().includes('diamond_ore')) {
player.sendSystemMessage(
Component.literal('You cannot break diamond ore here!')
);
return false; // Cancel the block break
}
return true; // Allow everything else
});

After events fire once the action is complete. They cannot be cancelled — the action already happened.

Events.on('blockBreak', (player, pos, state, level) => {
// React to the block that was already broken
Logger.info('{} broke a block at {}', player.getName().getString(), pos);
});

Event NameCallback SignatureDescription
blockBreak(player, pos, state, level)After a block is broken
blockBreakBefore(player, pos, state, level)Before a block is broken (cancellable)
blockBreakCanceled(player, pos, state, level)After a block break was cancelled
attackBlock(player, pos, direction, level)Player left-clicks a block
useBlock(player, pos, hand, hitResult, level)Player right-clicks a block
useItem(player, hand, stack, level)Player right-clicks with an item
blockEntityLoad(blockEntity, level)A block entity is loaded into the world
blockEntityUnload(blockEntity, level)A block entity is unloaded from the world
ParameterTypeDescription
playerServerPlayerThe player performing the action
posBlockPosThe block position (pos.getX(), pos.getY(), pos.getZ())
stateBlockStateThe block state (use state.getBlock() for the block type)
levelServerLevelThe world/dimension
directionDirectionThe face of the block that was clicked
handInteractionHandMAIN_HAND or OFF_HAND
hitResultBlockHitResultDetailed hit information (exact position, face, etc.)
stackItemStackThe item stack used
blockEntityBlockEntityThe block entity (chest, sign, etc.)

Event NameCallback SignatureDescription
attackEntity(player, entity, hand, level)Player left-clicks an entity
useEntity(player, entity, hand, hitResult, level)Player right-clicks an entity
Events.on('useEntity', (player, entity, hand, hitResult, level) => {
const name = entity.getName().getString();
Logger.info('{} interacted with {}', player.getName().getString(), name);
});

Event NameCallback SignatureDescription
playerJoin(player)Player joins the server
playerLeave(player)Player disconnects from the server
playerRespawn(oldPlayer, newPlayer, alive)After a player respawns
playerCopyData(oldPlayer, newPlayer, alive)Data copy on respawn or dimension change
playerChangeDimension(player, origin, destination)After a player changes dimension
ParameterTypeDescription
playerServerPlayerThe player instance
oldPlayerServerPlayerThe player instance before respawn/copy
newPlayerServerPlayerThe new player instance after respawn/copy
alivebooleantrue if the player was alive (e.g., dimension change), false if they died
originResourceKeyThe dimension they came from
destinationResourceKeyThe dimension they went to

Event NameCallback SignatureDescription
entityLoad(entity, level)Entity added to the world
entityUnload(entity, level)Entity removed from the world
entityChangeDimension(originalEntity, newEntity, origin, destination)Entity changes dimension
entityDamage(entity, source, amount)Living entity about to take damage
entityDeath(entity, source, amount)Living entity about to die
entityDeathAfter(entity, source)Living entity has died
entityKilledOther(level, killer, killed)An entity kills another entity
ParameterTypeDescription
entityEntity / LivingEntityThe entity involved
sourceDamageSourceThe damage source (.getEntity() for attacker, .type() for damage type)
amountnumberThe damage amount
originalEntityEntityThe entity before dimension change
newEntityEntityThe entity after dimension change
originResourceKeyThe origin dimension
destinationResourceKeyThe destination dimension
levelServerLevelThe world
killerEntityThe entity that dealt the killing blow
killedLivingEntityThe entity that was killed

Event NameCallback SignatureDescription
worldLoad(server, level)A world/dimension is loaded
worldUnload(server, level)A world/dimension is unloaded
chunkLoad(level, chunk)A chunk is loaded
chunkUnload(level, chunk)A chunk is unloaded
ParameterTypeDescription
serverMinecraftServerThe server instance
levelServerLevelThe world/dimension
chunkLevelChunkThe chunk that was loaded or unloaded

Event NameCallback SignatureDescription
serverStarted(server)Server has fully started
serverStopping(server)Server is shutting down
dataPackReload(server, success)Datapack reload finished
beforeSave(server, flush, force)Before the world is saved
afterSave(server, flush, force)After the world is saved
serverTick(server)Fires every server tick
worldTick(level)Fires every world tick
ParameterTypeDescription
serverMinecraftServerThe server instance
successbooleanWhether the datapack reload succeeded
flushbooleanWhether this is a flush save
forcebooleanWhether the save was forced
levelServerLevelThe world being ticked
// Run logic every 5 seconds (100 ticks) instead of every tick
let tickCount = 0;
Events.on('serverTick', (server) => {
tickCount++;
if (tickCount % 100 !== 0) return;
// Your logic here, runs every 5 seconds
});

Event NameCallback SignatureDescription
chatMessage(message, player, params)A player sends a chat message
commandMessage(message, source, params)A command message is sent (/say, /me, /msg)
gameMessage(server, message, overlay)A system message (death, join, advancement)
ParameterTypeDescription
messagePlayerChatMessage / ComponentThe message content
playerServerPlayerThe player who sent the message
sourceCommandSourceStackThe command source
paramsChatDecorator parametersDecoration/formatting parameters
serverMinecraftServerThe server instance
overlaybooleanWhether this is an overlay (action bar) message

Cobblemon events differ from vanilla Minecraft events. They pass a single event object as the callback parameter, with properties you access directly from that object.

Event NameCallback SignatureDescription
battleVictory(event)A battle was won
battleFled(event)A player fled from battle
battleStarted(event)A battle has started
pokeBallCaptureCalculated(event)Capture chance calculated (modify odds)
pokemonCaptured(event)A Pokemon was captured
pokemonSpawned(event)A wild Pokemon spawned
shinyChance(event)Shiny chance is being calculated (modify rate)
fishingBobberLand(event)Fishing bobber lands in water
fishingBite(event)Fish bites the bobber
evolutionComplete(event)A Pokemon finished evolving
evolutionAccepted(event)Player accepted an evolution
eggHatch(event)An egg has hatched
eggCollect(event)An egg was collected from the daycare
rideApplyStamina(event)Ride stamina is being applied

Events.on('blockBreak', (player, pos, state, level) => {
const playerName = player.getName().getString();
const blockName = state.getBlock().getName().getString();
const x = pos.getX();
const y = pos.getY();
const z = pos.getZ();
Logger.info('{} broke {} at {}, {}, {}', playerName, blockName, x, y, z);
});
Events.on('playerJoin', (player) => {
const wrapped = wrapPlayer(player);
wrapped.sendMessage('<gold>Welcome to the server, ' + wrapped.name + '!');
wrapped.playSound('minecraft:entity.player.levelup', {
volume: 0.8,
pitch: 1.2
});
// Track join count in player data
const joins = wrapped.data.getNumber('total_joins') + 1;
wrapped.data.set('total_joins', joins);
wrapped.sendActionBar('Login #' + joins);
});
Events.on('entityKilledOther', (level, killer, killed) => {
// Only care about player kills
if (!killer.isPlayer()) return;
const player = wrapPlayer(killer);
const entityType = killed.getType().toString();
// Increment kill counter
const key = 'kills_' + entityType;
const kills = player.data.getNumber(key) + 1;
player.data.set(key, kills);
// Reward every 50 kills of the same type
if (kills % 50 === 0) {
player.sendMessage('<green>Milestone: ' + kills + ' ' + entityType + ' defeated!');
player.giveItem('minecraft:diamond', 1);
player.playSound('minecraft:ui.toast.challenge_complete');
}
});
Events.on('battleVictory', (event) => {
const battle = event.getBattle();
const winners = event.getWinners();
winners.forEach((actor) => {
// Get the player entity from the battle actor
const playerEntity = actor.getPlayerEntity();
if (!playerEntity) return;
const player = wrapPlayer(playerEntity);
const wins = player.data.getNumber('battle_wins') + 1;
player.data.set('battle_wins', wins);
player.sendActionBar('<yellow>Wins: ' + wins);
// Bonus reward every 10 wins
if (wins % 10 === 0) {
player.giveItem('cobblemon:rare_candy', 3);
player.sendMessage('<gold>Battle milestone! +3 Rare Candy');
}
});
});

  • Start simple: subscribe to one event and log its parameters to understand the data before writing complex logic.
  • Use blockBreakBefore (not blockBreak) if you need to prevent the action. The after event cannot be cancelled.
  • Avoid heavy computation in serverTick and worldTick. Use tick counters or timers instead.
  • Cobblemon events use a single event object parameter — use Object.keys(event) to discover available fields.
  • Always check killer.isPlayer() in entityKilledOther since the killer can be any entity (mob, arrow, etc.).