External App (WebSocket UI Server)
Serves the BeamNG UI over a local WebSocket server for external device access.
Serves the BeamNG UI over a local WebSocket server for external device access.
Overview
ui_extApp creates a WebSocket server on port 8084 that serves the game's UI to external devices (phones, tablets, second screens). It reuses the game's existing UI frontend and stream system.
Extension path: lua/ge/extensions/ui/extApp.lua
Protocol: bng-ext-app-v1
Default port: 8084
Exports (M)
| Function | Signature | Description |
|---|---|---|
onExtensionLoaded | () | Creates/gets the WebSocket server and notifies UI of the URL. |
onExtensionUnloaded | () | Destroys the WebSocket server. |
onUpdate | () | Polls WebSocket events and processes incoming messages. |
requestUIData | () | Triggers externalUIURL guihook with the server URL. |
Internals
Server Setup
local function onExtensionLoaded()
server, chosenAddress = wsUtils.createOrGetWS('any', port, './', protocolName, '/ui/entrypoints/main/index.html')
print('ext app webserver running at: http://' .. chosenAddress .. ':' .. tostring(port))
updateUIData()
endThe server listens on all network interfaces ('any'), serving the main UI entrypoint HTML.
Stream Data
All stream data (vehicle telemetry, minimap data, etc.) is handled in C++ by the BNGWebWSServer - no Lua-side stream processing needed.
Event Processing
WebSocket events are polled each frame:
local events = server:getPeerEvents()
for _, evt in ipairs(events) do
if evt.type == 'D' and evt.msg ~= '' then
local data = jsonDecode(evt.msg)
_handleData(evt, data) -- currently only logs unknown commands
end
endUI Integration
The server URL is sent to the in-game UI via guihooks.trigger('externalUIURL', url) so it can display a QR code or link for external access.
How It Works
extensions.load('ui_extApp')starts the WebSocket server- External devices connect to
http://<ip>:8084to access the game UI - Stream data (telemetry, etc.) is served natively by the C++ WebSocket layer
- The in-game UI shows the connection URL for easy access
- Unloading the extension destroys the server and clears the URL
Additional Exports
The following exports are available but not yet documented in detail:
M.onExtensionLoadedM.onExtensionUnloadedM.onUpdateM.requestUIData