Reference

Event reference

The closed list of things a plugin can be told: the variants of Event in crates/rustmc-plugin/src/event.rs. Fifty events. 44 of them are also a hook point with the same name. The other six (player_look, player_input and the four creature_*) are told only to the plugin that asked for them or owns the creature.

How they are delivered:

  • A plugin hears the events its manifest names in events. An empty or missing list hears all of them.
  • Plugins run in priority order: first, early, normal, late, observer. The first cancel wins and the rest still run. A first plugin's cancel of a cancellable event ends it: only observers are told after it.
  • Cancelling an event that is not cancellable is ignored.
  • A handler that fails (a trap, a panic, out of fuel) counts as having passed, unless the manifest lists the event in fail_closed: then it counts as a cancel.
  • A Wasm guest receives each event as one JSON object: the fields below, plus "event": "<name>". Positions are [x, y, z], ids are integers, worlds are names, an account is 32 hex digits, and a missing optional (?) is null.
  • An event a Wasm guest causes with its own host call (damage_saying killing something, set_block) is queued and told as soon as that call returns. The guest cannot cancel it: the step has already happened.

A ? marks a field that may be null.

NameFieldsCancellable
server_startednoneno
server_stoppingnoneno
player_joinedplayer, nameno
player_leftplayer, nameno
player_payloadplayer, channel, data (the bytes; to a Wasm guest a list of byte values, the form send_payload takes). Every channel but minecraft:brandno
player_chatplayer, messageyes: the message is not sent
command_runplayer?, command, restyes: built-in commands do not run
block_breakplayer, world, at, block (the name), state (the whole state, minecraft:oak_stairs[facing=east,...], as set_block reads it)yes: the block stays
block_placeplayer, world, at, block, state (as for block_break)yes: nothing is placed
player_interactplayer, world, at, face, holding (with components), hand (main or off: one right-click can come from each), sneakingyes
damagevictim, attacker?, cause, amountyes: no damage is taken
deathvictim, killer?, messageno
player_move_blockplayer, world, from, tono
game_mode_changedplayer, mode (survival, creative, adventure, spectator)no
inspect_changeplayer (the staff member), account (the target's, 32 hex digits), name, view, changes (item, count)no
container_changeplayer, world, at, block, changes (item, count)no
entity_interactplayer, target, kind, hand, sneakingyes: nothing happens
block_hitplayer, world, at, face (down, up, north, south, west, east), hand (main)yes: the dig does not start, and its finish is refused
entity_attackplayer, target, kindyes: nothing is struck
reserved_explodedworld, at (the blast's centre), blocksno
ores_explodedworld, at (the blast's centre), player?, nearby (player, distance), blocks (at, block)no
blocks_pushedworld, moved (from, to, block, for each block a piston carries; never its arm)no
inventory_clickplayer, slot? (the player's own slot, as inventory_slot numbers it; none for a container's), click (Bukkit's ClickType, lower case: left, swap_offhand, ...)yes: nothing moves, and the window is sent back
player_swingplayer, hand (main)yes: nobody else sees the swing and the attack charge is kept
player_use_itemplayer, world, holding (with components), hand (main or off), sneakingyes: the item is not used
player_swap_handsplayer, main_hand, off_hand (the stacks about to change places)yes: neither moves
player_drop_itemplayer, slot (0-8), item (the stack in the slot), whole_stackyes: it stays in the hand
player_pickup_itemplayer, entity (the item entity), item, count, components, world, at, own (they threw it or died with it)yes: it stays on the ground
player_hotbar_changeplayer, from, to (0-8)yes: the old slot stays selected
player_lookplayer, yaw, pitchno
player_inputplayer, forward, backward, left, right, jump, sneak, sprintno
entity_mountedrider, vehicle (entity ids; a player's is their player id)yes: it stays off
entity_dismountedrider, vehicleyes, when the rider crouched or a plugin's dismount asked: it stays on
player_editplayer, world, at, action (bucket_empty, bucket_fill, ignite, place_entity, place_partner, sign_edit, projectile)yes: it does not happen
entity_harmplayer, target, kind, world, at, causeyes: no hurt
mob_deathvictim, kind, world, at, killer?, cause (the last blow's damage type; minecraft:generic for none)no
world_changedplayer, from, tono
item_craftedplayer, item, count, recipeno
fish_caughtplayer, item, world, at, tableyes: nothing comes up
loot_generatedsource (container or entity), table, world, at, player?, entity?, slots?, items (item, count)yes: the container stays empty, the creature drops nothing from its table
advancement_doneplayer, advancementno
statistic_changedplayer, stat, key, value, amountno
settings_changedplugin, keysno
player_resource_packplayer, pack (its UUID), status (accepted, declined, downloaded, loaded, failed_download, failed_reload, discarded, invalid_url)no
player_respawnplayer, world, atno
creature_order_doneentity, order, outcome (reached, blocked, no_path, target_gone, out_of_range, replaced, died, removed)no
creature_seesentity, target, kind (minecraft:player or the creature's type)no
creature_damagedentity, attacker?, cause, amount, healthno
creature_goneentityno
network_messagefrom (the publishing server's network name), channel, payload (base64 to a Wasm guest). Told only to plugins that network_subscribed to the channel, on the tick after it arrivedno
ticktickno

loot_generated is told whenever a container's table is rolled for one of these: a player opening it (player set), a hopper about to pull from or push into it, or the block breaking (both with no player, as the game's unpackLootTable(null) has none). A chest or hopper minecart is told when a player opens it. Other readers that roll a table on first look -- a comparator, /data, /loot, a crafter or dispenser reaching a loot chest -- roll it untold. Every creature's death drops are told too, with the table, the victim and the player who killed it.

To change the stacks, hook it: a prepend's items are what is placed, so a plugin adds or removes stacks there. A stack left as it was rolled keeps its enchantments and name. A new stack is split at its item's stack size (a count of 5000 diamonds is 79 stacks), a count of nought or less is ignored, and new stacks go into the slots the roll left empty; what does not fit in the container is dropped and logged.

statistic_changed is told for every counter the statistics screen shows except the five that move every tick (play_time, total_world_time, time_since_death, time_since_rest, sneak_time), which would be a hundred events a second per player; read those when you need them. Even so it is the busiest event there is -- a moving player counts distance on every movement packet, up to twenty a second per kind of movement -- so hear it only if you need it. With nothing hearing or hooking it, it costs nothing.

A Wasm guest receives the same fields as flat JSON, plus "event": "<name>". Positions are [x, y, z]. A holding stack is {item, count, damage, components, slot, stamp}, the components each id and its SNBT as inventory_slot reports them, slot where it is held (0-8 the hotbar, 40 the off hand, as inventory_slot numbers it) and stamp its stamp (empty for an empty hand) -- what edit_slot takes, so a plugin can edit the stack it was told about without reading it again.

player_pickup_item is told before an item on the ground goes into a player's inventory, and only when some of it would fit. Cancelled, it stays where it lies -- for a plugin to take it its own way (remove_entity takes an item entity away, give_item gives the stack as it likes). The game tries a pickup every tick a player stands over an item, so a refused one is told again the next tick while it would still fit.

player_resource_pack is every answer a client gives to a pack -- the server's own or one a plugin pushed -- progress (accepted, downloaded) as well as the last. An answer given while the player was still joining is told once they have joined, after player_joined. The game has already acted on the answer: a declined required pack disconnects them whatever a plugin does.

player_respawn is told once a player is back after dying, where they now stand.

block_hit is told when a player starts digging a block -- any block, one they cannot break (a barrier, bedrock, a reserved state with no break time) included, and before anything else about the dig: a note block's punch, a creative or instant break, a reserved block's clock. Cancelled, nothing of the dig happens, the client is sent the block back, and the finish its own clock sends later is refused. A held dig on a reserved block whose break a block_break handler refuses starts again by itself, so it is told as block_break each time, not block_hit.

entity_attack is told for every left click on an entity before anything is struck: a player, a creature, a vehicle, a stand, and an interaction entity -- a plugin's private one (spawn_entity_for) included, which nothing else answers. Cancelled, nothing is struck: no damage, knockback, hunger or wear. The swing's charge is spent either way, as the client spends it.

reserved_exploded is told once a blast is done, if it reached blocks of reserved states: those are never broken by an explosion (a plugin's block is its own to break), so the event lists them for their owner to act on -- break them with set_block, drop something, or leave them. Their own block's resistance still stops the blast. Pistons treat a reserved block as obsidian: never pushed or pulled.

game_mode_changed is also told, and its hook asked, for the mode a player's file brings back as they join, before player_joined. A plugin that overrides the hook with false leaves them in the server's default mode.

ores_exploded is told once a blast is done, if it destroyed anything ending _ore, or ancient debris. Only ore is listed, because every block of a crater would be a heavy call for each TNT of a chain. player is who lit the TNT or slept in the bed. It is missing when nobody can be named, as for TNT lit by redstone or a creature's blast. Then nearby lists the players in that world in survival or adventure as it went off, nearest first, at most 8, at any distance: a plugin looking later would find whoever walked up to look. It is a list of who was there, not of who did it. Blocks a claim kept, and reserved blocks, did not go and are not listed.

The five input events are the keys and buttons that are not a block or a creature. In 26.3:

  • player_swing is the client's punch packet: a left click at the air, or at something out of reach. The client sends nothing else for a swing; a left click on a block is a dig and one on a creature an attack, and neither is told here.
  • player_use_item is a right click the game reads as the item's: at the air, or after a click on a block the block did nothing with (that one is told as player_interact first). It is not told for an item that is cooling, which the game does not use; set_item_cooldown starts a cooldown and item_cooldown reads one, for the server's items and a plugin's own groups.
  • player_swap_hands and player_drop_item are F and Q outside a screen. Inside one they are an inventory_click. Nothing is told for Q with an empty hand.
  • player_hotbar_change is a number key or the scroll wheel.
  • player_look is told only to a plugin that asked with watch_look(player, true), only about the players it asked about, and at most once a tick per player, with where they look by then (the last of that tick's turns). Nothing is told while they hold still.

The four creature_* events are about the creatures a plugin made with spawn_creature, and are told only to the plugin that made them (see creatures):

  • creature_order_done ends every order but idle, once: how it went, replaced when another order (or another mind) took its place, died, or removed when the creature left the world another way. Orders that do not end by themselves (wander, follow, look_at) end only so.
  • creature_sees is told for a creature with a sight_range, twice a second at most, as a player (and, with sees_creatures, a creature) comes into its line of sight; not again until it has been out of it. Spectators are never seen.
  • creature_damaged is told after every blow that lands, with what came off and what is left. Not cancellable: invulnerable keeps a creature from harm.
  • creature_gone is told when one leaves the world without dying: its chunk unloaded, the game despawned it, or remove_entity took it. A death is mob_death, which every plugin may hear.
  • player_input is told only to a plugin that asked with watch_input(player, true), only about the players it asked about, once for each change of the keys the client reports (ServerboundPlayerInputPacket): what a vehicle's driver steers with. Nothing while they hold the same keys.
  • entity_mounted is asked before anything gets on anything: a player's click on a saddled horse, a boat or a harnessed happy ghast, /ride, a plugin's mount and a creature a boat scoops up. A plugin's set_passengers only tells it.
  • entity_dismounted is asked when a player crouches off and when a plugin's dismount asks, and only told -- the rider comes off whatever the answer -- for /ride dismount, a spear's stab, a mount that dies or throws its rider, a boat or cart that breaks, and set_passengers. A player disconnecting is not told: player_left is.

From docs/api/reference/events.md in the RustMC repository at bbd81209ad.