738605b6c0
121 MB across 66 dungeon-floor WebPs (~150 KB–6 MB each). Previously gitignored on the assumption LFS would be needed; plain git handles this fine and it removes the kg_fetch → kg_stitch dependency from the deploy path. README and Ansible bring-up step updated.
138 lines
5.2 KiB
Markdown
138 lines
5.2 KiB
Markdown
# mplus-routes
|
||
|
||
Mythic+ route planner for Ascension classic-vanilla dungeons. Static web app
|
||
targeted at `mplus.exil.es`. Uses **Keystone.guru** map tiles + enemy data,
|
||
courtesy of RaiderIO (verbal permission, see attribution below).
|
||
|
||
## Stack
|
||
|
||
- **Maps:** keystone.guru z=4 tile pyramid stitched to 6144×4096 WebP per
|
||
dungeon-floor (~150–600 KB each).
|
||
- **Data:** keystone.guru `mapcontext/data/<slug>/<mapping_id>/split_floors.js`
|
||
— enemies (with positions, classification, NPC linkage), enemy packs
|
||
(polygon outlines), enemy patrols (polylines), map icons (skulls, doors,
|
||
comments, gateways), NPC names from companion `en_US.js`.
|
||
- **Frontend:** vanilla HTML/CSS/JS, single page, no build step. Pan/zoom
|
||
via CSS transform on the canvas stage; SVG overlay in image-pixel space.
|
||
- **Hosting:** static. ~120 MB of WebPs total, committed to the repo. Drop
|
||
behind nginx; no backend.
|
||
|
||
## Layout
|
||
|
||
```
|
||
mplus-routes/
|
||
├── data/
|
||
│ ├── kg_dungeons.json registry: tile_key, data_slug, mapping_id per dungeon
|
||
│ └── kg/ raw kg tiles + data (gitignored)
|
||
│ ├── _summary.json
|
||
│ └── <tile_key>/
|
||
│ ├── split_floors.js
|
||
│ ├── lang.js
|
||
│ └── floor<n>/z4/<x>_<y>.png
|
||
├── tools/
|
||
│ ├── kg_fetch.py fetch tiles + data files for every dungeon in the registry
|
||
│ ├── kg_resync_summary.py rebuild data/kg/_summary.json from disk (after partial fetches)
|
||
│ ├── kg_stitch.py assemble 16×16 tile grids → web/assets/maps/<key>[_floor<n>].webp
|
||
│ ├── kg_build_data.py combine into web/assets/dungeons.json
|
||
│ └── check_kg_alignment.py server-side alignment sanity check (PIL renders into /tmp/)
|
||
└── web/
|
||
├── index.html
|
||
├── style.css
|
||
├── app.js
|
||
└── assets/
|
||
├── dungeons.json
|
||
└── maps/ per-dungeon WebPs (~120 MB, committed)
|
||
```
|
||
|
||
## Build
|
||
|
||
```bash
|
||
python3 -m venv .venv
|
||
.venv/bin/pip install Pillow
|
||
|
||
.venv/bin/python tools/kg_fetch.py --workers 32 --zoom 4 # fetch tiles + data (~1.3 GB raw)
|
||
.venv/bin/python tools/kg_stitch.py --workers 4 # → web/assets/maps/*.webp (~120 MB)
|
||
.venv/bin/python tools/kg_build_data.py # → web/assets/dungeons.json
|
||
```
|
||
|
||
## Run locally
|
||
|
||
```bash
|
||
cd web && python3 -m http.server 8765 # → http://localhost:8765/
|
||
```
|
||
|
||
## Deployment
|
||
|
||
Ansible role + playbook for `mplus.exil.es` live in
|
||
`/home/sub/repos/sub-net/ansible/roles/mplus_routes` and
|
||
`playbooks/setup_mplus_routes.yml`. Targets `exiles01:/srv/www/mplus.exil.es/`
|
||
behind the public HAProxy SNI router. The wildcard `*.exil.es` cert covers
|
||
TLS automatically.
|
||
|
||
First-time bring-up:
|
||
1. Add `mplus.exil.es` A/AAAA records in NetBox (→ public HAProxy VIPs)
|
||
2. Push the Ansible commit, trigger `Ansible_DeployPublicHaproxy`
|
||
3. Run `playbooks/setup_mplus_routes.yml` — `web/assets/maps/` ships in the
|
||
repo, no pre-build step needed.
|
||
|
||
## Coverage
|
||
|
||
29 classic dungeons in the picker:
|
||
|
||
| Dungeon | Enemies | Packs | Map icons |
|
||
|---|---:|---:|---:|
|
||
| Ragefire Chasm | 139 | 9 | 1 |
|
||
| The Deadmines | 218 | 26 | 13 |
|
||
| Wailing Caverns | 261 | 18 | 8 |
|
||
| Shadowfang Keep | 140 | 6 | 5 |
|
||
| The Stockade | 94 | 21 | 5 |
|
||
| Blackfathom Deeps | 240 | 20 | 21 |
|
||
| Gnomeregan | 282 | 44 | 25 |
|
||
| Razorfen Kraul | 199 | 39 | 12 |
|
||
| Razorfen Downs | 219 | 53 | 12 |
|
||
| SM (4 wings) | 69+96+87+79 | 22+25+20+25 | 7+2+4+4 |
|
||
| Uldaman | 261 | 33 | 12 |
|
||
| Zul'Farrak | 302 | 40 | 6 |
|
||
| Maraudon | 548 | 107 | 4 |
|
||
| Blackrock Depths | 819 | 169 | 33 |
|
||
| Lower Blackrock Spire | 380 | 98 | 17 |
|
||
| Upper Blackrock Spire | 207 | 56 | 20 |
|
||
| Stratholme | 377 | 77 | 19 |
|
||
| Scholomance | 344 | 64 | 14 |
|
||
| Dire Maul (3 wings) | 229+300+241 | 58+44+48 | 7+7+10 |
|
||
| Naxxramas (40) | 574 | 92 | 2 |
|
||
| Molten Core | 241 | 39 | 1 |
|
||
| Blackwing Lair | 79 | 15 | 1 |
|
||
| Zul'Gurub | 0 | 0 | 0 |
|
||
| Sunken Temple | 0 | 0 | 0 |
|
||
|
||
ZG and Sunken Temple have map tiles but no enemy data — kg's mapping_id
|
||
search didn't find populated data for them at time of build. Picker still
|
||
lets you draw routes on the map manually.
|
||
|
||
## Attribution
|
||
|
||
Map tiles and enemy data derived from
|
||
[Keystone.guru](https://keystone.guru/) (RaiderIO, Inc.). Used with
|
||
permission from the maintainers for the Ascension community deployment at
|
||
`mplus.exil.es`. World of Warcraft trademarks belong to Blizzard
|
||
Entertainment; this site is not affiliated with Blizzard.
|
||
|
||
## Refresh data sources
|
||
|
||
Both kg's tiles and data update over time. To refresh:
|
||
- Re-run the wide mapping-id probe (`tools/` doesn't ship one — easiest is
|
||
to fetch the kg homepage and find current ids, or re-run a probe like the
|
||
one in `data/kg/_summary.json` headers note).
|
||
- Update `data/kg_dungeons.json` with new mapping_ids.
|
||
- Re-run `kg_fetch.py` → `kg_stitch.py` → `kg_build_data.py`.
|
||
|
||
## Known gaps
|
||
|
||
- 2/29 dungeons (Zul'Gurub, Sunken Temple) are present without enemy data.
|
||
- Multi-floor dungeons (LBRS 7, BWL 4, Naxx 6, etc.) have all floors mapped
|
||
individually; the floor tabs in the UI let you switch between them.
|
||
- No trash-pull authoring beyond kg's data — packs are inherited as-is. For
|
||
custom-routing ("skip this pack, take this one"), use the route+pull tools
|
||
in the toolbar.
|