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

# Events

> Firing and listening: reliable, unreliable, targeted and broadcast.

An event is a named channel. Both sides construct it independently with the same name,
and every send and listen pair on that name lines up.

```luau theme={null}
-- server
local Score = Flux.Server("Score")
-- client
local Score = Flux.Client("Score")
```

## Sending

The four send methods differ along two axes: who receives the message, and whether
delivery is guaranteed.

<Tabs>
  <Tab title="Server">
    | Method                        | Recipients   | Delivery   |
    | ----------------------------- | ------------ | ---------- |
    | `Fire(player, ...)`           | one player   | reliable   |
    | `FireUnreliable(player, ...)` | one player   | unreliable |
    | `FireAll(...)`                | every player | reliable   |
    | `FireAllUnreliable(...)`      | every player | unreliable |

    ```luau theme={null}
    local Score = Flux.Server("Score")

    Score:Fire(player, 1200)                 -- just this player
    Score:FireAll("round_over", winner)      -- everybody
    Score:FireAllUnreliable(os.clock())      -- everybody, droppable
    ```
  </Tab>

  <Tab title="Client">
    The client only ever sends to the server, so there is no target argument.

    | Method                | Recipient  | Delivery   |
    | --------------------- | ---------- | ---------- |
    | `Fire(...)`           | the server | reliable   |
    | `FireUnreliable(...)` | the server | unreliable |

    ```luau theme={null}
    local Score = Flux.Client("Score")

    Score:Fire("request_leaderboard")
    Score:FireUnreliable(mouse.Hit.Position)
    ```
  </Tab>
</Tabs>

<Info>
  Sends are asynchronous and do not block. `Fire` writes into a buffer and returns
  immediately; the buffer is flushed on the next `Heartbeat`. See
  [Batching](/concepts/batching) for the exact timing.
</Info>

### Choosing reliable or unreliable

<AccordionGroup>
  <Accordion title="Use reliable for anything stateful" icon="lock">
    Damage, currency, inventory changes, round transitions, UI state. If dropping the
    message would leave the two sides disagreeing, it has to be reliable.
  </Accordion>

  <Accordion title="Use unreliable for continuous streams" icon="wave-square">
    Positions, aim direction, cosmetic effects, anything you re-send every frame. A
    dropped packet is corrected by the next one, so the loss costs nothing.
  </Accordion>

  <Accordion title="Never mix ordering assumptions" icon="triangle-exclamation">
    Reliable and unreliable travel over separate remotes and are flushed into separate
    buffers. A `FireUnreliable` issued before a `Fire` may arrive after it. Do not
    split one logical message across both channels.
  </Accordion>
</AccordionGroup>

## Listening

### Connect

`Connect` registers a persistent listener and returns a handle with a single
`Disconnect` method.

<CodeGroup>
  ```luau Server theme={null}
  local Chat = Flux.Server("Chat")

  local connection = Chat:Connect(function(player, message)
  	print(player.Name, "said:", message)
  end)
  ```

  ```luau Client theme={null}
  local Chat = Flux.Client("Chat")

  local connection = Chat:Connect(function(message)
  	print("Received:", message)
  end)
  ```
</CodeGroup>

<Warning>
  On the server, the first parameter is always the sending `Player`, followed by the
  arguments. On the client there is no player parameter. This is the most common source
  of off-by-one argument bugs when moving code between contexts.
</Warning>

### Once

`Once` fires at most one time, then removes itself.

```luau theme={null}
local Ready = Flux.Client("Ready")

Ready:Once(function(mapName)
	print("Map loaded:", mapName)
end)
```

<Note>
  `Once` returns nothing. There is no handle, so a `Once` listener cannot be cancelled
  before it fires. If you need to be able to back out, use `Connect` and disconnect
  inside the callback.
</Note>

### Wait

`Wait` yields the calling thread until the next message arrives, then returns the
arguments directly.

<CodeGroup>
  ```luau Server theme={null}
  -- Returns the player first, then the arguments.
  local player, choice = Vote:Wait()
  print(player.Name, "voted", choice)
  ```

  ```luau Client theme={null}
  -- Returns just the arguments.
  local mapName = Ready:Wait()
  print("Map loaded:", mapName)
  ```
</CodeGroup>

<Warning>
  `Wait` has to be called from a yieldable thread, because it uses
  `coroutine.running()` and `coroutine.yield()` internally. Calling it from a context
  that cannot yield will error. It also has no timeout: if the message never arrives,
  the thread stays parked forever. Guard long waits with `task.delay` yourself.
</Warning>

## Multiple listeners

Any number of listeners can be attached to the same name, and each will receive every
message.

```luau theme={null}
local Hit = Flux.Server("Hit")

Hit:Connect(applyDamage)
Hit:Connect(logForAntiCheat)
Hit:Connect(updateStatistics)
```

<Info>
  Ordering is not registration order. Flux dispatches listeners from the end of its
  internal list backwards, so the most recently connected listener runs first. Each
  callback is also spawned with `task.spawn`, which means they run concurrently and one
  erroring listener never blocks the others. Do not write code that depends on listener
  order.
</Info>

## Listeners are keyed by name, not by object

Constructing the same name twice does not give you two isolated channels. Both objects
read and write the same internal listener table.

```luau theme={null}
local a = Flux.Server("Ping")
local b = Flux.Server("Ping")

a:Connect(function(player)
	print("listener registered through a")
end)

-- Fires the listener above, even though it was registered on `a`.
b:Fire(player)
```

<Tip>
  This makes it safe to call `Flux.Server("Name")` in several modules rather than
  passing one object around. It also means a name collision between two unrelated
  systems will silently cross their traffic. Prefix your names once a place gets large:
  `"Combat.Hit"`, `"Shop.Purchase"`.
</Tip>

## Next steps

<CardGroup cols={2}>
  <Card title="Invocations" icon="arrow-right-arrow-left" href="/guides/invocations">
    Round trips with return values.
  </Card>

  <Card title="Connections" icon="plug" href="/guides/connections">
    Disconnecting, and what Flux does not clean up for you.
  </Card>
</CardGroup>
