---
title: "Events"
description: "Every event with its fields, which ones cancel and which fields the game reads back."
---

> Documentation Index
> Fetch the complete documentation index at: https://aesthetic-docs.pages.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Events

`module:event(name, fn)` subscribes. The callback gets one table of fields, or nothing when
the event has none. Names are exact snake_case strings.

Three rules cover the whole list:

**Cancellable** events carry `:cancel()`.

```lua
module:event("chat", function(e)
if e.text:find("spam") then
    e:cancel()   -- drop the message
end
end)
```

**Writable** fields are read back after the callback. Assign one and the game uses your value.

```lua
module:event("input", function(e)
e.jump = true    -- jump this tick
end)
```

**The table is dead after the callback returns.** Copy out what you need; do not store it.

Numbers are plain Lua numbers (`integer` marks the whole ones), colors are `0xAARRGGBB`, and
positions arrive as raw `x, y, z` scalars rather than [vec3](/vec3). Callbacks run only
while the module is enabled.

## Lifecycle

| Event | Fires |
|-------|-------|
| `enable` | Module toggled on |
| `disable` | Module toggled off |

## Ticks

| Event | Fields | Notes |
|-------|--------|-------|
| `tick` | none | Before the player tick. Cancellable |
| `post_tick` | none | After the player tick |
| `pre_interaction` | none | Before attacks and item use are processed |

## Input

| Event | Fields | Notes |
|-------|--------|-------|
| `input` | `forward, backward, left, right, jump, sneak, sprint` — `boolean`, all writable | Cancellable. Drives player movement |
| `key` | `key, action, mods` — `integer` | Cancellable. GLFW key codes |
| `char` | `char` — `string`; `codepoint, mods` — `integer` | Cancellable. Typed character |
| `mouse_move` | `x, y` — `number` | Cancellable |
| `mouse_scroll` | `horizontal, vertical` — `number` | Cancellable |
| `mouse_look` | `delta_x, delta_y` — `number` | Cancellable. Camera rotation by mouse |
| `cursor_lock` | `state` — `"lock"` / `"unlock"` | Cancellable |
| `slot_drag` | `slot` — `integer` (`-1` outside a slot); `button` — `integer`; `shift` — `boolean` | Cancellable |

## Chat and text

| Event | Fields | Notes |
|-------|--------|-------|
| `chat` | `text` — `string` | Cancellable. A message arrived |
| `chat_send` | `text` — `string` | Cancellable. You are about to send |
| `title` | `text` — `string`; `kind` — `"title"` / `"subtitle"` / `"actionbar"` | A title appeared |
| `boss_bar` | `text` — `string` | Boss bar text changed |

## Combat and interaction

| Event | Fields | Notes |
|-------|--------|-------|
| `attack` | `target` — [entity](/entity) | Cancellable. Before you hit |
| `post_attack` | `target` — [entity](/entity) | After the hit |
| `auto_attack_target` | `target` — [entity](/entity) or `nil`, writable | Cancellable. Auto Attack's target for this tick |
| `auto_attack_rotation` | `target` — [entity](/entity); `yaw, pitch` — `number`, writable | Cancellable. Auto Attack's aim before the rotation service sees it |
| `item_use` | `cooldown` — `integer`, writable | Cancellable |
| `block_interact` | `hand` — `"main"` / `"off"`; `x, y, z` — `integer`; `side` — `string` | Cancellable |
| `block_place` | `hand`; `x, y, z`; `side`; `item` — [item](/item) | |
| `block_breaking` | `state` — `"start"` / `"stop"`; `block` — block id; `x, y, z` | |

The two `auto_attack_*` events fire each interaction tick while Auto Attack is on, so you can
steer it instead of replacing it:

```lua
module:event("auto_attack_target", function(e)
if e.target and e.target:name() == "Bot" then
    e:cancel()
end
end)

module:event("auto_attack_rotation", function(e)
e.pitch = e.pitch - 2
end)
```

`rotation` below sits lower: it fires for every rotation the service applies, including the
one Auto Attack requests here.

## Movement

| Event | Fields | Notes |
|-------|--------|-------|
| `jump` | `yaw` — `number`; `cooldown` — `integer`; both writable | Cancellable |
| `land` | `x, y, z, fall_distance` — `number` | Touched the ground |
| `slowdown` | `multiplier` — `number`, writable | Cancellable. Slowdown while using an item |
| `rotation` | `yaw, pitch` — `number`, writable; `priority` — `integer`, read-only | Cancellable. Every rotation the service applies |

## Network

| Event | Fields | Notes |
|-------|--------|-------|
| `packet_send` | `name` — `string`, plus decoded fields | Cancellable |
| `packet_receive` | `name` — `string`, plus decoded fields | Cancellable |
| `packet_process` | none | Received packets applied to the world |
| `movement_packets` | none | After movement packets are sent |
| `player_packets` | none | After player packets are sent |

`name` is the stable snake_case packet name that `packets.send` also accepts. Common packets
carry decoded fields too; the full list is on [Packets](/packets).

```lua
module:event("packet_receive", function(e)
if e.name == "entity_velocity" and e.entity_id == player:id() then
    e:cancel()   -- ignore knockback aimed at us
end
end)
```

:::caution
`packet_send` and `packet_receive` run on network threads. Collect data there and act in
`tick`; never draw or call `projection` from them.
:::

## World and modules

| Event | Fields |
|-------|--------|
| `chunk_load` | `x, z` — `integer`, chunk coordinates |
| `chunk_unload` | `x, z` — `integer` |
| `module_state` | `module` — `string`; `enabled` — `boolean` |

## Rendering

`render_2d`, `render_gui` and `render_3d` receive a drawing object instead of a field table.

| Event | Fields | Notes |
|-------|--------|-------|
| `frame` | none | Every frame |
| `render_2d` | [2D canvas](/canvas) | Draw over the game |
| `render_gui` | [2D canvas](/canvas) | Draw during GUI screens |
| `render_3d` | [3D renderer](/world-render) | Draw in the world |
| `camera` | `x, y, z, yaw, pitch` — `number`, all writable; `tick_progress` — `number` | Camera pose each frame, after it is positioned. Free Camera moves through this event, so writing the fields overrides it too |
| `sky_color` | `color` — writable; `original` — the value without you | |
| `time_of_day` | `time` — daytime ticks, writable; `original` — `integer` | Visual only |
| `skybox` | `rendered` — `boolean`, writable; `true` hides the vanilla sky | |
| `fog` | `red, green, blue, alpha, environmental_start, environmental_end, render_distance_start, render_distance_end` — `number`, all writable | Color channels are `0..1`, the rest are world distances |
| `window_resize` | `width, height` — `integer` | |

Source: https://aesthetic-docs.pages.dev/events/index.md
