Developer

3 min readUpdated 3 weeks ago

Overview

Integration happens through the open/ folder. There are no exports. Each handler is a plain function with a default body; override it to extend or block a flow without touching the core. The handlers run on the side their file targets: open/server.lua on the server, open/client.lua on the client, open/shared.lua on both.

Server Handlers

Located in open/server.lua.

BeforeGiveItem

open/server.lua
1function OpenServer.BeforeGiveItem(src, item, amount)
2    return true
3end

Fires before a trap is refunded to the player on pickup. Return false to block the give.

BeforePlace

open/server.lua
1function OpenServer.BeforePlace(src, trapTypeName, coords)
2    return true
3end

Fires after the core placement checks pass, before the trap is created. Return false to block placement.

BeforeCapture

open/server.lua
1function OpenServer.BeforeCapture(trap, targetModelHash, targetCitizenId)
2    return true
3end

Fires before a capture is finalized. targetModelHash is set for animal captures, targetCitizenId for player captures. Return false to reject the capture.

OnActionComplete

open/server.lua
1function OpenServer.OnActionComplete(src, actionType, trap)
2end

Fires after any state change. actionType is one of 'place', 'bait', 'capture', 'kill', 'open', 'close', 'pickup', 'expire', 'break'. src is nil for system events such as bait expiry.

Untrusted Capture

'capture' and 'kill' are reported by the client and are not proof an animal was present. If rewards are granted here, credit trap.ownerCitizenId rather than src, and add server-side checks of your own.

OnCleanupDelete

open/server.lua
1function OpenServer.OnCleanupDelete(trapId, trapRecord)
2end

Fires when the cleanup scheduler removes an inactive persistent trap. trapRecord may be nil if the trap was already gone from memory.

Client Handlers

Located in open/client.lua.

Notify

open/client.lua
1function OpenClient.Notify(message, type)
2    Bridge.Notify(message, type)
3end

Routes every notification. Override it to send notifications through a custom UI. type is 'info', 'success', 'warning' or 'error'.

CanPlace

open/client.lua
1function OpenClient.CanPlace(trapTypeName)
2    return true
3end

Fires before placement starts. Return false to cancel based on a custom condition such as a zone or job check.

BeforeOpenMenu

open/client.lua
1function OpenClient.BeforeOpenMenu(trapData)
2    return true
3end

Fires before the interaction panel opens. Return false to block it.

AfterPlace / AfterCapture / AfterOpen / AfterKill

open/client.lua
1function OpenClient.AfterPlace(trapData) end
2function OpenClient.AfterCapture(trapData) end
3function OpenClient.AfterOpen(trapData) end
4function OpenClient.AfterKill(trapData) end

Each fires after the matching action resolves on the client, with the trap data. Use them to drive custom effects.

Shared Handlers

Located in open/shared.lua.

OnPlayerAction

open/shared.lua
1function OpenHandlers.OnPlayerAction(src, data)
2    return true
3end

A generic guard the core calls on a player-initiated action. Return false to refuse. Use it for a server-wide block, for example during an event.

ValidateAction

open/shared.lua
1function OpenHandlers.ValidateAction(src, actionType)
2    return true
3end

Per-action validation called just before the action runs. actionType is 'place', 'bait', 'capture', 'kill', 'open', 'close', 'pickup' or 'repair'. Return false to silently refuse.

Examples

open/client.lua
1function OpenClient.CanPlace(trapTypeName)
2    if InSafeZone(cache.ped) then
3        OpenClient.Notify('You cannot place traps here.', 'error')
4        return false
5    end
6    return true
7end
open/server.lua
1function OpenServer.OnActionComplete(src, actionType, trap)
2    if actionType ~= 'kill' then return end
3    local ownerSrc = GetSourceFromCitizenId(trap.ownerCitizenId)
4    if ownerSrc then
5        Bridge.GiveItem(ownerSrc, 'raw_meat', 1)
6    end
7end
open/shared.lua
1function OpenHandlers.OnPlayerAction(src, data)
2    return not EventActive
3end