# mplus-routes Mythic+ route planner targeted at `mplus.exil.es` (Ascension community). Static web app: pick a dungeon, see the 4K AI-upscaled map with boss positions, click to drop waypoints/pull markers, draw a route, share via URL hash. ## Data sources - **Boss coords:** AtlasLootAscension `MapData.lua` (vanilla / TBC / WotLK data files), exported by `bisbeard/export_atlasloot_maps.lua` → `data/atlasloot_maps.json`. - **Dungeon maps:** [keyboardturner/WoWMapUprez_Dungeons][uprez] — AI-upscaled (SRCNN) ~4K dungeon maps for every WoW expansion. Tiles are 4×3 grids of 1024×1024 BLPs that we stitch into 4096×3072 PNGs. [uprez]: https://github.com/keyboardturner/WoWMapUprez_Dungeons ## Stack - **Frontend:** vanilla HTML/CSS/JS, single page, no build step. Pan/zoom via CSS transform on the canvas stage; all overlays drawn into an SVG matching the map's image-pixel coord space. - **Build pipeline:** Python + Pillow (uses Pillow's native BLP decoder). - **Hosting:** static. ~260 MB of WebPs total — drop behind any nginx / CDN. No backend. ## Layout ``` mplus-routes/ ├── data/ │ ├── uprez/ # sparse-clone of WoWMapUprez_Dungeons │ ├── atlasloot_maps.json # boss coords by MapName │ └── aliases.json # AtlasLoot id → uprez basename overrides ├── tools/ │ ├── stitch_uprez.py # BLP tiles → 4096×3072 WebP per floor │ └── build_data.py # combine into web/assets/dungeons.json └── web/ ├── index.html ├── style.css ├── app.js └── assets/ ├── dungeons.json # combined data feeding the UI └── maps/ # per-dungeon WebP files served to browsers ``` ## Build ```bash python3 -m venv .venv .venv/bin/pip install Pillow # 1. (one-time) sparse-clone the uprez map pack into data/uprez/ git clone --depth=1 --no-checkout https://github.com/keyboardturner/WoWMapUprez_Dungeons.git data/uprez cd data/uprez && git sparse-checkout init --cone && git sparse-checkout set "Interface/Worldmap" && git checkout && cd ../.. # 2. stitch BLP tiles → WebP (parallel, ~2 minutes on a modern laptop) .venv/bin/python tools/stitch_uprez.py --no-png # 3. combine boss coords + map index → dungeons.json .venv/bin/python tools/build_data.py ``` `stitch_uprez.py --max-width 2048` halves output size if 4K is overkill. ## Run locally ```bash cd web && python3 -m http.server 8765 # http://localhost:8765/ ``` ## Hosting The whole `web/` directory is fully static. - **Domain:** `mplus.exil.es` - **TLS:** wildcard via the cluster's existing edge (Caddy / Traefik / certbot). - **Backend:** none — routes encode into `#` for sharing. A short-URL service is a clean follow-up if shareable `/r/` URLs become wanted (KV-backed Cloudflare Worker would be enough). ## Refresh data sources - **AtlasLoot coords:** re-export with `lua5.4 ../bisbeard/export_atlasloot_maps.lua > data/atlasloot_maps.json` after AtlasLootAscension updates. - **Maps:** `cd data/uprez && git pull` then re-run `stitch_uprez.py` + `build_data.py` after upstream uprez updates. ## Attribution Map textures derived from [WoWMapUprez_Dungeons][uprez]. World of Warcraft trademarks belong to Blizzard Entertainment. This site is not affiliated with Blizzard. ## Known gaps - AtlasLootAscension's WotLK `MapData.lua` has a known upstream bug where every dungeon's `MapName` is `"DireMaul"` — we ignore `MapName` for resolution and use the AtlasLoot dungeon-id (with explicit aliases as needed) instead. - A handful of dungeons in AtlasLoot don't have a corresponding upreza texture (e.g. SerpentshrineCavern interior) — those land in the picker without a map and can still be used for blank-canvas routing. - No trash-pull data — coords are boss-only. Trash groups are authored by hand using the Pull tool. - Multi-floor dungeons currently put all bosses into `unassignedBosses` rather than mapping each pin to its specific floor. Floor-assignment is a follow-up tool.