Skip to content

Architecture

noteMASTER11 edited this page Jul 22, 2026 · 16 revisions

Architecture

Runtime layers

flowchart TB
  subgraph Views[UI views]
    HUD[In-game TaxiDriverHUD<br/>AngularJS / CEF]
    Phone[Connected Phone browser<br/>same Angular app + Canvas map]
  end

  subgraph GE[Game Engine Lua — authoritative]
    Orchestrator[taxiDriver.lua<br/>phase and public API]
    Publisher[hudPublisher.lua<br/>epochs, snapshots, patches]
    Domains[Routing, persistence, shifts,<br/>economy, profile, events]
    Supervisor[autopilot.lua<br/>AI supervisor]
    Perception[autopilotPerception.lua<br/>predictive route + spatial model]
    Fleet[fleetManager.lua<br/>economy + worker lifecycle]
    Workers[fleetWorker.lua<br/>lightweight native-route workers]
    AIJournal[aiLogger.lua<br/>streaming JSONL diagnostics]
    Bridge[lanBridge.lua<br/>native External UI + map export]
    Network[networkAddress.lua<br/>LAN candidate ranking]
  end

  subgraph VL[Lazy Vehicle Lua]
    Telemetry[taxiDriverTelemetry]
    Cargo[taxiDriverCargo]
    Recovery[taxiDriverAutopilotRecovery<br/>exact approach + safety rays]
  end

  BeamNG[BeamNG Free Roam systems<br/>road graph, traffic, triggers,<br/>stations, minimap, vehicles]

  HUD <-->|engineLua / guihooks| Orchestrator
  Phone <-->|HTTP + WebSocket| Bridge
  Network --> Bridge
  Bridge <--> Publisher
  Publisher <--> Orchestrator
  Orchestrator <--> Domains
  Orchestrator <--> Supervisor
  Supervisor <--> Perception
  Orchestrator <--> Fleet
  Fleet <--> Workers
  Workers --> BeamNG
  Supervisor --> AIJournal
  Orchestrator <-->|Vehicle Bridge| Telemetry
  Orchestrator <-->|lazy commands| Cargo
  Supervisor <-->|path and completion callbacks| Recovery
  GE <--> BeamNG
  VL <--> BeamNG
Loading

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 orchestrator, state machine, fares, fuel/cargo integration, and public UI API
lua/ge/extensions/taxiDriver/persistence.lua Settings, difficulty, profile, progress schemas, validation, and JSON I/O
lua/ge/extensions/taxiDriver/routePlanner.lua Road-graph routing, semantic stop discovery, speed limits, and level caches
lua/ge/extensions/taxiDriver/vehicleControl.lua Telemetry, forced-stop/freeze control, and passenger/cargo access triggers
lua/ge/extensions/taxiDriver/vehicleHistory.lua Vehicle identity, previews, per-configuration odometer, and work history
lua/ge/extensions/taxiDriver/shiftTracker.lua Current and previous shift totals and net-income calculation
lua/ge/extensions/taxiDriver/shiftHistory.lua Sanitized 60-second shift snapshots, installed-vehicle validation, and vehicle/energy restoration
lua/ge/extensions/taxiDriver/tripEvents.lua Optional cancellations, route changes, tips, and fragile cargo rules
lua/ge/extensions/taxiDriver/autopilot.lua Native-AI route supervision, proactive target handoff, following, signals, overtaking, exact approach, and recovery state
lua/ge/extensions/taxiDriver/autopilotPerception.lua Predictive road-access selection, reference alignment, vehicle-aligned sensor fans, surface/footprint checks, local suffixes, and spatial recovery graph
lua/ge/extensions/taxiDriver/aiLogger.lua Opt-in streaming JSONL journal for AI route, target, traffic, controller, gearbox, recovery, and damage events
lua/ge/extensions/taxiDriver/fleetManager.lua Fleet hiring, economy, persistence, native/world markers, and employee lifecycle
lua/ge/extensions/taxiDriver/fleetWorker.lua Lightweight per-vehicle assignment progress, native route dispatch, current-segment replanning, and bounded failure hand-off
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/nextOfferGuard.lua Real-time, phase-independent expiry validation for proposed next orders
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 Native External UI lifecycle, stable pairing identity, Windows LAN discovery, complete road export, and external vehicle snapshots
lua/ge/extensions/taxiDriver/networkAddress.lua Private IPv4 validation, adapter classification, bind verification, candidate scoring, and deterministic selection
lua/ge/extensions/taxiDriver/hudPublisher.lua Full HUD snapshots, compact field patches, epochs, revisions, and resynchronization checks
lua/ge/extensions/taxiDriver/vehicleScanGuard.lua Vehicle Config suspension, VM lifecycle generations, and stable-VM settle timing
lua/ge/extensions/taxiDriver/logger.lua Structured [TaxiDriver] operations, runtime, LAN, vehicle, warning, and error records
lua/vehicle/extensions/taxiDriverTelemetry.lua Lazy-loaded damage/g-force telemetry and forced-stop inputs
lua/vehicle/extensions/taxiDriverCargo.lua Lazy-loaded physical cargo mass attached to the active vehicle
lua/vehicle/extensions/taxiDriverAutopilotRecovery.lua Lazy exact-approach/bypass controller, powertrain/gearbox override, indicators, and trajectory-ray braking
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 Nine 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
  • shiftTracker current totals, shiftHistory active snapshot identity, AI-use flag, and the active order's optional random event
  • fleetManager session workers, worker routes, wage clocks, assignment state, and cached nearby traffic candidates

State publication and recovery

sequenceDiagram
  participant GE as taxiDriver.lua
  participant Pub as hudPublisher.lua
  participant UI as In-game UI
  participant LAN as lanBridge.lua
  participant Phone as Connected Phone

  GE->>Pub: authoritative state changed
  Pub->>UI: TaxiDriverHUDState or Patch
  Pub->>LAN: revisioned snapshot/patch
  LAN->>Phone: GUI hook over WebSocket
  Phone->>Phone: validate epoch + baseRevision
  alt continuous revision
    Phone->>Phone: merge changed fields
  else missing or stale revision
    Phone->>GE: request full state on heartbeat
    GE->>Pub: force snapshot
    Pub->>Phone: new authoritative state
  end
Loading

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) services vehicle identity, energy, optional LAN state, and taxi gameplay while the mode is active. Vehicle Config temporarily suspends this work before BeamNG rebuilds the current vehicle VM.

  • updateActiveMode(dtSim) advances gameplay and refuses to advance timers when dtSim <= 0.
  • nextOfferGuard advances proposed-order lifetime from dtReal before Vehicle Config or gameplay-phase early returns, so a modal cannot survive a paused or corrupted simulation timer.
  • HUD emission is throttled with dtReal to approximately every 0.2 seconds.
  • With Connected Phone active, periodic updates use revisioned field-level patches; full snapshots remain available for load and recovery.
  • Refueling progress uses the same configured HUD interval instead of a separate 0.1-second stream.
  • Vehicle lifecycle callbacks start a 1.5-second quiet period before telemetry, cargo, energy, and identity work resume.
  • BeamNG's native External UI transport owns HTTP and WebSocket traffic when its LAN listener is reachable. Otherwise the update loop pumps a bounded non-blocking byte proxy from the selected private IPv4 to the game's loopback listener.
  • Fleet workers monitor independently every 250 ms with four staggered update phases; aggregate HUD data is refreshed once per second, nearby hiring candidates are cached for two seconds, and dirty fleet statistics are flushed after a five-second debounce.

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

Player AI and Fleet AI boundary

The player's optional AI Driver and hired Fleet drivers share BeamNG's road graph but no longer share a supervisor instance or perception workload.

flowchart LR
  Route[TaxiDriver road route] --> Choice{Vehicle role}
  Choice -->|Player vehicle| Player[autopilot.lua]
  Player --> Predict[Predictive access model<br/>spatial rays and local A*]
  Predict --> Recovery[Vehicle Lua exact approach<br/>collision and reverse recovery]
  Choice -->|Hired Fleet vehicle| Worker[fleetWorker.lua]
  Worker --> Native[BeamNG ai.driveUsingPath]
  Worker --> Monitor[Staggered progress monitor<br/>bounded current-segment replans]
Loading

This boundary is intentional. Predictive AI remains an interactive, visualizable experiment for one player vehicle. Fleet employees favor predictable CPU cost: no per-worker scene scan, surface-ray fan, parked-vehicle enrollment, spatial graph, exact-approach controller, or gearbox override is created.

UI communication

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

  • TaxiDriverHUDState for full snapshots;
  • TaxiDriverHUDPatch for revisioned field-level changes;
  • TaxiDriverProfileData.

Every HUD stream has an epoch and revision. Clients reject stale or out-of-order patches and request a full snapshot when baseRevision does not match. The controller also normalizes Lua empty tables because they can arrive as JavaScript objects instead of arrays.

Experimental External Web UI

lanBridge.lua starts BeamNG's native bng-ext-app-v1 server with listen address any on TCP port 8085 and probes the selected private IPv4. If that endpoint is reachable, the native server directly serves static HTTP assets and WebSocket traffic. If BeamNG exposes only 127.0.0.1, TaxiDriver binds the selected LAN address and proxies raw bytes to loopback. Both paths retain one authoritative gameplay state and require no companion process.

Predictive AI routing

AI target approach is split between a graph-scale access search and a collision-checked local suffix. The remaining native route acts as a reference envelope, preventing a geometrically short graph candidate from starting backwards or jumping to an unrelated parallel road. See Predictive Route Model for the equations, branch-and-bound selection, 180° sensor model, local A* graph, and execution lifecycle.

BeamNG 0.38.6 can still report only 127.0.0.1 on some Windows installations. Address publication is therefore independent from the server's returned label. networkAddress.lua combines BeamNG adapter entries, the native result, a UDP route probe, Winsock hostname resolution, and the last confirmed address. It rejects loopback/APIPA/non-private values, verifies that BeamNG can bind each candidate, penalizes known virtual/VPN descriptions, and ranks the remaining interfaces.

flowchart LR
  Toggle[Share enabled] --> Native[Create native server on any:8085]
  Native --> Sources{Collect IPv4 candidates}
  Sources --> Beam[BeamNG adapters]
  Sources --> Route[Windows route socket]
  Sources --> DNS[Winsock hostname resolution]
  Sources --> Saved[Last confirmed address]
  Beam --> Rank[Validate + bind-test + rank]
  Route --> Rank
  DNS --> Rank
  Saved --> Rank
  Rank -->|winner| Persist[Write lan.json and publish QR]
  Rank -->|none| Error[Localized unavailable state + diagnostics]
Loading

The server is started only after the player enables Connected phone. Sharing 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.

Five occlusion rectangles protect:

  • route/arrival information;
  • speed-limit sign;
  • phone notifications;
  • the AI control overlay;
  • the fleet Active drivers overlay.

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. Version 2.25.0 moved persistence, routing, vehicle control/history, shift accounting, and random events into focused modules. New independent configuration, pure calculations, or data pools should continue to live outside the main orchestrator.

Clone this wiki locally