← World map and portals · all tasks
What playing it actually found — starting at home, closed doors, a keyboard on iPad, and the builds nobody had shipped
world-map-and-portals/010 · created 2026-08-16 · updated 2026-08-18
What prompted it
Kris played the deployed build on a phone, an iPad and a laptop on 2026-08-16 and found six things. Every one of them was real.
1. Strangers standing in the world
The live Village contained MapProbe, Wanderer-6137, E2E-Verifier, Sir K and a second
MapProbe, clustered on the spawn cell. They were the verification scripts’ own
characters — the live verifiers create a guest, join, walk, and their entity persists in
the world snapshot. Cleared, and noted as a recurring hazard: any live verify run leaves a
character behind until someone empties state->'entities' for the authored areas.
2. A new player started in the commons, among those strangers
The client joined the public world by default. Now there is a join_home_world RPC and new
adventurers start in their own home, walking out of the front door into the Village.
A better first minute, and the first thing a player sees is a place that is theirs.
3. A door that teleported you to the corner of the map
The Village’s portal at (20,0) leads to the Wizard Battle Pit, which is restricted. Walking
into it refused the transfer — and because the transfer erases your entity from the source
world before the director answers (that is what makes crash-safety hold), a refusal left
the player with no entity at all. The client’s recovery re-said hello and the world built a
brand-new entity at the default spawn: the top-left corner, silently, with no message.
Now a refusal restores the actual entity — same id, same character — at the cell the
player stepped in from, and the HUD says “That way is closed to you — for now.” The
portal.test.ts case that documented this as a known gap has been rewritten to assert the
fix.
4. Hidden portals weren’t hidden in the game
hidden_unless_passable filtered the world map but not the world. The in-game grid is
hydrated per area, shared by everyone in it, so it can’t answer a per-player question. The
director now works out at join time which doors this account may not see and sends the list
with the join grant — one shared grid, drawn differently per player. Tested with a
stranger and a member standing in the same area seeing different doors.
5. No keyboard on iPad
Godot’s web export draws to a canvas, so there is no focused DOM element for the browser to
raise a keyboard for, and DisplayServer.virtual_keyboard_show() is a no-op on web. Every
text field in the game was dead on a touch device — signup included, which is a hard stop.
Fixed with a real DOM <input> floated over the canvas (game/shell/text-input.js), hooked
into every LineEdit at the factory (theme/lor_forms.gd) via
theme/web_keyboard.gd. Touch devices only, so laptop web is untouched. iOS only opens the
keyboard for a genuine gesture on a real input, so the focus call is synchronous inside the
tap that focused the Godot field — anything deferred and Safari refuses.
Not verified on a real iPad from this session — the plumbing is tested and deployed; the device check is Kris’s.
6. The Android build was never deployed
Correct. The world-map work went out to the web and the server, and the APK was left at the
2026-08-13 build — so the phone showed no map, no profile menu and no portals. Built and
uploaded twice today under the line-in-the-sand rule: APK_NAME v1 → v2 → v3, with
play.astro’s download link following each time.
Verified
Director 150 tests, Godot 116. On production: a new account lands in its own 16×16 home with one door at the bottom middle and nobody else inside; the public map is unchanged; both builds are live.
View source in repository · also available as raw markdown.