# es_extended (/docs/es_extended)

`es_extended` is the core resource of ESX Legacy. It loads characters from the database, creates the server-side [xPlayer](/docs/es_extended/server/xplayer) object, manages money accounts, jobs, items, weapons and permissions, and exposes all of this through the shared `ESX` object that every other ESX resource uses.

## Overview [#overview]

| Fact | Value |
| --- | --- |
| Resource | `es_extended` |
| Version | ESX Legacy 1.16.4 |
| Side | Server, client and shared |
| Dependencies | `oxmysql`, `esx_lib` |
| Export | `getSharedObject` (and `RunStaticPlayerMethod`, used by `ESX.Player`) |
| Database tables | `users`, `jobs`, `job_grades`, `items` (plus `owned_vehicles` for extended vehicles) |
| License | GPL-3.0 |

## Getting the ESX object [#getting-the-esx-object]

There are two supported ways. Pick one per resource.

### Option 1: imports.lua (recommended) [#option-1-importslua-recommended]

```lua title="fxmanifest.lua"
fx_version "cerulean"
game "gta5"
lua54 "yes"

shared_script "@es_extended/imports.lua"

client_script "client/main.lua"
server_script "server/main.lua"
```

`imports.lua` sets a global `ESX` and adds extras:

- On the client, `ESX.PlayerData` and `ESX.PlayerLoaded` stay in sync automatically, and an optional global `OnPlayerData(key, value, last)` function is called on changes.
- On the server, `ESX.Player(source)` and `ESX.ExtendedPlayers()` return [static players](/docs/es_extended/server/xplayer#static-players-esxplayer).
- `ESX.require`, `ESX.load` and `ESX.loadJson` load modules and JSON files when ox_lib is not installed. See [require](/docs/es_extended/client/imports/require).

### Option 2: the export [#option-2-the-export]

```lua title="server/main.lua"
ESX = exports["es_extended"]:getSharedObject()
```

The export returns the `ESX` table at the moment you call it. Functions work normally, but data tables such as `ESX.PlayerData` on the client are not refreshed in your resource. Use getters like `ESX.GetPlayerData()` and `ESX.GetJobs()` instead.

<Callout type="warn" title="Deprecated pattern">
`TriggerEvent("esx:getSharedObject", function(obj) ESX = obj end)` still works in 1.16.4 for backwards compatibility. Do not use it in new code. See [convert old ESX scripts](/docs/guides/convert-old-esx-scripts).
</Callout>

## Resource structure [#resource-structure]

<Files>
  <Folder name="es_extended" defaultOpen>
    <File name="fxmanifest.lua" />
    <File name="imports.lua" />
    <File name="locale.lua" />
    <Folder name="shared" defaultOpen>
      <Folder name="config" defaultOpen>
        <File name="main.lua" />
        <File name="weapons.lua" />
        <File name="adjustments.lua" />
        <File name="logs.lua" />
      </Folder>
      <File name="main.lua" />
      <File name="compat.lua" />
      <Folder name="modules" />
    </Folder>
    <Folder name="server">
      <Folder name="classes" />
      <Folder name="modules" />
      <Folder name="bridge" />
      <Folder name="migration" />
    </Folder>
    <Folder name="client">
      <Folder name="modules" />
      <Folder name="imports" />
    </Folder>
    <Folder name="locales" />
    <Folder name="html" />
  </Folder>
</Files>

| Path | Purpose |
| --- | --- |
| `shared/config/` | The only files you should edit. See [config](/docs/es_extended/config). `logs.lua` is loaded on the server only. |
| `shared/main.lua` | Creates `ESX` and registers the `getSharedObject` export. |
| `shared/modules/` | Shared helpers: config access, weapons, validation, random strings, debug. |
| `shared/compat.lua` | Maps `ESX.Table`, `ESX.Math`, `ESX.SetTimeout` and similar to their esx_lib versions. |
| `server/classes/` | The xPlayer class (split by topic) and the extended vehicle class. |
| `server/modules/` | Player sessions and saving, commands, callbacks, jobs, items, pickups, paychecks, OneSync helpers, Discord logging. |
| `server/bridge/` | Inventory bridges, currently ox_inventory. |
| `server/migration/` | Automatic database migrations that run on start. |
| `client/modules/` | Spawning, player data sync, adjustments, admin tools, death handling, UI wrappers. |
| `client/imports/` | Optional modules loaded by `imports.lua` on the client. |
| `locales/` | Translations, selected with the `esx:locale` convar. |

## Server, client and shared [#server-client-and-shared]

| Side | What you use | Reference |
| --- | --- | --- |
| Server | `ESX.GetPlayerFromId`, `ESX.RegisterCommand`, `ESX.RegisterServerCallback`, `ESX.CreateJob`, ... | [Server functions](/docs/es_extended/server/functions) |
| Server | Player methods: money, items, job, metadata | [xPlayer](/docs/es_extended/server/xplayer) |
| Server | Entity spawning and area searches | [OneSync](/docs/es_extended/server/onesync) |
| Client | `ESX.PlayerData`, notifications, `ESX.TriggerServerCallback`, game helpers | [Client functions](/docs/es_extended/client/functions) |
| Both | `ESX.GetConfig`, `ESX.GetWeapon`, `ESX.Math`, `ESX.Table`, timeouts | [Shared functions](/docs/es_extended/shared) |

Keep authority on the server. The client may ask, but the server checks distance, money, job and items before changing anything.

## Player lifecycle [#player-lifecycle]

<Steps>
<Step>
### Connecting [#connecting]

The player joins. es_extended reads their identifier (`Config.Identifier`, default `license`). Without multicharacter, the character loads right away. With [esx_multicharacter](/docs/core/esx_multicharacter), it waits for the character selection.
</Step>
<Step>
### Loading [#loading]

The `users` row is loaded (or created with the starting money and items), the xPlayer is built and stored in `ESX.Players`. The server event `esx:playerLoaded` fires with `playerId, xPlayer, isNew`.
</Step>
<Step>
### On the client [#on-the-client]

The client receives `esx:playerLoaded` with the player data, spawns the ped and sets `ESX.PlayerLoaded = true`. From now on events like `esx:setJob` and `esx:setAccountMoney` keep `ESX.PlayerData` in sync.
</Step>
<Step>
### Playing [#playing]

The character is saved every 10 minutes and paychecks run every `Config.PaycheckInterval`.
</Step>
<Step>
### Leaving [#leaving]

On disconnect (or logout in multicharacter), `esx:playerDropped` fires with `playerId, reason`, the character is saved and removed from `ESX.Players`. On logout the client receives `esx:onPlayerLogout`.
</Step>
</Steps>

```lua title="server/main.lua"
AddEventHandler("esx:playerLoaded", function(playerId, xPlayer, isNew)
    if isNew then
        xPlayer.addInventoryItem("phone", 1)
    end
end)

AddEventHandler("esx:playerDropped", function(playerId, reason)
    print(("Player %s left: %s"):format(playerId, reason))
end)
```

All events with their arguments: [server events](/docs/es_extended/events/server) and [client events](/docs/es_extended/events/client).

## Explore es_extended [#explore-es_extended]

<Cards>
  <Card title="xPlayer" href="/docs/es_extended/server/xplayer">Every server-side player method: money, items, job, weapons, metadata.</Card>
  <Card title="Server functions" href="/docs/es_extended/server/functions">ESX.* on the server: players, callbacks, commands, jobs, items, vehicles.</Card>
  <Card title="Client functions" href="/docs/es_extended/client/functions">ESX.* on the client: player data, notifications, callbacks, UI.</Card>
  <Card title="Shared functions" href="/docs/es_extended/shared">Helpers available on both sides.</Card>
  <Card title="PlayerData" href="/docs/es_extended/playerdata">Which data ESX keeps per character and where to read it.</Card>
  <Card title="Commands" href="/docs/es_extended/commands">Built-in admin and player commands with permissions.</Card>
  <Card title="Config" href="/docs/es_extended/config">Every key in shared/config/main.lua.</Card>
  <Card title="Events" href="/docs/es_extended/events/server">Server and client events fired by es_extended.</Card>
</Cards>

## Related [#related]

- [Your first ESX resource](/docs/getting-started/first-resource)
- [Coding practices](/docs/getting-started/coding-practices)
- [esx_lib](/docs/core/esx_lib)
- [Convert old ESX scripts](/docs/guides/convert-old-esx-scripts)
