A modern web-based map editor for Helbreath .amd map files. Replaces the legacy Windows-only AnMap tool with a cross-platform browser-based editor. Built with Vue 3, TypeScript, PixiJS 8, and Vite.
- Node.js 18+
- npm
- Helbreath client
.paksprite files
npm install
cd tools/pak-converter && npm install && cd ../..The editor needs sprites extracted from Helbreath .pak files. This step converts them into PNG spritesheets and an atlas.json used at runtime.
npm run convert-assetsBy default the converter reads ../client/bin/assets/sprites (a Helbreath client checkout beside this folder). Point it elsewhere with an environment variable or an argument:
HELBREATH_SPRITES=/path/to/sprites npm run convert-assets
npm run convert-assets -- -- --source /path/to/spritesThis generates ~78MB in public/assets/ (gitignored). Without this step, the editor has no sprites to display. If the converter prints WARNING: no PAK file found for: ..., maps that use those sprites will have holes.
npm run devThe editor opens at http://localhost:3000.
npm run build # type-checks, then builds to dist/
npm run preview # serve the production build locallyThe build uses relative paths (base: './'), so dist/ can be hosted from any directory of a static web server.
Every push to master builds the editor and uploads it over FTP (.github/workflows/deploy.yml). It can also be run by hand from the repository's Actions tab.
The sprites are not deployed by the action. public/assets/ is ~78MB of extracted game art that is deliberately kept out of this public repository. The build puts its own JS/CSS in static/, and the action never reads or writes the server's assets/ folder, so you upload the sprites once and deploys stay a few MB.
One-time setup:
-
Run
npm run convert-assets, then upload the contents ofpublic/assets/to<site directory>/assets/on the server with any FTP client. Repeat this only when the converter or the.pakfiles change. -
Add the FTP credentials to the repository (Settings → Secrets and variables → Actions), or with the GitHub CLI:
gh secret set FTP_SERVER # e.g. ftp.example.com gh secret set FTP_USERNAME gh secret set FTP_PASSWORD gh variable set FTP_SERVER_DIR --body "/public_html/map-editor/" # must end with /
Optional variables:
FTP_PROTOCOL(ftpsby default;ftpif the host has no TLS) andFTP_PORT(default 21). The action does not speak SFTP - if the host only offers SFTP, swap the upload step for an SFTP action.
The action only deletes remote files that it uploaded itself, so anything else in the directory is left alone. Do not enable dangerous-clean-slate: it wipes the directory, sprites included.
- Ctrl+O or drag a
.amdfile onto the window to open a map (e.g.default.amd,aresden.amdfrom the client'smapdatadirectory). - Ctrl+S saves. In Chromium browsers the map is written straight back to the file you opened; elsewhere it downloads. Ctrl+Shift+S is Save As.
- Saving is lossless: bytes the editor doesn't understand are preserved, so an unedited map re-saves byte-identical.
- You are warned before unsaved changes are discarded.
Ctrl+N creates a map filled with a terrain preset (grass, dirt, cobblestone, dark stone, water, or empty).
| Tool | Shortcut | Description |
|---|---|---|
| Select | V | Drag a rectangle. Edit its flags in the Properties panel, copy/paste it, or clear its objects |
| Paint Tile | B | Paint base terrain with the tile brush |
| Paint Object | O | Place objects (trees, structures, props) |
| Erase Object | E | Remove objects |
| Eyedropper | I | Pick the object or tile under the cursor. Right-click does this from any tool |
| Bucket Fill | F | Fill the connected area of the same terrain sprite (100,000 tile limit per click), or the whole selection when clicking inside one |
| Blocked / Teleport / Farming / Buildable | X / T / R / U | Paint tile flags. The first tile you click decides whether the drag sets or clears the flag |
- Brush size ([ / ]) applies to tile painting, erasing, and the flag tools.
- Building a tile brush: pick a PAK and sprite on the left, then click or drag tiles in the sheet on the right. Right-drag removes tiles.
- Pattern lock (the ▦ toolbar button, on by default): Helbreath terrain is a block of frames that repeats by map position. With pattern lock on, a multi-tile brush is tiled onto the map grid, so whatever you paint lines up seamlessly with the same terrain anywhere else. Turn it off to stamp the brush exactly where you click.
- Selecting a flag tool turns on its overlay, so you can see what you are painting. Toggle overlays with the Show buttons.
| Flag | Meaning |
|---|---|
| Blocked | Players and monsters can't walk here |
| Teleport | Teleport trigger (the destination is configured on the server) |
| Farming | Crops can be planted (server-side) |
| Buildable | Stored in the file, but no known client or server reads it |
Water is not a flag. The game treats tile sprite 19 as water (fishing, movement). To make water, paint with sprite 19 from maptiles1. The blue W overlay shows exactly those tiles.
- Scroll wheel zooms at the cursor; + / - / 0 zoom in, out, and reset
- Space+drag, middle-drag, or Ctrl+drag pans
- Minimap: click or drag to move the view
- G toggles the grid
Ctrl+Z / Ctrl+Y (or Ctrl+Shift+Z), up to 50 operations. A drag is one operation.
| Shortcut | Action |
|---|---|
| Ctrl+N / Ctrl+O | New / open map |
| Ctrl+S / Ctrl+Shift+S | Save / save as |
| Ctrl+Z | Undo |
| Ctrl+Y / Ctrl+Shift+Z | Redo |
| Ctrl+C / Ctrl+V | Copy selection / paste at cursor |
| Delete | Clear objects in the selection |
| Escape | Clear the selection |
| V / B / O / E / I / F | Select, paint tile, paint object, erase object, eyedropper, bucket fill |
| X / T / R / U | Blocked, teleport, farming, buildable |
| G | Toggle grid |
| [ / ] | Decrease/increase brush size |
| + / - / 0 | Zoom in / out / reset |
| Space+drag | Pan viewport |
| Right-click | Eyedropper |
map-editor/
├── tools/
│ └── pak-converter/ # Node.js tool: converts .pak archives to PNG spritesheets
├── src/
│ ├── components/ # Vue UI components (toolbar, palette, panels)
│ ├── pixi/ # PixiJS map renderer
│ ├── formats/ # File format parsers/writers (AMD)
│ ├── stores/ # Pinia state stores (map, editor, assets)
│ └── composables/ # Vue composables (tools, renderer wiring)
├── public/
│ └── assets/ # Generated spritesheets (gitignored)
└── package.json
See CLAUDE.md for the file formats, architecture, and the reasoning behind them.