Skip to content

Architecture

noteMASTER11 edited this page Jul 15, 2026 · 16 revisions

Architecture

Runtime layers

TaxiDriverHUD (AngularJS / CEF)
        ⇅ bngApi.engineLua + guihooks
taxiDriver_taxiDriver (Game Engine Lua extension)
        ⇅ core_vehicleBridge / queueLuaCommand
taxiDriverTelemetry + taxiDriverCargo (Vehicle Lua extensions)
        ⇅ BeamNG road, route, minimap, trigger, site, and station systems
BeamNG.drive Free Roam

External phone browser (experimental)
        ⇅ HTTP + WebSocket bng-ext-app-v1
lanBridge (private IPv4:8085 → native External UI on loopback)
        ⇅ guihooks + the same taxiDriver_taxiDriver state

The GE extension is authoritative for gameplay state, routes, money, rating, penalties, persistence, realistic fuel, delivery state, and external-phone connectivity. The in-game and external UIs are views over the same Lua state. UI-only state includes open pages, local countdown animation, chat scheduling, audio players, and compact/full layout selection. Vehicle Lua supplies damage and g-force telemetry, can enforce an emergency stop, and applies physical cargo mass.

File map

File Responsibility
lua/ge/extensions/taxiDriver/taxiDriver.lua Runtime controller, state machine, routes, fares, persistence, fuel/cargo integration, HUD payloads
lua/ge/extensions/taxiDriver/config.lua Static runtime, offer, balance, difficulty, fuel, and phase configuration
lua/ge/extensions/taxiDriver/identity.lua Passenger-name pools and driver-avatar whitelist
lua/ge/extensions/taxiDriver/passengerMood.lua Pure mood calculations and event severity functions
lua/ge/extensions/taxiDriver/offerGenerator.lua Incremental coroutine job scheduler
lua/ge/extensions/taxiDriver/routeDiversity.lua Spatial route-pair history and endpoint diversity validation
lua/ge/extensions/taxiDriver/delivery.lua Cargo weight, fare premium, impact damage, and delivery-rating calculations
lua/ge/extensions/taxiDriver/lanBridge.lua External UI lifecycle, stable pairing identity, LAN address selection, raw TCP bridge, complete road export, and external vehicle snapshots
lua/vehicle/extensions/auto/taxiDriverTelemetry.lua Damage/g-force telemetry and forced-stop inputs
lua/vehicle/extensions/auto/taxiDriverCargo.lua Physical cargo mass attached to the active vehicle
ui/modules/apps/TaxiDriverHUD/app.js Angular controller, Lua bridge, UI-only state, sounds, chat, minimap geometry
ui/modules/apps/TaxiDriverHUD/app.html Phone screens and Angular bindings
ui/modules/apps/TaxiDriverHUD/app.css Complete phone styling and animation
ui/modules/apps/TaxiDriverHUD/locales.json Seven complete localization dictionaries
ui/modules/apps/TaxiDriverHUD/app.json BeamNG UI App registration and default dimensions
ui/modules/apps/TaxiDriverHUD/external/ Lightweight browser entry point, detailed loader, synchronized phone runtime, sounds, and canvas map renderer
mod_info/TaxiDriver/info.json Mod Manager metadata

GE extension dependencies

taxiDriver.lua declares:

  • core_groundMarkers — route path and remaining length;
  • core_vehicleTriggers — passenger-door trigger support;
  • core_vehicle_manager — vehicle integration;
  • freeroam_gasStations — station interaction and refueling wrappers;
  • gameplay_sites_sitesManager — semantic parking/site candidates.

It additionally uses gameplay/route/route, gameplay/traffic/trafficUtils, map graph APIs, facility APIs, raw POIs, marker interaction, vehicle bridge, settings, and native minimap extension APIs.

State ownership

Persistent state

  • userSettings
  • driverProfile
  • userProgress
  • mirrored summary fields in state: balance, rating, rating totals, and completed rides

Shift state

  • state.active, state.phase, active vehicle ID, difficulty, realistic-mode flag
  • current offers pool
  • active trip
  • floating nextOffer and acceptance state
  • telemetry snapshot
  • station, refueling session, and fuel detour
  • minimap/navigation ownership

Cached map state

  • semantic stop candidates keyed by level identifier;
  • 24 recently accepted taxi stop positions;
  • dynamic minimap wrapper and original settings.

Main update loop

M.onUpdate(dtReal, dtSim) always services the optional LAN bridge, then advances taxi gameplay while the mode is active.

  • updateActiveMode(dtSim) advances gameplay and refuses to advance timers when dtSim <= 0.
  • HUD emission is throttled with dtReal to approximately every 0.2 seconds.
  • Refueling can request more frequent HUD updates (0.1 seconds) while its progress bar is active.
  • External HTTP and WebSocket proxy traffic is pumped non-blockingly before heartbeat evaluation, including while gameplay is paused or offline.

The split means pause-safe gameplay with a responsive CEF interface.

UI communication

The UI never mutates the Lua state directly. It calls public extension methods using bngApi.engineLua. Lua emits complete snapshots through:

  • TaxiDriverHUDState;
  • TaxiDriverProfileData.

The controller normalizes Lua empty tables because they can arrive as JavaScript objects instead of arrays.

Experimental External Web UI

BeamNG 0.38.6 may create its native External UI listener only on 127.0.0.1 even when it reports a LAN address. lanBridge.lua therefore binds TCP port 8085 specifically to the selected private IPv4 address and proxies raw traffic to 127.0.0.1:8085. Because the proxy is byte-transparent, it carries both static HTTP assets and the bng-ext-app-v1 WebSocket without maintaining a second gameplay state.

The bridge accepts a bounded number of clients, uses non-blocking reads/writes and bounded buffers, and is started only after the player enables Connected phone. The setting is session-only and returns to off whenever the UI App or mod starts. See External Web UI.

Native minimap integration

The map is not a screenshot or duplicated HTML renderer. TaxiDriver loads ui_apps_minimap_minimap, changes it to rectangular mode while owned, and reports the phone map rectangle in normalized screen coordinates.

Three occlusion rectangles protect:

  • route/arrival information;
  • speed-limit sign;
  • phone notifications.

All transforms and prior minimap settings are reset when the route screen disappears.

Free Roam fuel integration

Realistic Mode uses reversible function wrapping rather than permanently modifying BeamNG source. Restoration checks that the installed wrapper is still active before replacing it with the saved original function. This reduces interference with other extensions, although two mods wrapping the same function can still be load-order sensitive.

LuaJIT local-variable constraint

BeamNG's LuaJIT has a practical limit of 200 local variables in a function/chunk. The main extension is intentionally close to this limit. New independent configuration, pure calculations, or data pools should be placed in focused modules rather than adding top-level locals to taxiDriver.lua.

Clone this wiki locally