OPX//77
opx_infinitymenu

menu

Last updated on

The keyboard-driven list menu that other client modules open through the menu contract, and the spec format it accepts.

Draws one list menu at a time: a titled strip of rows the player moves through with the arrow keys and chooses with Enter. No content of its own: other client modules (admin, elevators, animations, garages, shops…) build a spec, call Open and get a callback for every choice. For picking from a short list, toggling a setting or stepping through submenus.

Sideclient
Requiresnone
Optionaldowned (no menu opens over a downed player)
Contractmenu v1 — client
Configconfig/menu.lua (shared)
Datanone
  • When a form's Enter reopens a menu (a staff search, for example), Enter and Backspace that are still held during the first four key polls must be released before they act, so the reopened menu does not fire the row under the cursor.
  • With focus = 'none', polled keys run the owner's callback on their own thread, not inside the scheduler's shared resume.
  • A menu opened from inside another view's close callback is no longer orphaned.
  • Escape inside a submenu goes back one level (like Backspace) and closes only at the top level. It reaches the menu only when the menu is the top layer.
  • A row with confirm asks first: see Confirm rows.

Configuration

config/menu.lua sets OPX.Config.MODULES.menu. Shared script. Defaults a spec may override per menu.

KeyDefaultEffect
enabledtruefalse switches the module off; OPX.Api.Get('menu') then answers nil.
ANCHOR'top-left'top-left, top-right, left, right or center. Anything else reads as top-left.
WIDTH340Pixels, clamped 240..1200.
MAX_HEIGHT_VH56Maximum height in viewport %, clamped 20..100.
VISIBLE_ROWS9Rows drawn at once, clamped 3..24.
WHILE_DOWN{ admin = true }Owners whose menu may open, and stays open, while the player is down.

Refusal codes

CodeMeaning
spec_must_be_a_tablespec is not a table.
invalid_ownerowner missing or not a valid name.
no_surfaceThe interactive WebUI surface does not exist.
player_downThe player is down and the owner is not in WHILE_DOWN.
menu_busyAnother owner's menu is open and steal was not set.
callback_requiredon is not a function.
invalid_menu_id, invalid_status, invalid_focus, invalid_closableThat spec field is malformed.
invalid_menu_data, menu_data_too_largedata is not a table, or over 64 nodes / 4 levels.
items_must_be_a_table, empty_menu, only_separators, too_many_itemsA level is not a list, is empty, holds only separators, or has more than 200 rows.
menu_too_large, menu_too_deepMore than 400 rows in the tree, or more than 8 levels.
item_must_be_a_table, invalid_item_id, invalid_item_label, invalid_item_description, invalid_item_iconA row field is malformed.
invalid_item_data, item_data_too_largeA row's data is not a table, or too large.
invalid_slider, invalid_slider_rangeslider is not a table, or max is not above min.
invalid_choices, invalid_choice, empty_choiceschoices is malformed or empty.
handle_requiredClose was called without a handle.
no_menu_open, stale_handleNothing is open, or the handle is not the open menu's.

Locale keys owned here: menu.key.choose, menu.key.select, menu.key.change, menu.key.back (the Keys labels), and menu.confirm.title, menu.confirm.yes, menu.confirm.no (the confirm rows).

On this page