← World map and portals · all tasks

Meeting yourself in the Badlands — one account, one body, per world

done priority 1 estimate S

world-map-and-portals/013 · created 2026-08-16 · updated 2026-08-18

What prompted it

Kris, exploring v5 with the portals finally working, walked into The Badlands and found a second William 3rd standing beside him — same name, same character, both idle.

Not a leftover verifier character. Both rows in that world’s snapshot carried his account id.

What was actually wrong

Entity ids are minted per world, and there are two ways to leave an Area:

Come back into that Area later through a portal and you arrive carrying the id you hold in the world you came from. _handle_hydrate_entity pointed entities_by_account at the arriving body and simply left the old one sitting in entities — still broadcast to every peer, still written into every snapshot, and never looked at again by anything, because the account index only ever points at one. A body with no way back to its owner.

Kris’s own path was exactly this: he had been in the Village, closed the game, then come back in through his own front door. The Badlands twin was the same shape one hop further out.

The fix

_drop_other_entities_for_account(), enforcing one invariant — one account, one body, per world — at both points where an entity enters a world:

Kris’s actual duplicate row was also deleted from production directly, so he didn’t have to wait for the Badlands to next spawn.

Verified

New test walks his exact path — be in the Village, close the game, come back in through your own front door — and asserts one body in the Village afterwards. Confirmed it fails without the fix (expected length 1, got 2), which is the only thing that makes a regression test worth having. Director 154 tests, Godot 116. verify-home-door and verify-world-map both 10/10 against the droplet after deploying.

Server-side only — world_server.gd runs on the droplet, so no new APK and no web re-export. v5 on the phone is still current.

View source in repository · also available as raw markdown.