> ## Documentation Index
> Fetch the complete documentation index at: https://mythicframework.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Event System

> Understanding event-driven communication in Mythic Framework

Mythic Framework uses an event-driven architecture that enables loosely-coupled communication between resources, between client and server, and between different parts of the same resource.

## Event Types

<CardGroup cols={2}>
  <Card title="Native FiveM Events" icon="server">
    Built-in FiveM events like `playerConnecting`, `onResourceStart`, etc.
  </Card>

  <Card title="Network Events" icon="wifi">
    Client-server communication via `TriggerServerEvent` and `TriggerClientEvent`
  </Card>

  <Card title="Local Events" icon="location-dot">
    Same-side communication via `TriggerEvent` (doesn't cross network)
  </Card>

  <Card title="Mythic Events" icon="bolt">
    Framework-specific events with middleware support
  </Card>
</CardGroup>

## Event Naming Conventions

```lua theme={null}
-- Pattern: resource:side:action
'mythic-inventory:server:AddItem'
'mythic-inventory:client:UpdateUI'
'mythic-characters:shared:CharacterLoaded'

-- Pattern: System:Type:Event
'Core:Shared:Ready'
'Proxy:Shared:RegisterReady'
'Middleware:Server:PlayerConnecting'
```

## Core Framework Events

### Initialization Events

```lua theme={null}
-- Proxy system ready — safe to register components
AddEventHandler('Proxy:Shared:RegisterReady', function()
    exports['mythic-base']:RegisterComponent('MyComponent', { ... })
end)

-- Core components loaded — safe to fetch and use components
AddEventHandler('Core:Shared:Ready', function()
    exports['mythic-base']:RequestDependencies('MyResource', {
        'Callbacks', 'Fetch', 'Logger'
    }, function(errors)
        if #errors == 0 then
            RetrieveComponents()
        end
    end)
end)

-- A component was registered or extended
AddEventHandler('Proxy:Shared:ExtendReady', function(componentName)
    print('Component ready:', componentName)
end)
```

### Player Events (Server)

```lua theme={null}
-- Player connecting (before fully connected)
AddEventHandler('playerConnecting', function(name, setKickReason, deferrals)
    local source = source
    deferrals.defer()
    deferrals.update('Checking whitelist...')

    local allowed = CheckWhitelist(source)
    if allowed then
        deferrals.done()
    else
        deferrals.done('Not whitelisted')
    end
end)

-- Player dropped
AddEventHandler('playerDropped', function(reason)
    local source = source
    print('Player left:', GetPlayerName(source), 'Reason:', reason)
end)
```

### Character Events

```lua theme={null}
-- Server-side: character selected and loaded
AddEventHandler('mythic-characters:server:CharacterSelected', function(source, character)
    print('Character loaded:', character.SID)
end)

-- Client-side: player spawned in world
AddEventHandler('mythic-characters:client:Spawned', function(character, location)
    print('Spawned at:', location.x, location.y, location.z)
end)
```

## Registering Event Handlers

### Server-Side

```lua theme={null}
-- Listen to local server event
AddEventHandler('mythic-inventory:server:UseItem', function(slot)
    local source = source
    local char = Fetch:Source(source):GetData('Character')
    -- Handle item use
end)

-- Listen to network event from client (must use RegisterNetEvent)
RegisterNetEvent('mythic-inventory:server:DropItem', function(slot, count)
    local source = source
    -- Handle drop
end)
```

### Client-Side

```lua theme={null}
-- Listen to network event from server (must use RegisterNetEvent)
RegisterNetEvent('mythic-inventory:client:UpdateInventory', function(inventory)
    SendNUIMessage({
        type = 'SET_INVENTORY',
        inventory = inventory
    })
end)
```

## Triggering Events

### Local Events (Same Side)

```lua theme={null}
-- Server to server (same or different resource)
TriggerEvent('mythic-economy:server:AddMoney', source, 500)

-- Client to client
TriggerEvent('mythic-hud:client:ShowNotification', {
    message = 'Welcome!',
    type = 'info'
})
```

### Network Events (Cross Network)

```lua theme={null}
-- Client to server
TriggerServerEvent('mythic-inventory:server:UseItem', slot)

-- Server to specific client
TriggerClientEvent('mythic-inventory:client:UpdateInventory', source, inventory)

-- Server to all clients
TriggerClientEvent('mythic-notifications:client:SendAll', -1, {
    message = 'Server restarting in 5 minutes',
    type = 'warning'
})
```

## Middleware System

Mythic includes a middleware system for intercepting and processing events before they reach handlers.

**Location:** `mythic-base/core/sv_middleware.lua`

### Registering Middleware

```lua theme={null}
-- Middleware with priority (lower number = runs first)
Middleware:Add('playerConnecting', function(source, ...)
    local args = {...}
    local name = args[1]

    Logger:Info('Connections', 'Player connecting', {
        source = source,
        name = name
    })

    -- Return true to allow event to continue
    return true, ...
end, 10)

-- Higher priority middleware (runs before priority 10)
Middleware:Add('playerConnecting', function(source, ...)
    if #GetPlayers() >= GetConvarInt('sv_maxclients', 32) then
        -- Return false to block the event
        return false, 'Server is full'
    end
    return true, ...
end, 5)
```

### Middleware Priority

Lower numbers run first:

| Priority | Order  | Use Case               |
| -------- | ------ | ---------------------- |
| 1-5      | First  | Anti-cheat, validation |
| 10-50    | Middle | Business logic         |
| 100+     | Last   | Logging, monitoring    |

## Callback System

For request-response patterns, use callbacks instead of fire-and-forget events.

### Server Callbacks

```lua theme={null}
-- Register callback on server
Callbacks:RegisterServerCallback('mythic-garage:GetVehicles', function(source, data, cb)
    local char = Fetch:Source(source):GetData('Character')

    Database.Game:find({
        collection = 'vehicles',
        query = { owner = char:GetData('SID') }
    }, function(success, vehicles)
        cb(success and vehicles or {})
    end)
end)

-- Client calls server callback
Callbacks:ServerCallback('mythic-garage:GetVehicles', {}, function(vehicles)
    print('Got vehicles:', #vehicles)
end)
```

### Client Callbacks

```lua theme={null}
-- Register callback on client
Callbacks:RegisterClientCallback('mythic-hud:GetPosition', function(data, cb)
    local ped = PlayerPedId()
    local coords = GetEntityCoords(ped)
    cb({ x = coords.x, y = coords.y, z = coords.z })
end)

-- Server requests data from specific client
Callbacks:ClientCallback(source, 'mythic-hud:GetPosition', {}, function(position)
    print('Player position:', position.x, position.y, position.z)
end)
```

## Performance Considerations

<AccordionGroup>
  <Accordion title="Event Frequency" icon="gauge">
    Avoid triggering events in tight loops:

    ```lua theme={null}
    -- Bad: triggers 100 events per tick
    CreateThread(function()
        while true do
            for i = 1, 100 do
                TriggerEvent('someEvent', i)
            end
            Wait(0)
        end
    end)

    -- Good: batch data into one event
    CreateThread(function()
        while true do
            local batch = {}
            for i = 1, 100 do
                table.insert(batch, i)
            end
            TriggerEvent('someEvent', batch)
            Wait(1000)
        end
    end)
    ```
  </Accordion>

  <Accordion title="Network Events" icon="wifi">
    Network events have overhead. Send them at reasonable intervals:

    ```lua theme={null}
    -- Bad: network event every frame
    CreateThread(function()
        while true do
            TriggerServerEvent('updatePosition', GetEntityCoords(PlayerPedId()))
            Wait(0)
        end
    end)

    -- Good: update periodically
    CreateThread(function()
        while true do
            TriggerServerEvent('updatePosition', GetEntityCoords(PlayerPedId()))
            Wait(5000)
        end
    end)
    ```
  </Accordion>

  <Accordion title="Data Size" icon="database">
    Keep event payloads small to reduce network traffic:

    ```lua theme={null}
    -- Bad: sending entire inventory every update
    TriggerClientEvent('updateInventory', source, entireInventory)

    -- Good: send only what changed
    TriggerClientEvent('updateInventorySlot', source, slot, item)
    ```
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Component System" icon="cubes" href="/concepts/component-system">
    Complement events with components
  </Card>

  <Card title="Callback API" icon="phone" href="/api/core/callback">
    Complete callback API reference
  </Card>

  <Card title="Middleware API" icon="filter" href="/api/core/middleware">
    Middleware API reference
  </Card>

  <Card title="Resource Structure" icon="folder-tree" href="/concepts/resource-structure">
    How to structure resources
  </Card>
</CardGroup>
