Midir is a companion app for retail Dark Ages. It reads the game client's network traffic, decodes it, and keeps a record of each character that you log in on. The record stays on your computer.
Midir does for Dark Ages what Altoholic does for World of Warcraft. It answers the question "which of my characters holds that item?", and it answers it while the character is offline.
Midir also drives the client for you. It walks your character to a place that you name, it speaks lines for you, and it works an NPC errand. Each of these features is off until you turn it on.
- Live — the character that is logged in now: statistics, health and mana, equipment, inventory, appearance, legend marks, gold, title, and guild. The sheet fills as the packets arrive.
- Characters — each character that you log in on, and the time Midir last read it.
- Items — each item across all of your characters, searchable by name. A row gives the total, and names each character that holds it. Point at a name to see the slot, the durability, and the time Midir last read that character. The bank is included.
- Boards — the posts from the town boards and from your mailbox, kept for you to read again. Midir can also read a board for you: it opens the board through the game's own pane, and it reads each post to the oldest one.
- Map — the map that your character stands on, drawn as a grid from the game's own map cache. The grid shows the blocked tiles, the warps, each live character, and the route that the Walker planned. You can also correct a warp here.
- Diagnostics — Midir's own log, and your session recordings. You can filter the log, copy it into a report, and delete a recording.
Each of these features is off until you turn it on. One stop control halts all of them.
- Walker — name a place, and Midir walks your character there across maps. Midir reads each step from the network. It plans again when a step fails, and it stops when something else moves your character.
- Speaker — Midir says your lines in one game window, on an interval that you set.
- Errands — Midir walks to an NPC, then works the dialog. It reads the conversation from the network, and it selects each option by the words of that option. It stops at an unexpected dialog.
The Walker and the Speaker replace DA Walker and DA Speaker. These two community tools read the game's memory. Midir reads the network instead.
- The way between maps. Your character walks through a warp, and Midir learns that warp from the wire. After two crossings, Midir plans routes through it.
- A correction that you make. The Map tab shows each warp that Midir knows, and where the warp came from. You can accept a warp, refuse it, move it to the correct tile, or add one. Your correction has more authority than the map data that Midir imported.
- A place that needs a route. The Walker shows such a place dim, and the Go button stays off. Walk that warp one time by hand, or add the warp on the Map tab.
- The name of each map. Midir learns the game's own name for a map on your first visit there. Until then it uses the names in its own data files.
- The bank, the legend, and the boards. The game sends these only when you open them. Midir keeps what it reads, and always gives the time that it read them.
This step is optional. In Settings, under Legacy data files, select your Dark Ages folder. Midir then draws the icon of each item, and a picture of your character in its equipment. Midir reads these files, and leaves them as they are.
Midir reads from the network, and acts through the game's own window.
- It reads passively. Capture is with Npcap, the same driver that Wireshark uses. Everything that Midir knows comes off the wire: the map, your position, your items, and your bank. Midir stays out of the game's memory.
- It acts as you do. The assistant features send keys and clicks to the game window. The client examines each action, and each action is one that you can do by hand.
- It leaves the client as it is, with its memory and its files.
- Each assistant feature is off until you turn it on, and one stop halts all of them.
- You type your own password. Midir keeps away from the login dialog and from each password field.
Automation of a game is against the terms of service of most operators. You turn on an assistant feature at your own risk.
Midir makes one request of its own. Midir reads a small list of version numbers from GitHub, ten seconds after start and each time you select Check for updates in Settings. The answer tells you if a newer Midir is available.
- The request carries no personal data. It names the app and nothing more.
- Midir downloads no update and installs no update. Midir shows the version, and you select the link and download the release yourself.
- GitHub receives the request, as it does for a web page that you open.
- Your character record, your recordings, and your settings stay on your computer.
Until the first release of Midir, the list holds no entry for Midir. Midir then shows nothing, which is correct.
- Windows 10 or later.
- Retail Dark Ages, client version 7.41.
- Npcap, installed in WinPcap API-compatible mode.
If you install Npcap with the option "Restrict Npcap driver's access to Administrators only", you must run Midir as an administrator. Midir shows this instruction if it cannot open the adapter.
The stand-in legend marks are from the Game Icons set, used under CC BY 3.0. Midir draws them when it cannot read your Dark Ages folder; when it can, it draws the game's own art from the files already on your computer.
Midir learns the encryption keys from the login handshake. If you start Midir in the middle of a game session, it cannot read that session. Start Midir first, then start Dark Ages.
Over Remote Desktop, Midir changes to software rendering by itself. A remote session has no GPU, and Chromium's GPU compositing is what makes a window drag slowly and the app use about 10% CPU when it does nothing. You do not set anything: Midir reads the session type when it starts.
Midir cannot see a reconnected session. Windows records the session type at logon and does not change it, so a console session that you later connect to over Remote Desktop still shows as local. If a window drags slowly over Remote Desktop, set MIDIR_DISABLE_GPU=1 in the environment before you start Midir. The same variable works the other way: MIDIR_DISABLE_GPU=0 turns hardware rendering on again if the detection is wrong on your computer. Any other value that is not empty means on.
| Script | What it does |
|---|---|
npm run dev |
Launch with HMR |
npm run typecheck |
tsc --build (node and web projects) |
npm run lint / lint:check |
ESLint (flat config), with and without --fix |
npm test / test:coverage |
Vitest (node and jsdom projects) |
npm run e2e / e2e:only |
Playwright E2E on the built app (with and without a rebuild first) |
npm run build:win |
Package Windows nsis and portable |
npm run build:win:portable |
Portable exe only |
npm run build:unpack |
Unpacked build for local smoke tests |
npm run verify:fuses -- <exe> |
Read the Electron fuses off a packaged binary |
Run this gate green before you commit: npm run typecheck && npm run lint:check && npm test && npm run build.
Release notes are written in CHANGELOG.md. Do not edit the GitHub release after it is published.
- As PRs land, add the user-facing change under
## [Unreleased](Keep a Changelog format). - To cut a release, promote
## [Unreleased]to## [X.Y.Z] - YYYY-MM-DD, add a fresh empty[Unreleased]above it, and bump the version withnpm version X.Y.Z --no-git-tag-version. - Start the packaged app before you tag. Run
npm run build:win, then open each exe indist/and make sure that the window opens. The asar integrity fuse makes a damaged package exit with no window and no message, so a package that nobody started is not known to work (HTOO-381).npm run verify:fuses -- dist/win-unpacked/midir.exereads the fuses off the package; the release job runs it too. - Tag
vX.Y.Zand push.release.ymlbuilds and signs the artifacts. Thenscripts/changelog-extract.mjspulls that version's section into the release body, andgenerate_release_notesappends the automatic PR list below it.
A missing section falls back to the automatic notes, so a forgotten entry never fails the release.
If npm run dev builds but the main process stops with Cannot read properties of undefined (reading 'isPackaged'), or no window opens, look for a leaked ELECTRON_RUN_AS_NODE=1 in your shell. Some Electron-hosted terminals set it, which makes Electron run as plain Node. Clear it and try again:
Remove-Item Env:ELECTRON_RUN_AS_NODE; npm run devunset ELECTRON_RUN_AS_NODE && npm run dev