Reactive state, interaction points and keybinds on the client.
All three clean up after your resource when it stops.

## Reactive state

Built-in keys: `ped`, `vehicle`, `seat`, `weapon`, `playerId`, `serverId`.

```lua
ObsiLib.state.get('vehicle')
ObsiLib.state.set('menuOpen', true)

local id = ObsiLib.state.on('vehicle', function(vehicle, previous)
    if vehicle then print('entered', vehicle) end
end)
ObsiLib.state.off(id)
```

Every change is also a plain event, `obsi-lib:state:<key>`:

```lua
AddEventHandler('obsi-lib:state:weapon', function(weapon, previous) end)
```

Values pushed from the server with `ObsiLib.state.push` are read the same way.

## Points

Run code while the player is near a position:

```lua
local point = ObsiLib.point.add({
    coords = vec3(441.8, -996.2, 30.7),
    distance = 2.0,
    onEnter = function() ObsiLib.ui.showText({ key = 'E', label = 'Evidence' }) end,
    onExit = function() ObsiLib.ui.hideText() end,
    inside = function()            -- every frame while in range
        if IsControlJustPressed(0, 38) then ObsiLib.stash.open('police_evidence') end
    end,
})

point.remove()
ObsiLib.point.closest()
ObsiLib.point.nearby()
ObsiLib.point.all()
```

## Keybinds

```lua
local bind = ObsiLib.keybind.add({
    name = 'my_script_tablet', description = 'Open tablet', key = 'F5',
    onPress = function() OpenTablet() end,
    onRelease = function() end,
})

bind.disable(true)
bind.currentKey()   -- the key the player bound in the settings
```

Players can rebind it in **Settings → Key Bindings → FiveM**.
