Reach the tile route, and give the map what it was missing (#130, #131) - #132
Conversation
**The world rendered in the app and in neither web surface, because the panel's
tile route was unreachable.** Server routes match
/^\/api\/servers\/([^/]+)(?:\/(\w+))?$/
and `\w` does not match a slash, so `/api/servers/:id/map/tiles` matched nothing
and fell through to the 404 at the bottom. Every tile fetch from the panel has
404'd since #119; the desktop was fine because it goes over IPC. One nested
segment is allowed now, still `\w`-only per segment so a sub-route cannot
express a traversal.
The coverage test could not have caught it: it compares the documented surface
to route literals found in the handler's own source, and `'map/tiles'` was in
the source. So there is a second check now — every documented fixed-path GET
route must answer something other than the router's own "not-found", called with
an owner token so a scope refusal cannot be mistaken for a reachable route. It
found the bug immediately when reinstated, and it also flags routes with a
second placeholder as untestable rather than pretending to cover them.
**Heatmap off by default**, on all three surfaces. It is an analysis overlay,
and a red block over the one player online was the first thing anyone saw.
**Click a player to go to them.** The list under the map was inert; with several
people online, finding one meant panning and reading the coordinate readout. It
centres the view and keeps the zoom — jumping to a fixed zoom would throw away
the scale the operator had chosen.
**Structures on the map**: villages, dungeons and ruins, temples, fortresses,
mineshafts, with a filter. Read from `structures.starts` in the same chunk NBT
the surface already comes from, so it costs a lookup rather than a second pass
over the world, and only when asked for — a payload that carries them "in case"
is one the public feed could leak.
Off by default everywhere. An operator may switch them on for their own map
without a setting, because they can already read the world folder. **The public
map cannot**: the feed sends markers only when the operator published them and
ignores what the caller asks for, so the site cannot be talked into a treasure
map of a private world. The toggle is hidden on the public page for the same
reason — a control the feed ignores is not a control.
**How far ahead to load**, as an operator setting. Worth being exact about what
it is not: MSMS never generates terrain. It reads region files the server has
already written, and a map that could grow a world by being panned would be a
map that can fill a disk. "Load ahead" reads a ring of chunks around the
viewport so panning is already drawn — more parsing, same world. Pregenerating
terrain deliberately is a separate feature.
…nsion changes I split the three maps again, one PR after merging them. Structures went into the shared web engine and the routes, and the desktop — which is an admin surface and the one an operator uses most — got none of it. It has the toggle, the filter and the same markers now, drawn from the same `structureKind` grouping so a village is the same dot everywhere. Worse, and older than this PR: tiles are keyed by chunk alone, and the nether uses the same coordinates as the overworld. Switching dimension kept the tiles, so one world's terrain was drawn under another world's players — shipped in #119 and true on every surface. Both caches are dropped when the dimension changes. The markers were also drawn before the grid and the heatmap, so a grid line crossed every one of them. They go after both and before the players: a marker under a line reads as a smudge, and a player must never be behind one.
|
Self-review: markers on the desktop too, and drop tiles when the dimension changes I split the three maps again, one PR after merging them. Structures went into the Worse, and older than this PR: tiles are keyed by chunk alone, and the nether The markers were also drawn before the grid and the heatmap, so a grid line |
Reach the tile route, and give the map what it was missing (#130, #131)
The world rendered in the app and in neither web surface, because the panel's
tile route was unreachable. Server routes match
and
\wdoes not match a slash, so/api/servers/:id/map/tilesmatched nothingand fell through to the 404 at the bottom. Every tile fetch from the panel has
404'd since #119; the desktop was fine because it goes over IPC. One nested
segment is allowed now, still
\w-only per segment so a sub-route cannotexpress a traversal.
The coverage test could not have caught it: it compares the documented surface
to route literals found in the handler's own source, and
'map/tiles'was inthe source. So there is a second check now — every documented fixed-path GET
route must answer something other than the router's own "not-found", called with
an owner token so a scope refusal cannot be mistaken for a reachable route. It
found the bug immediately when reinstated, and it also flags routes with a
second placeholder as untestable rather than pretending to cover them.
Heatmap off by default, on all three surfaces. It is an analysis overlay,
and a red block over the one player online was the first thing anyone saw.
Click a player to go to them. The list under the map was inert; with several
people online, finding one meant panning and reading the coordinate readout. It
centres the view and keeps the zoom — jumping to a fixed zoom would throw away
the scale the operator had chosen.
Structures on the map: villages, dungeons and ruins, temples, fortresses,
mineshafts, with a filter. Read from
structures.startsin the same chunk NBTthe surface already comes from, so it costs a lookup rather than a second pass
over the world, and only when asked for — a payload that carries them "in case"
is one the public feed could leak.
Off by default everywhere. An operator may switch them on for their own map
without a setting, because they can already read the world folder. The public
map cannot: the feed sends markers only when the operator published them and
ignores what the caller asks for, so the site cannot be talked into a treasure
map of a private world. The toggle is hidden on the public page for the same
reason — a control the feed ignores is not a control.
How far ahead to load, as an operator setting. Worth being exact about what
it is not: MSMS never generates terrain. It reads region files the server has
already written, and a map that could grow a world by being panned would be a
map that can fill a disk. "Load ahead" reads a ring of chunks around the
viewport so panning is already drawn — more parsing, same world. Pregenerating
terrain deliberately is a separate feature.