// Barebones Leaflet viewer (Phase 1). No auth/marker/chat UI yet — those are Phase 3/4. // // Tiles are one Minecraft chunk (16x16 blocks) each, upscaled to 256px, at a single native // zoom level (see api's tile route + worker/src/render/cpu.rs) — Leaflet stretches that one // native zoom to whatever zoom the user picks via `maxNativeZoom`/`minNativeZoom`. // // Coordinate mapping: Leaflet's CRS.Simple treats [lat, lng] as [y, x] with y growing upward // on screen. Minecraft's Z grows south (visually "down" on a conventional north-up map), so // tile y = -chunkZ here; the api negates it back to chunkZ when looking up the tile pointer // (see api/src/index.ts's /api/tiles route comment). function mapmapper() { return { loading: true, server: null, leaflet: null, async init() { const servers = await fetch("/api/servers").then((r) => r.json()); this.loading = false; this.server = servers[0] ?? null; this.leaflet = L.map("map", { crs: L.CRS.Simple, minZoom: -4, maxZoom: 6 }); this.leaflet.setView([0, 0], 0); if (this.server) { L.tileLayer(`/api/tiles/${this.server.id}/0/{z}/{x}/{y}.png`, { tileSize: 256, minNativeZoom: 0, maxNativeZoom: 0, noWrap: true, errorTileUrl: "data:image/svg+xml;base64," + btoa(''), }).addTo(this.leaflet); } }, }; }