Skip to content

Fix Connected Phone map not rendering on BeamNG 0.39 - #4

Merged
noteMASTER11 merged 9 commits into
noteMASTER11:mainfrom
JamDaBam:fix/lan-proxy-map-drain
Jul 29, 2026
Merged

Fix Connected Phone map not rendering on BeamNG 0.39#4
noteMASTER11 merged 9 commits into
noteMASTER11:mainfrom
JamDaBam:fix/lan-proxy-map-drain

Conversation

@JamDaBam

@JamDaBam JamDaBam commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes the external Connected Phone map no longer working after updating to BeamNG.drive 0.39.

The rest of the Connected Phone UI continued to work normally, but the map either remained completely empty or rendered without roads and the vehicle marker.

Root cause

BeamNG 0.39 introduced changes to the external client bridge that affected the map in two ways:

  • The existing beamng.ingame check no longer reliably identified the external Connected Phone client, preventing the external map canvas from being initialized.
  • The guihooks.trigger events previously used to send road, map, and vehicle data no longer reached external browser clients, while other HUD events continued to work normally.

Fix

External-client detection is now explicitly initialized by external.js, with the previous beamng.ingame check retained as a fallback.

Map data delivery was changed from the no longer working guihooks.trigger push mechanism to a pull-based approach using the existing bngApi.engineLua(...) channel.

The external client periodically requests the current map state through pollExternalState(). Vehicle position is returned on every poll, while larger road and terrain data is only transferred when its revision changes.

The existing map rendering logic remains unchanged and now receives its data through the new polling mechanism.

This restores the road network and live vehicle position/heading on the external Connected Phone client with BeamNG.drive 0.39.

The map was also tested inside BeamNG's in-game phone app to ensure that the changes do not affect the existing in-game implementation. Both the external Connected Phone map and the in-game map are working correctly.

JamDaBam and others added 9 commits July 29, 2026 17:56
BeamNG 0.39 fails to bind the native LAN server to non-loopback
interfaces (lws SO_BINDTODEVICE ENODEV), pushing Connected Phone
sessions onto the lua_proxy fallback transport. That proxy only
relayed one read/write per connection per game frame, so bursty
payloads like road/map chunks could trickle out slowly or stall
instead of being forwarded as soon as they arrive.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
BeamNG 0.39's UI/menu engine rewrite changed the availability/timing
of the beamng.ingame global for external WebSocket clients, so
app.js's externalPhoneMode detection silently evaluated false. That
disabled the external map canvases (ng-if="externalPhoneMode") and
made the TaxiDriverExternalRoadData/MapData handlers early-return
with no error, while the rest of the phone UI kept working normally
off other code paths.

external.js only ever bootstraps the Connected Phone browser client
(the in-game phone loads app.js directly), so it can set a flag we
fully control instead of relying on BeamNG's own global.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
TaxiDriverHUDState/HUDPatch keep arriving on the external Connected
Phone client, but TaxiDriverExternalVehicleState/RoadData/MapData
never do, despite both families going through the identical
guihooks.trigger() call with no Lua-side error and all publishing
gates satisfied. The only remaining difference is the one-time
subscribeToEvents("{}") call in external.js: an empty filter may
have meant "subscribe to everything" pre-0.39, but BeamNG 0.39's
bridge appears to now require (or default to) an explicit list.

This is an experiment pending in-game confirmation, not a verified
fix - BeamNG doesn't publicly document this bridge's subscription
filter format.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diagnosing a BeamNG 0.39 regression where TaxiDriverExternalVehicleState/
RoadData/MapData guihooks.trigger calls never reach the Connected Phone
browser client, despite no Lua-side errors and canPublishNavigation()
gating checking out. This logs (every 2s while gated open) the active
transport, current phase, cached road count, pending road chunk index,
and whether a vehicle snapshot is available, to confirm from the game
log whether Lua is actually attempting to publish.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Confirmed via BeamNG's own ui-vue bridge source that subscribeToEvents
feeds StreamManager's vehicle-telemetry "streams" concept, which is
unrelated to bridge.events' plain named-event pub/sub (how
TaxiDriverHUDState/HUDPatch/VehicleChange etc. already arrive with no
subscription needed). The array payload from the previous commit was
also the wrong shape for this call regardless - BeamNG 0.39 logs
"Wrong data stream request format" and rejects it outright, so it was
actively harmful, not just ineffective. Reverting to keep the original
"{}" call BeamNG's own Angular bootstrap uses.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
BeamNG 0.39's native external (non-CEF) Connected Phone client stopped
receiving lanBridge.lua's guihooks.trigger("TaxiDriverExternal...")
pushes for vehicle position, road geometry, and map/route data - with
no error on either side, confirmed via debug logging that Lua kept
firing them every cycle and via browser devtools that nothing ever
arrived over the WebSocket, while other guihooks.trigger events
(TaxiDriverHUDState/HUDPatch) kept working fine over the same bridge.

Replace the push path with a pull one, reusing the bngApi.engineLua
request/response channel that view-switching and heartbeats already
use reliably in this build:

- lanBridge.lua: drop the chunked road-publish/guihooks.trigger
  machinery; add M.pollExternalState(clientRoadRevision,
  clientMapRevision), a plain getter over the same cached map/road
  data (still kept warm by M.update() every frame). Road/terrain data
  is only included when the client's known revision is stale.
- taxiDriver.lua / optionalLanBridge.lua: wire the new entry point
  through, per this mod's lazy-load whitelist requirement.
- app.js: external client now self-schedules a poll (125-500ms,
  matching the existing quality setting) via
  taxiDriver_taxiDriver.pollExternalState(...) instead of listening
  for the three dead push events, which are removed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
bngApi.engineLua(code, callback) splices code in as an argument to
guihooks.trigger("onBNGAPICallback", ...), so it must be a single Lua
expression, not an "if ... then ... end" statement - the latter
crashed the GE Lua VM outright ("unexpected symbol near 'if'"). Use
the `x and x.method(...)` short-circuit idiom instead, matching the
only other callback-style engineLua call in this file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Revert the LAN proxy multi-pass drain rewrite in lanBridge.lua back to
main's original single-pass loop, and drop an external.js comment
narrating it - both were an earlier, disproven hypothesis (the map was
confirmed still broken after that fix shipped) rather than part of
the actual fix, which was switching push to poll delivery.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Pulls in upstream's Release 4.0.0 RC (new UI/CSS, AI/autopilot
overhaul, updated baselines). Merged cleanly with no conflicts; the
map/bridge fix (externalPhoneMode detection + poll-based
TaxiDriverExternal* delivery) is unaffected since upstream's only
touches to lanBridge.lua/external.js were asset-revision version
bumps ("341-rc" -> "400-rc"), and its taxiDriver.lua/app.js changes
landed in unrelated areas (autopilot, offers, native heartbeat
visibility handling).

Note: tests/lua/combinatorics.lua:252 fails on this merge, but was
verified to already fail identically on plain upstream main
(b6c4f15) before merging - a pre-existing issue in their release,
not introduced here.
@JamDaBam

Copy link
Copy Markdown
Contributor Author

@noteMASTER11
I worked the day on the canvas fix.
For me it's working again.
I opened this pull request so you can see the changes.

@noteMASTER11
noteMASTER11 merged commit 9346f4c into noteMASTER11:main Jul 29, 2026
@JamDaBam
JamDaBam deleted the fix/lan-proxy-map-drain branch August 1, 2026 10:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants