> For the complete documentation index, see [llms.txt](https://docs.boii.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.boii.dev/fivem-free-resources/bdsc/guides/extending-players.md).

# Extending Players

BDSC supports dynamic, runtime-safe extension of player objects with custom data and methods. \
This lets you build modular logic without touching the core.

***

## Add Data

Adds custom data to the player. Optionally replicated to the client.

**Example**

```lua
player:add_data("stats", { health = 100, stamina = 50 }, true)
```

**Parameters**

* `stats` – key name for the data entry.
* `{ health = 100, stamina = 50 }` – table to store.
* `true` – replicate to client (optional).

***

## Add Methods

Attach custom methods that can later be executed via `run_method`.

**Example**

```lua
player:add_method("stats", "get_health", function(self)
    local stats = self:get_data("stats")
    return stats and stats.health or 0
end)
```

**Usage**

```lua
player:run_method("stats", "get_health")
```

***

## Update Data

Modify an existing data block and optionally sync it.

**Example**

```lua
local stats = player:get_data("stats")
stats.health = stats.health - 10
player:set_data("stats", stats, true)
```

***

## Remove Data

Removes a data key.

**Example**

```lua
player:remove_data("job")
```

***

## Sync Data

Force a sync of all replicated data to the client.

**Example**

```lua
player:sync_data()
```

***

## Dump All Data

Logs all currently stored player data.

**Example**

```lua
local data = player:get_data()
for k, v in pairs(data) do
    print(k .. ": " .. json.encode(v))
end
```

***

Here’s a concise section explaining how the `on_save` and `on_destroy` methods work when registered via namespaces:

***

## Lifecycle Hooks

BDSC supports **namespace-specific lifecycle methods** that automatically run when certain player events occur.

These methods are defined under a specific namespace using `add_method` and are called internally during key moments in the player's lifecycle.

#### Supported Hooks

| Hook Name    | Description                                                                 |
| ------------ | --------------------------------------------------------------------------- |
| `on_save`    | Called when `player:save()` is triggered (e.g., on disconnect or manually). |
| `on_destroy` | Called when `player:destroy()` is triggered (e.g., on player drop).         |

#### How It Works

When a lifecycle event runs, BDSC will automatically check each namespace for these methods and call them in order.

#### Example

```lua
player:add_method("stats", "on_save", function(self)
    print("Saving stats for player:", self.meta.username)
end)

player:add_method("inventory", "on_destroy", function(self)
    print("Cleaning up inventory for:", self.meta.username)
end)
```

You **do not** need to manually call these - BDSC will handle them as long as they are added under a namespace using `add_method(namespace, "on_save" | "on_destroy", fn)`.

> Avoid long-running operations inside these hooks — keep them lightweight for stability.

***

## Missing Method Safety

Calling a non-existent method will return `nil`.

**Example**

```lua
local result = player:run_method("missing")
print("Result:", result or "nil")
```

***

## No Internal Access

Only the `meta` table is exposed. All other functionality data, methods, syncing - must be accessed via the public API.

Direct access to `_extensions._data`, `_extensions._methods`, or other internals is not possible and never required.

***

## Quick Example

Below is a minimal, self-contained example that demonstrates how to create a player object and extend it externally using basic commands.

This includes:

* Adding a `stats` data block
* Defining custom methods (like `get_health`)
* Syncing data to the client
* Simulating damage
* Handling save logic

```lua
local core = exports.bdsc:import()

-- Create and initialize a new player
RegisterCommand("make", function(src)
    local player = core.create_player(src)
    if not player then print("Failed to create player") return end

    -- Add initial stats
    player:add_data("stats", {
        health = 100,
        stamina = 50
    }, true)

    -- Add method to retrieve health
    player:add_method("stats", "get_health", function(self)
        local stats = self:get_data("stats")
        return stats and stats.health or 0
    end)

    -- Add save lifecycle method
    player:add_method("stats", "on_save", function()
        print("saving player stats")
    end)

    print("Player created and methods attached.")
end, false)

-- Check player health
RegisterCommand("hp", function(src)
    local player = core.get_player(src)
    if not player then print("No player found.") return end

    local hp = player:run_method("stats", "get_health")
    print("Health:", hp)
end, false)

-- Apply damage to the player
RegisterCommand("damage", function(src, args)
    local player = core.get_player(src)
    if not player then print("No player found.") return end

    local amount = tonumber(args[1]) or 10
    local stats = player:get_data("stats")
    stats.health = stats.health - amount

    player:set_data("stats", stats, true)
    print("Damaged player for", amount)
end, false)
```

> **Tip:** Every player object supports runtime extension. You can safely add new data or methods at any point — even after creation.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.boii.dev/fivem-free-resources/bdsc/guides/extending-players.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
