Events plugins subscribe to — the sandboxed allowlist and the full internal EventBus.
Events Reference

There are two event surfaces, depending on which runtime your plugin uses (see the Overview):
- Sandboxed plugins (default, and the only option on hosted) subscribe with
ed5.events.on("<id>", handler)and must hold the capabilityevents:read:<id>. Only a curated allowlist of events is available. - Trusted file plugins (desktop, or a self-hosted server with trusted file plugins turned on) subscribe with
ctx.eventBus.on("<name>", handler)and can reach the full internal EventBus documented further down.
Sandboxed events (ed5.events.on)#
These are the only events a sandboxed plugin can subscribe to. Request the matching capability in your manifest. Note the dot notation (mob.killed, not mob:killed).
| Event id | Capability | Payload delivered |
|---|---|---|
mob.killed | events:read:mob.killed | { killerId, mobId, mobDefinitionId, posX, posY, zoneId, mobTier? } |
player.login | events:read:player.login | { playerId, playerName, isGuest, zoneId, characterId? } |
player.logout | events:read:player.logout | { playerId, playerName, zoneId, characterId? } |
player.levelup | events:read:player.levelup | { entityId, level, totalSkillLevels, skillCount } |
player.death | events:read:player.death | { victimId, killerId, posX, posY, isPvpKill, pvpRule, zoneId, deathCause } |
item.crafted | events:read:item.crafted | { playerId, recipeId, outputItemDefinitionId, outputQuantity, quality } |
item.pickup | events:read:item.pickup | { playerId, itemDefinitionId, quantity, sourceEntityId } |
zone.enter | events:read:zone.enter | { entityId, previousZoneId, newZoneId, zoneName } |
chat.messageappears in the capability catalog but is not yet wired — you can requestevents:read:chat.message, but the handler never fires today.
Internal EventBus (trusted file plugins only)#
Everything below is the full internal event set, reachable only from trusted file plugins via ctx.eventBus.on("<name>", handler) (colon notation). Sandboxed plugins cannot subscribe to these — use the allowlist above.
Combat Events#
mob:killed#
{ killerId, mobId, mobDefinitionId, posX, posY, zoneId, mobTier }player:killed#
{ victimId, killerId, posX, posY, isPvpKill, pvpRule, zoneId,
deathCause /* "combat" | "survival" | "environment" */ }ability:cast#
{ casterId, abilityId, zoneId? }combat:enter / combat:leave#
{ entityId, zoneId? }damage:dealt#
{ attackerId, targetId, abilityId, damage, isCrit, damageType, targetHpLeft }loot:dropped#
{ mobId, killerId, items: [{ definitionId, quantity }], posX, posY, zoneId }item:pickedup#
{ playerId, itemDefinitionId, quantity, sourceEntityId }Harvesting & Crafting#
harvest:yield#
{ playerId, nodeId, resourceType, itemDefinitionId, quantity, zoneId }harvest:nodeDepleted#
{ nodeId, resourceNodeDefId, zoneId, posX, posY, respawnMs }craft:started#
{ entityId, recipeId, recipeName }craft:completed#
{ playerId, recipeId, outputItemDefinitionId, outputQuantity, quality }Progression#
skill:discovered#
{ entityId, skillId, skillName, triggerAction }skill:xpGained#
{ entityId, skillId, amount, newXp, newLevel }skill:levelUp#
{ playerId, skillId, newLevel }player:levelUpdate#
{ entityId, level, totalSkillLevels, skillCount }Quests#
quest:accepted#
{ entityId, questId, questName }quest:objectiveAdvanced#
{ entityId, questId, objectiveId, objType, newProgress, targetCount }quest:turnedIn#
{ playerId, questId, questName, rewardGold, rewardXp, rewardItemIds }quest:abandoned#
{ entityId, questId }Economy & Social#
trade:completed#
{ playerAId, playerBId, itemsTraded, goldTraded }gold:changed#
{ entityId, amount, newBalance }chat:message#
{ senderId, senderName, channel, text, zoneId }Pets#
tame:success#
{ playerId, petDefinitionId, petLevel, mobEntityId }tame:failed#
{ playerId, mobEntityId, mobDefinitionId }petBattle:started#
{ battleId, challengerId, defenderId }petBattle:ended#
{ battleId, winnerId, loserId }Inventory#
item:equipped#
{ entityId, itemInstanceId, definitionId, slot }item:unequipped#
{ entityId, itemInstanceId, definitionId, slot }item:broken#
{ entityId, itemInstanceId, definitionId }World & Interaction#
world:event#
{ eventId, zoneId?, phase /* "starting" | "ended" */ }interaction:approaching / interaction:started / interaction:completed / interaction:cancelled#
{ entityId, objectInstanceId, interactionId, anchorId? }
// interaction:cancelled also includes: reasonzone:fenced / zone:recovered / zones:reloaded#
// zone:fenced { zoneId, reason? }
// zone:recovered { zoneId, fromShardId? }
// zones:reloaded { reason? }Movement & Environment#
player:step#
{ entityId, zoneId? }weather:changed#
{ weather, previousWeather /* string | null */ }time:changed#
{ timeOfDay, previousTimeOfDay /* string | null */ }calendar:event-started#
{ eventId, name, absoluteDay }Zone & Connection#
zone:changed#
{ entityId, previousZoneId, newZoneId, zoneName }player:login#
{ playerId, playerName, isGuest, zoneId, characterId? }player:logout#
{ playerId, playerName, zoneId, characterId? }Achievements#
achievement:progress#
{ entityId, characterId, achievementId, currentCount, requiredCount }achievement:completed#
{ entityId, characterId, achievementId, achievementName, points }Server Lifecycle#
tick:start / tick:end#
{ deltaMs } // tick:end also has tickMsserver:starting#
{}server:ready#
{ timestamp }server:stopping#
{ timestamp }