> For the complete documentation index, see [llms.txt](https://visionstore.gitbook.io/visionstore-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://visionstore.gitbook.io/visionstore-docs/scripts/crafting/developers/events.md).

# Events

Server events you can listen to from any resource - logs, NPC unlocks and custom craft failures.

Vision Crafting fires these **local server events**. Listen to them from any server resource.

{% hint style="warning" %}
Use **`AddEventHandler`**. These events are local only. Don't register them with `RegisterNetEvent`, which would let clients fake them.
{% endhint %}

| Event                                     | Arguments                                             | When                                                             |
| ----------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------------- |
| `Chapo_Crafting:server:log`               | `event, title, lines`                                 | Every log line (placement, pickup, crafts, claims, admin, NPCs). |
| `Chapo_Crafting:server:workbenchUnlocked` | `src, identifier, workbench, npcId`                   | A player completed a hidden NPC and unlocked a workbench.        |
| `Chapo_Crafting:server:customFailure`     | `recipeKey, succeeded, failed, removedItems, results` | A recipe with `failure.mode = 'custom'` had failed units.        |

## Log

Fired for every log line, whether or not Discord / ox\_lib logging is on.

* `event`: `'place'`, `'pickup'`, `'craft'`, `'claim'` or `'admin'`.
* `title`: for example `'Bench placed'`, `'Craft claimed'`, `'Bench issued'`, `'NPC entry fee paid'`.
* `lines`: an array of `{ label, value }` pairs, in a fixed order.

```lua
AddEventHandler('Chapo_Crafting:server:log', function(event, title, lines)
    local parts = {}
    for _, line in ipairs(lines) do
        parts[#parts + 1] = ('%s=%s'):format(line[1], tostring(line[2]))
    end
    print(('[crafting:%s] %s | %s'):format(event, title, table.concat(parts, ' ')))
end)
```

## Workbench unlocked

```lua
AddEventHandler('Chapo_Crafting:server:workbenchUnlocked', function(src, identifier, workbench, npcId)
    -- workbench = the NPC's unlock id, e.g. 'weapons'; npcId = e.g. 'weapon_dealer'
    print(('%s unlocked the %s workbench from %s'):format(identifier, workbench, npcId))
end)
```

## Custom failure

Give a recipe `failure = { chance = 15, mode = 'custom' }`. When some units fail, this event decides what the player gets back: **add entries to `results`**. Anything you don't add is lost.

| Argument       | What it is                                                                        |
| -------------- | --------------------------------------------------------------------------------- |
| `recipeKey`    | The recipe key, e.g. `'thermite'`.                                                |
| `succeeded`    | Units that succeeded. Their results are already in `results`.                     |
| `failed`       | Units that failed.                                                                |
| `removedItems` | The ingredients that were taken when the craft started.                           |
| `results`      | The list the player will receive. Add `{ item = 'x', amount = n }` entries to it. |

```lua
AddEventHandler('Chapo_Crafting:server:customFailure',
    function(recipeKey, succeeded, failed, removedItems, results)
        if recipeKey == 'thermite' then
            -- a failed thermite leaves some scrap behind
            results[#results + 1] = { item = 'metalscrap', amount = failed * 2 }
        end
    end)
```

## Client: refresh after a house door

Housing scripts that move players between routing buckets without setting the `instance` state bag should tell the crafting system when a player walks through a door, so the bench list is refreshed. From a **client** script:

```lua
TriggerEvent('Chapo_Crafting:client:instanceChanged')
```

rtx\_housing is already wired. See [Bridges](/visionstore-docs/scripts/crafting/developers/bridges.md#housing).


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://visionstore.gitbook.io/visionstore-docs/scripts/crafting/developers/events.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
