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

# Housing

Boards can live **inside instanced player housing** — visible only to players who are inside the same apartment or house, persistent across restarts.

{% hint style="warning" %}
**Which housing type do you have?** There are two kinds, and they need different setups:

* **Bucket-based** (e.g. **esx\_property**) — many homes share the same world coordinates, separated by routing buckets. **These need the instance integration below.**
* **Coordinate-based** (e.g. **qb-houses**) — every home sits at its own physical location. **These need no integration at all** — just leave boards as world boards, and preferably use a [targeting system](/mole-resource-docs/scripts/hanoi-tower/configuration-file.md#target-interaction) (`ox_target` / `sleepless_interact`) for cleaner interaction indoors. [Details ↓](/mole-resource-docs/scripts/hanoi-tower/housing.md#coordinate-based-housing-qb-houses-and-similar)

Not sure? If entering a home changes your routing bucket, it's bucket-based. If it just teleports you somewhere in the map, it's coordinate-based.
{% endhint %}

## How it works

The script doesn't know what a "house" or a "bucket" is. Instead it uses an **instance identifier** — an opaque string your housing script provides:

* `nil` → open world (default for every player)
* any string, e.g. `"42"` or `"apartment:12"` → a specific home

**The rule is simple: a player only sees boards whose instance matches their own.** Boards placed inside a home inherit the placer's instance and are stored with it in the database.

{% hint style="danger" %}
The identifier must be **stable** — the same home must produce the same string today and after a server restart. A property ID from your housing database is perfect. **Never use the routing bucket number** if it changes between sessions.
{% endhint %}

***

## The Export

Your housing script calls one export in two places — when a player **enters** a home and when they **leave**:

```lua
-- on enter (server-side):
exports['mr_hanoitower']:SetPlayerInstance(source, propertyId)

-- on exit (server-side):
exports['mr_hanoitower']:SetPlayerInstance(source, nil)
```

What the export handles for you automatically:

* If the player was mid-game on a board, they are **forced out safely** — the timer pauses, the lock releases, and the state is saved
* The player receives a fresh, filtered board list — home boards appear, world boards disappear (and vice versa on exit)
* On disconnect, the player's instance is cleared automatically

A read-only companion export is also available:

```lua
local instance = exports['mr_hanoitower']:GetPlayerInstance(source) -- string or nil
```

***

## Example: esx\_property

Tested integration — one line added to the enter event, one to the exit event of `esx_property` (server side):

{% code title="esx\_property/server/main.lua" %}

```lua
RegisterNetEvent('esx_property:enter', function(PropertyId)
    local player = source
    -- ... existing esx_property code ...
    SetPlayerRoutingBucket(player, PropertyId)
    exports['mr_hanoitower']:SetPlayerInstance(player, PropertyId)  -- << add this
end)

RegisterNetEvent('esx_property:leave', function(PropertyId)
    local player = source
    -- ... existing esx_property code ...
    SetPlayerRoutingBucket(player, 0)
    exports['mr_hanoitower']:SetPlayerInstance(player, nil)         -- << add this
end)
```

{% endcode %}

{% hint style="info" %}
`PropertyId` in esx\_property is the permanent database ID of the property, so it is a valid stable identifier — even though the same number also happens to be used as the routing bucket.
{% endhint %}

***

## Other housing scripts

The pattern is identical for any housing system:

1. Find the **server-side** place where a player enters a home (usually where `SetPlayerRoutingBucket` is called)
2. Call `SetPlayerInstance(source, <permanent home id>)` there
3. Find the exit place and call `SetPlayerInstance(source, nil)`

| Housing script | Enter / exit location (typical)                     | Stable ID to use                        |
| -------------- | --------------------------------------------------- | --------------------------------------- |
| qb-apartments  | `qb-apartments/server/main.lua`, enter/leave events | apartment name (e.g. `"apartment1204"`) |
| qb-houses      | server events for entering/exiting                  | house key/name                          |
| ps-housing     | property enter/exit handlers                        | `property_id`                           |

{% hint style="warning" %}
These locations are indicative — housing scripts differ between versions. The esx\_property example above is the tested one.
{% endhint %}

***

## Coordinate-based housing (qb-houses and similar)

Some housing scripts don't use routing buckets — instead each property sits at its **own physical location** in the world (the interior shell is just a repeated model). **qb-houses** works this way.

For these systems you **don't need instance integration at all**: because every home occupies different coordinates, boards placed inside them are already physically separated. A board left as a world board (`instance = nil`) simply lives at that home's coordinates and won't appear in any other home.

{% hint style="success" %}
**Recommended for coordinate-based housing:** use a targeting system (`Config.Target = "ox_target"` or `"sleepless_interact"`) instead of the built-in proximity prompt. Targeting requires the player to aim directly at the board object, which avoids stray "Play / Pick up" prompts inside tight interiors and feels cleaner than a distance-based hint. See [Target / Interaction](broken://pages/d9e621a5850f2023136e171080b6836cc3667536#target-interaction).
{% endhint %}

{% hint style="info" %}
Only use `SetPlayerInstance` for **bucket-based** housing (like esx\_property), where multiple homes share the same world coordinates and must be separated by instance. For coordinate-based housing it is unnecessary.
{% endhint %}

***

## Without integration

No integration? Everything still works in the open world. As a safety measure, **placing a board is blocked while the player is in a routing bucket ≠ 0** with no reported instance — otherwise the board would be saved as a "world" board at coordinates inside a housing shell and become effectively lost. The player keeps the item and sees the `place-blocked-instance` message.
