Repository navigation
ZedLib — Backend refactoring changes
Summary
Full refactor of the Lua backend: NUI message batching, reactive menu items with watcher, validation, debug mode, and optimisations. Public API remains backward compatible.
1. Performance and NUI latency
- Batching: All NUI messages go through
ZedInternal.SendNUI(action, data)and are flushed once per frame in a singlezedlib:batchpayload. No more consecutiveSendNUIMessagecalls. - Load order:
lua/api/_init.luais loaded beforelua/client.luaso the buffer andSendUIare defined first. - NUI: New handler
zedlib:batchinmessageHandlers.tsdispatches each message in the batch to the existing handlers. - Ticks: Context loop uses
Wait(100)when ALT is not held (was 150). Interact loop usesWait(200)when no interact point is registered. - Context: Model hashes are cached in
ZedState.modelHashCacheto avoid repeatedGetHashKey(). - Callbacks: Import wrapper uses resource-specific events
__zedlib_cb_{resourceName}_{id}when the callback id matchesres:cb:num; otherwise falls back tozedlib:triggerCallback.
2. Dynamic item refresh (reactive values)
- Reactive properties: For menu items,
label,rightLabel,rightLabelColor,infoData, andchecked(checkbox) can be functions. They are called when building the item and periodically by the watcher. - Watcher (
lua/api/watcher.lua): A thread runs atZedConfig.refreshInterval(default 100 ms) only whenZedInternal.menuOpenis true and at least one item has reactive props. It evaluates functions, compares with a cache (deep compare for tables), and sendszedlib:updateItemwith a partial patch when something changes. - Manual refresh:
zed.RefreshItem(menuId, itemId, patch)— sends a partial update for one item.zed.RefreshMenu(menuId)— re-serialises and resends all items of the menu.
- NUI: New handlers
zedlib:updateItemandzedlib:refreshMenu.menuStorehasreplaceItems(menuId, items)for full menu refresh.
3. Menu storage and validation
- State: Menus are stored in
ZedState.menus[menuId]withitemsandcategories. Each item keeps the rawopts(including functions).ZedState.menuItemsById[menuId][itemId]gives O(1) lookup. - Validation: All public menu/dialog/context/progress functions validate arguments and use
ZedInternal.assert(component, condition, message)on failure. Warnings (e.g. category does not exist yet, progress already active) go throughZedInternal.log("WARN", ...). - Helpers:
ZedInternal.validateHex(s),ZedInternal.parseBaseItem(opts)in_init.lua. Dialog validates input types and button variants; ProgressBar validates duration, anim (dict/clip), prop (model); AddContextOption validates exactly one of type/entity/model and optional submenu.
4. Debug mode
- Config:
ZedConfig.debug(defaultfalse),ZedConfig.debugFilter(optional table of components, e.g.{"MENU", "NUI"}),ZedConfig.refreshInterval(default100). - Runtime:
zed.SetConfig({ debug = true }),zed.SetConfig({ debugFilter = {"MENU"} })update ZedConfig and are passed to NUI viazedlib:setConfig. - Logger:
ZedInternal.log(level, component, message, data)with levelDEBUG/INFO/WARN/ERROR. Only runs whenZedConfig.debugis true; ifdebugFilteris set, only listed components are logged. - Command:
RegisterCommand('zeddebug', ...)togglesZedConfig.debugin-game. - Errors: All previous
print()error paths (menu/dialog/context/interact callbacks) now useZedInternal.log("ERROR", component, message, nil).
5. File and API changes
| File | Changes |
|---|---|
config.lua |
Added refreshInterval, debug, debugFilter. |
fxmanifest.lua |
_init.lua before client.lua; added watcher.lua. |
lua/client.lua |
SendUI removed (uses _init); callback errors use ZedInternal.log; context wait 100 when ALT not held. |
lua/api/_init.lua |
ZedState, ZedConst, ZedInternal (SendNUI, assert, log, validateHex, parseBaseItem, fireCallback with resource events), flush thread, SendUI, zeddebug command. |
lua/api/menu.lua |
Full validation; menus/items stored in ZedState; reactive resolution; RefreshItem, RefreshMenu. |
lua/api/watcher.lua |
New. Watcher thread and reactive evaluation. |
lua/api/context.lua |
Model hash cache; validations; errors via log. |
lua/api/dialog.lua |
Validations for inputs/buttons/color. |
lua/api/progressbar.lua |
Validations; warning when already active; errors via log. |
lua/api/interact.lua |
Wait 200 when no config/best; callback errors via log. |
lua/api/config.lua |
SetConfig merges debug, debugFilter, refreshInterval into ZedConfig. |
lua/api/exports.lua |
Doc block; exports RefreshItem, RefreshMenu. |
import.lua |
RefreshItem, RefreshMenu; storeCb registers __zedlib_cb_*; ZedConfigOptions extended. |
web/.../handlers.ts |
dispatchNuiAction export. |
web/.../messageHandlers.ts |
zedlib:batch, zedlib:updateItem, zedlib:refreshMenu. |
web/.../menuStore.ts |
replaceItems(menuId, items). |
6. Breaking changes
- None to the existing public API. All existing function signatures and behaviour are preserved.
- Reactive values: Passing a function for
label,rightLabel,rightLabelColor,infoData, orcheckedis new; static values behave as before.
7. New APIs
zed.RefreshItem(menuId, itemId, patch)— partial update for one menu item.zed.RefreshMenu(menuId)— full refresh of menu items to NUI.zed.SetConfig({ debug = true | false, debugFilter = {"MENU", "NUI"}, refreshInterval = 100 })— runtime config.- In-game:
/zeddebugtoggles debug mode.