dfhack-remote-node 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +16 -0
- package/README.md +126 -0
- package/build/proto.json +4390 -0
- package/dist/index.d.ts +228 -0
- package/dist/index.js +4762 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
- package/proto/AdventureControl.proto +109 -0
- package/proto/Basic.proto +207 -0
- package/proto/BasicApi.proto +109 -0
- package/proto/CoreProtocol.proto +92 -0
- package/proto/DwarfControl.proto +97 -0
- package/proto/ItemdefInstrument.proto +108 -0
- package/proto/RemoteFortressReader.proto +1131 -0
- package/proto/ui_sidebar_mode.proto +65 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020, Alexander Chandel (original browser client)
|
|
4
|
+
Copyright (c) 2026, Alexander Olvera (TypeScript/Node port)
|
|
5
|
+
|
|
6
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
7
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
8
|
+
copyright notice and this permission notice appear in all copies.
|
|
9
|
+
|
|
10
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
11
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
12
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
13
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
14
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
15
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
16
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# dfhack-remote-node
|
|
2
|
+
|
|
3
|
+
A small, strictly-typed Node client for the [DFHack](https://github.com/DFHack/dfhack)
|
|
4
|
+
Remote RPC protocol — protobuf over raw TCP (`127.0.0.1:5000`). It lets a Node
|
|
5
|
+
process read from (and, later, act on) a live Dwarf Fortress fort without
|
|
6
|
+
compiling against DFHack's C++.
|
|
7
|
+
|
|
8
|
+
This is a TypeScript port of the original browser client
|
|
9
|
+
([alexchandel/dfhack-remote](https://github.com/alexchandel/dfhack-remote), ISC).
|
|
10
|
+
The protocol codec is carried over; the transport was rewritten from
|
|
11
|
+
WebSocket + `websockify` to Node `net.Socket`, `RunCommand` console output is now
|
|
12
|
+
captured instead of discarded, and methods bind lazily on first use.
|
|
13
|
+
|
|
14
|
+
Built primarily as the RPC layer for a DFHack MCP server.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
npm install dfhack-remote-node
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The published package ships prebuilt (`dist/` ESM + type declarations, proto
|
|
23
|
+
bundle inlined), so no build step is needed to consume it.
|
|
24
|
+
|
|
25
|
+
To work on the library from a clone instead:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npm install
|
|
29
|
+
npm run build # regenerates build/proto.json and bundles dist/
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`build/proto.json` (the compiled protobuf bundle) is committed, so the source
|
|
33
|
+
runs immediately; `npm run build` produces the distributable `dist/` (ESM +
|
|
34
|
+
type declarations, with the proto bundle inlined).
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
import { DwarfClient } from 'dfhack-remote-node';
|
|
40
|
+
|
|
41
|
+
const df = new DwarfClient(); // defaults to 127.0.0.1:5000
|
|
42
|
+
await df.connect(); // handshake
|
|
43
|
+
|
|
44
|
+
console.log(await df.getVersion()); // DFHack version string
|
|
45
|
+
const world = await df.getWorldInfo(); // decoded GetWorldInfoOut
|
|
46
|
+
console.log(world.worldName?.englishName);
|
|
47
|
+
|
|
48
|
+
// Arbitrary Lua snippet; returns whatever it prints (captured console output):
|
|
49
|
+
const text = await df.runLuaSnippet('print(#df.global.world.units.active)');
|
|
50
|
+
|
|
51
|
+
// Any method in the METHODS table, by name:
|
|
52
|
+
const map = await df.call('GetMapInfo');
|
|
53
|
+
|
|
54
|
+
df.close();
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Every reply object also carries `_text` — the concatenated console output from
|
|
58
|
+
any TEXT frames the call produced.
|
|
59
|
+
|
|
60
|
+
## Package layout
|
|
61
|
+
|
|
62
|
+
`src/` is split by concern (all TypeScript ESM):
|
|
63
|
+
|
|
64
|
+
| File | Responsibility |
|
|
65
|
+
| --------------- | ----------------------------------------------------------------------------------- |
|
|
66
|
+
| `codec.ts` | wire framing: magic bytes, frame ids, `encodeMessage`, `readHandshake`, `readFrame` |
|
|
67
|
+
| `errors.ts` | `RpcError`, `ProtocolError` |
|
|
68
|
+
| `connection.ts` | `DfConnection` — the `net.Socket` transport + call queue |
|
|
69
|
+
| `methods.ts` | the `METHODS` table (fully-qualified protobuf type names) |
|
|
70
|
+
| `proto.ts` | loads the committed proto bundle as a JSON module import |
|
|
71
|
+
| `client.ts` | `DwarfClient` — the high-level API |
|
|
72
|
+
| `index.ts` | public exports |
|
|
73
|
+
|
|
74
|
+
The source imports the proto bundle as a JSON module
|
|
75
|
+
(`import protoJson from '../build/proto.json' with { type: 'json' }`), so the
|
|
76
|
+
bundler inlines it into `dist/` — there is no runtime file lookup.
|
|
77
|
+
|
|
78
|
+
## Protos
|
|
79
|
+
|
|
80
|
+
> The `.proto` files are pinned to **DFHack `53.15-r2`** (pulled from
|
|
81
|
+
> [DFHack/dfhack](https://github.com/DFHack/dfhack) at the commit the running
|
|
82
|
+
> build reports via `getGitDescription`). To retarget another version, replace
|
|
83
|
+
> the files from the matching tag and re-run `npm run gen-proto`. Method
|
|
84
|
+
> input/output types in `METHODS` (`src/methods.ts`) are fully-qualified names
|
|
85
|
+
> that must match DFHack's registration, or `BindMethod` reports a "wrong
|
|
86
|
+
> signature" at runtime — which makes drift detectable per method.
|
|
87
|
+
|
|
88
|
+
## Scripts
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
npm run build # gen-proto + tsup -> dist/ (ESM + .d.ts, proto inlined)
|
|
92
|
+
npm run gen-proto # regenerate build/proto.json from proto/*.proto
|
|
93
|
+
npm run typecheck # tsc --noEmit
|
|
94
|
+
npm run lint # eslint (flat config)
|
|
95
|
+
npm run format # prettier --write
|
|
96
|
+
npm test # offline: mock server speaks the real wire format, no game needed
|
|
97
|
+
npm run spike # live: connect to a running fort, print version + world + fort name
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`npm test` validates handshake, framing, lazy binding, protobuf round-trip, and
|
|
101
|
+
TEXT-frame capture against an in-process mock. `npm run spike` (M0) requires
|
|
102
|
+
Dwarf Fortress running with DFHack and a fort loaded.
|
|
103
|
+
|
|
104
|
+
## Protocol notes
|
|
105
|
+
|
|
106
|
+
- Handshake: client sends `DFHack?\n` + `i32(1)`, server replies `DFHack!\n` + `i32(1)`.
|
|
107
|
+
- Message header: `id:i16, pad:u16, size:i32` (little-endian), then `size` body bytes.
|
|
108
|
+
- A call's reply is zero or more `TEXT` frames (console output) followed by one
|
|
109
|
+
`RESULT` frame (reply protobuf) or one `FAIL` frame (errno in the size field).
|
|
110
|
+
- Calls are serialized — DFHack handles one at a time per socket.
|
|
111
|
+
- `GetBlockList` only returns blocks _changed since the last call_ — don't build a
|
|
112
|
+
full-map snapshot on it naively (use `ResetMapHashes` to force a resend).
|
|
113
|
+
|
|
114
|
+
## Contributing
|
|
115
|
+
|
|
116
|
+
Issues and PRs welcome. Please keep the module boundaries above intact, run
|
|
117
|
+
`npm run typecheck`, `npm run lint`, and `npm test` before opening a PR, and add
|
|
118
|
+
new RPC methods to `src/methods.ts` with their fully-qualified protobuf type
|
|
119
|
+
names. Changes touching the live protocol should be verified against a running
|
|
120
|
+
fort with `npm run spike`.
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
ISC. Ported from [alexchandel/dfhack-remote](https://github.com/alexchandel/dfhack-remote)
|
|
125
|
+
(Copyright © 2020 Alexander Chandel); the original copyright and license are
|
|
126
|
+
preserved in [LICENSE.md](./LICENSE.md).
|