# Client

The `ak47_lib` provides unified client events that trigger across all supported frameworks (ESX, QBCore, Qbox). This allows you to listen for core player state changes without writing framework-specific event handlers.

#### **`ak47_lib:OnPlayerLoaded`**

Triggered when the player's character has completely loaded into the server and spawned. This event also safely fires if your resource is restarted while the player is already loaded in the server, ensuring your script always catches the active player state.

```lua
--- @param PlayerData table The full framework-specific player data object
--- @param resourceName string|nil The name of the resource if triggered by a resource restart
AddEventHandler('ak47_lib:OnPlayerLoaded', function(PlayerData, resourceName)
    print("Player has successfully loaded!")
    
    -- Example: Initialize script data or spawn UI elements
    Lib47.PlayerLoaded = true
    
    -- If you need to check framework-specific data
    if Lib47.Framework == 'qb' or Lib47.Framework == 'qbx' then
        print("Citizen ID: " .. PlayerData.citizenid)
    elseif Lib47.Framework == 'esx' then
        print("Identifier: " .. PlayerData.identifier)
    end
end)
```

#### **`ak47_lib:OnJobUpdate`**

Triggered on the client whenever the player's job (or grade) is updated by the server.

```lua
--- @param JobInfo table The updated framework-specific job object
AddEventHandler('ak47_lib:OnJobUpdate', function(JobInfo)
    print("Player's job has been updated!")
    
    -- Note: Because the raw JobInfo varies by framework, it's highly recommended
    -- to use the built-in Lib47.GetJob() function inside this event to get a standardized table.
    
    local formattedJob = Lib47.GetJob()
    if formattedJob then
        print(string.format("New Job: %s | Grade: %s | Is Boss: %s", 
            formattedJob.label, 
            formattedJob.grade.name, 
            tostring(formattedJob.isboss)
        ))
    end
end)
```

#### **`ak47_lib:OnPlayerDataUpdate`**

Triggered on the client whenever the core player data object receives a synchronized update from the server. This often occurs when inventory items change, metadata updates, or money is added/removed.

```lua
--- @param PlayerData table The newly updated framework-specific player data object
AddEventHandler('ak47_lib:OnPlayerDataUpdate', function(PlayerData)
    -- This event fires frequently depending on the framework and server activity.
    -- Use this to dynamically update UI elements or active tracking loops.
    
    if Lib47.Framework == 'esx' then
        -- Example: Checking updated accounts in ESX
        for i=1, #PlayerData.accounts, 1 do
            if PlayerData.accounts[i].name == 'bank' then
                print("Updated Bank Balance: $" .. PlayerData.accounts[i].money)
            end
        end
        
    elseif Lib47.Framework == 'qb' or Lib47.Framework == 'qbx' then
        -- Example: Checking updated metadata in QBCore/Qbox
        print("Updated Hunger Level: " .. PlayerData.metadata["hunger"])
    end
end)
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.menanak47.com/plugins/ak47_lib/events/client.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
