Framework and inventory adapters
Some checks need to know what your server’s framework and inventory know about a player: their job, whether they are dead or handcuffed, which weapon the inventory says they hold. Bastrel reads this through adapters. They are read only and need no change to qbx_core or ox_inventory: Bastrel never edits a file of another resource, and it never writes to the inventory or to the player.
The checks that use the adapters (state, netevents, see state.md and netevents.md) are delivered; the adapters start with Bastrel.
What is supported
Section titled “What is supported”| Part | Supported | Setting |
|---|---|---|
| Framework | QBX (qbx_core) |
config/framework.lua, name = 'qbx' |
| Inventory | ox_inventory, or none |
config/framework.lua, inventory = 'ox_inventory' or 'none' |
qbcore, esx and standalone are accepted as values but have no adapter yet: Bastrel prints a warning at startup and the checks that read the framework do nothing. A value Bastrel does not know takes the default, with a warning. Bastrel never stops because of this file.
If qbx_core or ox_inventory is configured but not started, the console shows:
[bastrel] WARNING framework: qbx_core is not started; job, group, dead and cuffed checks do nothing until it is.[bastrel] WARNING inventory: ox_inventory is not started; the weapon checks that read the inventory do nothing until it is.This is a warning, not an error: it appears when Bastrel starts before qbx_core or ox_inventory, so the order of your ensure lines matters (start both before bastrel). If ox_inventory starts later, Bastrel registers its hooks by itself within a few seconds and when ox_inventory restarts; qbx_core is read on every call, so it needs no restart.
An unknown is never a verdict
Section titled “An unknown is never a verdict”An adapter answers “unknown” when it cannot tell: the resource is stopped, the player is still loading, an export fails, a field is missing. Bastrel then makes no decision. In particular, an inventory that is not loaded yet is never read as “the player has no weapon”, and a framework that does not answer is never read as “the player is alive and free”. This is what keeps a late-loading resource from causing false alerts.
ox_inventory
Section titled “ox_inventory”Bastrel reads the weapon the inventory says is equipped (GetCurrentWeapon). Treat that as what ox_inventory reports, not as a server-side proof: it is set from the answer of the player’s client when a weapon is used, and a client can clear it. Bastrel never bans on it alone.
It also registers post-hooks on swapItems, usingItem and buyItem. A post-hook only tells Bastrel “something just happened”; it cannot reject or alter anything. Only a weapon item (recognised through ox_inventory’s own item data, so custom weapons count too) that is moved, given (both players are covered), bought or used starts a short grace, and only for that weapon: moving bread or water never extends a grace. A weapon removed by a server script (RemoveItem) has no hook; Bastrel notices it from one periodic sample to the next, and covers the weapon that disappeared as well as a newly equipped one. Moving a weapon inside a stash gives the player no grace, and neither does merely creating one (a shop can create the item before the purchase fails).
The hook runs on every inventory move, even for items that are not weapons (ox_inventory can only filter by exact item name). The cost has not been measured yet (to be measured). To register no hook at all, edit config/modules.lua:
adapters = { inventory = { hooks = false } },The grace is then only started from one sample to the next, which can delay it by one sample. hooks = false also switches off the journal of the item movements and the economy rules that read the same hooks, including the ones that can refuse an action (hooks with a callback on swapItems, buyItem and craftItem): with the hooks off, those rules see no item movement.
Bastrel reads PlayerData.job.name, PlayerData.job.grade.level, GetGroups, and the metadata isdead, inlaststand and ishandcuffed. A player in last stand counts as not alive. These values are written by your framework and your scripts; Bastrel only reads them.