pi-courier 0.1.39 → 0.1.41

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.
Files changed (40) hide show
  1. package/README.md +3 -2
  2. package/README.zh-CN.md +3 -2
  3. package/assets/avatars/instance-01.png +0 -0
  4. package/assets/avatars/instance-02.png +0 -0
  5. package/assets/avatars/instance-03.png +0 -0
  6. package/assets/avatars/instance-04.png +0 -0
  7. package/assets/avatars/instance-05.png +0 -0
  8. package/assets/avatars/instance-06.png +0 -0
  9. package/assets/avatars/instance-07.png +0 -0
  10. package/assets/avatars/instance-08.png +0 -0
  11. package/assets/avatars/instance-09.png +0 -0
  12. package/assets/avatars/instance-10.png +0 -0
  13. package/assets/avatars/instance-11.png +0 -0
  14. package/assets/avatars/instance-12.png +0 -0
  15. package/assets/avatars/management.png +0 -0
  16. package/dist/cli.js +65 -12
  17. package/dist/cli.js.map +1 -1
  18. package/dist/space-identity.d.ts +34 -0
  19. package/dist/space-identity.d.ts.map +1 -0
  20. package/dist/space-identity.js +60 -0
  21. package/dist/space-identity.js.map +1 -0
  22. package/dist/space.d.ts +20 -5
  23. package/dist/space.d.ts.map +1 -1
  24. package/dist/space.js +95 -16
  25. package/dist/space.js.map +1 -1
  26. package/dist/standalone.d.ts.map +1 -1
  27. package/dist/standalone.js +4 -1
  28. package/dist/standalone.js.map +1 -1
  29. package/dist/systemd-hint.d.ts +29 -0
  30. package/dist/systemd-hint.d.ts.map +1 -0
  31. package/dist/systemd-hint.js +51 -0
  32. package/dist/systemd-hint.js.map +1 -0
  33. package/dist/transports/interface.d.ts +13 -1
  34. package/dist/transports/interface.d.ts.map +1 -1
  35. package/dist/transports/matrix-rooms.d.ts +9 -0
  36. package/dist/transports/matrix-rooms.d.ts.map +1 -1
  37. package/dist/transports/matrix-rooms.js +42 -1
  38. package/dist/transports/matrix-rooms.js.map +1 -1
  39. package/package.json +2 -1
  40. package/scripts/generate-avatars.mjs +452 -0
@@ -0,0 +1,452 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Generate the bundled pixel avatars (assets/avatars/*.png) — 12 generic pool
4
+ * images + 1 dedicated management-room image. Blocky pixel style, 16×16 grid
5
+ * rendered at 8× (128×128), zero dependencies (zlib PNG encoder below).
6
+ *
7
+ * All artwork here is ORIGINAL — inspired by the generic "chunky pixel" /
8
+ * blocky aesthetic only. No Mojang/Microsoft assets, characters, logos,
9
+ * fonts or signature textures are reproduced; palettes are our own. If you
10
+ * swap these files for your own art, keep the filenames and the pool stays
11
+ * drop-in compatible.
12
+ *
13
+ * Usage: node scripts/generate-avatars.mjs (idempotent, rewrites the PNGs)
14
+ */
15
+
16
+ import { deflateSync } from "node:zlib";
17
+ import { mkdirSync, writeFileSync } from "node:fs";
18
+ import { dirname, join } from "node:path";
19
+ import { fileURLToPath } from "node:url";
20
+
21
+ const OUT_DIR = join(dirname(fileURLToPath(import.meta.url)), "..", "assets", "avatars");
22
+ const GRID = 16;
23
+ const SCALE = 8;
24
+ const SIZE = GRID * SCALE; // 128
25
+
26
+ // ---- tiny PNG encoder (RGBA, filter 0) -------------------------------------
27
+
28
+ const CRC_TABLE = (() => {
29
+ const table = new Uint32Array(256);
30
+ for (let n = 0; n < 256; n++) {
31
+ let c = n;
32
+ for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
33
+ table[n] = c >>> 0;
34
+ }
35
+ return table;
36
+ })();
37
+
38
+ function crc32(buf) {
39
+ let c = 0xffffffff;
40
+ for (const byte of buf) c = CRC_TABLE[(c ^ byte) & 0xff] ^ (c >>> 8);
41
+ return (c ^ 0xffffffff) >>> 0;
42
+ }
43
+
44
+ function pngChunk(type, data) {
45
+ const body = Buffer.concat([Buffer.from(type, "ascii"), data]);
46
+ const len = Buffer.alloc(4);
47
+ len.writeUInt32BE(data.length);
48
+ const crc = Buffer.alloc(4);
49
+ crc.writeUInt32BE(crc32(body));
50
+ return Buffer.concat([len, body, crc]);
51
+ }
52
+
53
+ function encodePng(width, height, rgba) {
54
+ if (rgba.length !== width * height * 4) throw new Error("rgba buffer size mismatch");
55
+ const ihdr = Buffer.alloc(13);
56
+ ihdr.writeUInt32BE(width, 0);
57
+ ihdr.writeUInt32BE(height, 4);
58
+ ihdr[8] = 8; // bit depth
59
+ ihdr[9] = 6; // color type RGBA
60
+ const raw = Buffer.alloc(height * (1 + width * 4));
61
+ for (let y = 0; y < height; y++) {
62
+ raw[y * (1 + width * 4)] = 0; // filter: none
63
+ rgba.copy(raw, y * (1 + width * 4) + 1, y * width * 4, (y + 1) * width * 4);
64
+ }
65
+ return Buffer.concat([
66
+ Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
67
+ pngChunk("IHDR", ihdr),
68
+ pngChunk("IDAT", deflateSync(raw, { level: 9 })),
69
+ pngChunk("IEND", Buffer.alloc(0)),
70
+ ]);
71
+ }
72
+
73
+ // ---- sprite machinery -------------------------------------------------------
74
+
75
+ function hexToRgb(hex) {
76
+ const value = Number.parseInt(hex.replace("#", ""), 16);
77
+ return [(value >> 16) & 0xff, (value >> 8) & 0xff, value & 0xff];
78
+ }
79
+
80
+ /** Minecraft-ish "block" backdrop: dark outer frame, light top/left inner
81
+ * bevel, sparse dark speckle inside — deterministic per seed. */
82
+ function backdropColor(x, y, bg, seed) {
83
+ if (x === 0 || y === 0 || x === 15 || y === 15) return bg.dark;
84
+ if (x === 1 || y === 1) return bg.light;
85
+ return (x * 7 + y * 13 + seed * 31) % 9 === 0 ? bg.dark : bg.base;
86
+ }
87
+
88
+ function validateArt(art, name) {
89
+ art.forEach((row, y) => {
90
+ if (row.length > GRID) throw new Error(`${name} row ${y} longer than ${GRID}: "${row}"`);
91
+ });
92
+ if (art.length > GRID) throw new Error(`${name} has more than ${GRID} rows`);
93
+ }
94
+
95
+ function renderSprite(sprite) {
96
+ validateArt(sprite.art, sprite.file);
97
+ const rgba = Buffer.alloc(SIZE * SIZE * 4);
98
+ const palette = Object.fromEntries(Object.entries(sprite.colors).map(([k, v]) => [k, hexToRgb(v)]));
99
+ for (const key of Object.keys(sprite.colors)) {
100
+ if (key.length !== 1 || key === ".") throw new Error(`${sprite.file}: bad palette key "${key}"`);
101
+ }
102
+ for (let cy = 0; cy < GRID; cy++) {
103
+ for (let cx = 0; cx < GRID; cx++) {
104
+ const char = sprite.art[cy]?.[cx] ?? ".";
105
+ let rgb;
106
+ if (char === ".") rgb = backdropColor(cx, cy, sprite.bg, sprite.seed);
107
+ else {
108
+ rgb = palette[char];
109
+ if (!rgb) throw new Error(`${sprite.file}: unknown char "${char}" at ${cx},${cy}`);
110
+ }
111
+ for (let py = 0; py < SCALE; py++) {
112
+ for (let px = 0; px < SCALE; px++) {
113
+ const offset = ((cy * SCALE + py) * SIZE + cx * SCALE + px) * 4;
114
+ rgba[offset] = rgb[0];
115
+ rgba[offset + 1] = rgb[1];
116
+ rgba[offset + 2] = rgb[2];
117
+ rgba[offset + 3] = 255;
118
+ }
119
+ }
120
+ }
121
+ }
122
+ return encodePng(SIZE, SIZE, rgba);
123
+ }
124
+
125
+ // ---- the 12 pool sprites + management --------------------------------------
126
+ // '.' = backdrop block; every other char maps to a color in `colors`.
127
+ // Rows shorter than 16 are padded with '.' on the right.
128
+
129
+ const sprites = [
130
+ {
131
+ file: "instance-01.png",
132
+ seed: 1,
133
+ bg: { base: "#3a3f4a", dark: "#262a33", light: "#4d5461" },
134
+ colors: { P: "#f6a821", p: "#c67f10" },
135
+ art: [
136
+ "................",
137
+ "................",
138
+ "................",
139
+ "...PPPPPPPPPP...",
140
+ "...PPPPPPPPPP...",
141
+ "...PPPPPPPPPP...",
142
+ "...PP....PP.....",
143
+ "...PP....PP.....",
144
+ "...PP....PP.....",
145
+ "...PP....PP.....",
146
+ "...PP....PP.....",
147
+ "...PP....PP.....",
148
+ "...pp....pp.....",
149
+ "................",
150
+ "................",
151
+ "................",
152
+ ],
153
+ },
154
+ {
155
+ file: "instance-02.png",
156
+ seed: 2,
157
+ bg: { base: "#4a3a66", dark: "#33284a", light: "#5d4a7d" },
158
+ colors: { L: "#eae4ff", l: "#bfa9e6", s: "#ffd76e" },
159
+ art: [
160
+ "................",
161
+ ".s.....s......s.",
162
+ "..............s.",
163
+ "...LLLLLLLLLL...",
164
+ "...LLLLLLLLLL...",
165
+ "...LLLLLLLLLL...",
166
+ "...LL....LL.....",
167
+ "...LL....LL.....",
168
+ "...LL....LL.....",
169
+ "...LL....LL.....",
170
+ "...LL....LL.....",
171
+ "...LL....LL.....",
172
+ "...ll....ll..s..",
173
+ ".s..............",
174
+ "................",
175
+ "................",
176
+ ],
177
+ },
178
+ {
179
+ file: "instance-03.png",
180
+ seed: 3,
181
+ bg: { base: "#2e6e6a", dark: "#1f4f4c", light: "#3d8a85" },
182
+ colors: { o: "#16403d", b: "#7fd6c9", l: "#a9e8de", w: "#f4fefe", p: "#10312e", m: "#16403d", e: "#55b3a5", a: "#d8f5ef" },
183
+ art: [
184
+ ".......aa.......",
185
+ ".......oo.......",
186
+ "..oooooooooooo..",
187
+ "..ollllllllllo..",
188
+ "..obbbbbbbbbbo..",
189
+ "..obwwbbbbwwbo..",
190
+ ".eobwpbbbbwpboe.",
191
+ ".eobbbbbbbbbboe.",
192
+ ".eobbbbbbbbbboe.",
193
+ "..obmmmmmmmmbo",
194
+ "..obbbbbbbbbbo..",
195
+ "..oooooooooooo..",
196
+ "................",
197
+ "................",
198
+ "................",
199
+ "................",
200
+ ],
201
+ },
202
+ {
203
+ file: "instance-04.png",
204
+ seed: 4,
205
+ bg: { base: "#7a4423", dark: "#59301a", light: "#96582e" },
206
+ colors: { o: "#4a2a14", b: "#f2a65a", l: "#f8c48c", p: "#3a2109", m: "#4a2a14" },
207
+ art: [
208
+ "..ll........ll..",
209
+ "..ll........ll..",
210
+ "..oooooooooooo..",
211
+ "..ollllllllllo..",
212
+ "..obbbbbbbbbbo..",
213
+ "..obpbbbbbbpbo..",
214
+ "..obpbbbbbbpbo..",
215
+ "..obbbbbbbbbbo..",
216
+ "..obbmmmmmmbbo..",
217
+ "..obbbbbbbbbbo..",
218
+ "..oooooooooooo..",
219
+ "................",
220
+ "................",
221
+ "................",
222
+ "................",
223
+ "................",
224
+ ],
225
+ },
226
+ {
227
+ file: "instance-05.png",
228
+ seed: 5,
229
+ bg: { base: "#6b6f76", dark: "#4c5057", light: "#82868e" },
230
+ colors: { o: "#1e5f73", L: "#bdf3f7", M: "#59c8dd", D: "#2f8fa8" },
231
+ art: [
232
+ "................",
233
+ "................",
234
+ "......oooo......",
235
+ ".....oLLLoo.....",
236
+ "....oLLMMMo.....",
237
+ "...oLLMMMMDo....",
238
+ "..oLLMMMMMDDo...",
239
+ "..oLMMMMMDDDo...",
240
+ "...oMMMMDDDo....",
241
+ "....oMMMDDo.....",
242
+ ".....oMDDo......",
243
+ "......oDDo......",
244
+ ".......oo.......",
245
+ "................",
246
+ "................",
247
+ "................",
248
+ ],
249
+ },
250
+ {
251
+ file: "instance-06.png",
252
+ seed: 6,
253
+ bg: { base: "#2f6b33", dark: "#1f4a23", light: "#3d8442" },
254
+ colors: { t: "#ffd76e", d: "#fff3c4", c: "#23343f", p: "#ffd76e", G: "#ffe9a8" },
255
+ art: [
256
+ "................",
257
+ "................",
258
+ ".......dd.......",
259
+ ".......tt.......",
260
+ ".......tt.......",
261
+ "....pccccccp....",
262
+ "....pccccccp....",
263
+ ".dttpccGGccp....",
264
+ ".dttpccGGccptttd",
265
+ "....pccccccp...t",
266
+ "....pccccccp...t",
267
+ ".......tt......t",
268
+ ".......dd......d",
269
+ "................",
270
+ "................",
271
+ "................",
272
+ ],
273
+ },
274
+ {
275
+ file: "instance-07.png",
276
+ seed: 7,
277
+ bg: { base: "#4a4a55", dark: "#35353e", light: "#5c5c68" },
278
+ colors: { o: "#2c2c34", b: "#c9ccd4", p: "#f0a7b8", E: "#9fe06f", P: "#23301b", n: "#e88aa0" },
279
+ art: [
280
+ "................",
281
+ "..oo........oo..",
282
+ "..opo......opo..",
283
+ "..oppo....oppo..",
284
+ "..oooooooooooo..",
285
+ "..obbbbbbbbbbo..",
286
+ "..obbbbbbbbbbo..",
287
+ "..obEEbbbbEEbo..",
288
+ "..obEPbbbbEPbo..",
289
+ "..obbbbbbbbbbo..",
290
+ "..obbbnnbbbbo...",
291
+ "..obbbbbbbbbbo..",
292
+ "..obbbbbbbbbbo..",
293
+ "..oooooooooooo..",
294
+ "................",
295
+ "................",
296
+ ],
297
+ },
298
+ {
299
+ file: "instance-08.png",
300
+ seed: 8,
301
+ bg: { base: "#5a4632", dark: "#40321f", light: "#6f5840" },
302
+ colors: { o: "#33261a", b: "#a9793f", w: "#f7f3e8", p: "#2b1d10", n: "#f0a03c", f: "#c79459" },
303
+ art: [
304
+ "................",
305
+ ".o............o.",
306
+ ".oo..........oo.",
307
+ "..oooooooooooo..",
308
+ "..owwwbbbbwwwo..",
309
+ "..owpwbbbbwpwo..",
310
+ "..owwwbbbbwwwo..",
311
+ "..obbbbnnbbbbo..",
312
+ "..obbbbbbbbbbo..",
313
+ "..obfbbbbfbbbo..",
314
+ "..obbbbbbbbbbo..",
315
+ "..obfbbbbfbbbo..",
316
+ "..oooooooooooo..",
317
+ "...nn......nn...",
318
+ "................",
319
+ "................",
320
+ ],
321
+ },
322
+ {
323
+ file: "instance-09.png",
324
+ seed: 9,
325
+ bg: { base: "#232a4a", dark: "#171c33", light: "#2f3860" },
326
+ colors: { r: "#e05252", R: "#b03a3a", w: "#f2f4f8", c: "#8fd8e8", f: "#ffb347", y: "#ffe08a", s: "#cfd6f0" },
327
+ art: [
328
+ "................",
329
+ ".......rr.....s.",
330
+ "..s...rrrr......",
331
+ "......wwww......",
332
+ "......wccw....s.",
333
+ "......wccw......",
334
+ "......wwww......",
335
+ "......wwww......",
336
+ "......wwww......",
337
+ "..RR..wwww..RR..",
338
+ "..RRr.wwww.rRR..",
339
+ "....rrwwwwrr....",
340
+ "..s....ff.......",
341
+ ".......yy.......",
342
+ "................",
343
+ "................",
344
+ ],
345
+ },
346
+ {
347
+ file: "instance-10.png",
348
+ seed: 10,
349
+ bg: { base: "#6d5140", dark: "#4f3a2d", light: "#836552" },
350
+ colors: { g: "#6fc26f", d: "#4a9e4a", p: "#e08a5f", P: "#c96f4a", q: "#a3532f", o: "#7a3f22" },
351
+ art: [
352
+ "................",
353
+ "................",
354
+ "..ggg......ggg..",
355
+ ".ggggg....ggggg.",
356
+ ".gggggg..gggggg.",
357
+ "..gggggddggggg..",
358
+ ".......gg.......",
359
+ ".......gg.......",
360
+ ".......gg.......",
361
+ "...pppppppppp...",
362
+ "...PPPPPPPPPq...",
363
+ "...PPPPPPPPPq...",
364
+ "....PPPPPPqq....",
365
+ ".....oooooo.....",
366
+ "................",
367
+ "................",
368
+ ],
369
+ },
370
+ {
371
+ file: "instance-11.png",
372
+ seed: 11,
373
+ bg: { base: "#3a4150", dark: "#282e3a", light: "#4a5263" },
374
+ colors: { o: "#1f242e", S: "#0d1f16", G: "#7ee787", B: "#8a93a5", b: "#6a7284" },
375
+ art: [
376
+ "................",
377
+ "................",
378
+ ".oooooooooooooo.",
379
+ ".oSSSSSSSSSSSSo.",
380
+ ".oSGGGGSSSSSSSo.",
381
+ ".oSSSSSSSSSSSSo.",
382
+ ".oSGGSSSSSSSSSo.",
383
+ ".oSSSSSSGGSSSSo.",
384
+ ".oSSSSSSSSSSSSo.",
385
+ ".oooooooooooooo.",
386
+ ".oooooooooooooo.",
387
+ ".obBBBBBBBBBBbo.",
388
+ "................",
389
+ "................",
390
+ "................",
391
+ "................",
392
+ ],
393
+ },
394
+ {
395
+ file: "instance-12.png",
396
+ seed: 12,
397
+ bg: { base: "#8a3a3a", dark: "#672a2a", light: "#a34a4a" },
398
+ colors: { o: "#3a3430", w: "#f7f4ec", p: "#2f2b28" },
399
+ art: [
400
+ "................",
401
+ "................",
402
+ "..oooooooooo....",
403
+ "..owwwwwwwwwo...",
404
+ "..owppwwwwppwo..",
405
+ "..owppwwwwppwo..",
406
+ "..owwwwwwwwwo...",
407
+ "..owwwwppwwwwo..",
408
+ "..owwwwppwwwwo..",
409
+ "..owwwwwwwwwo...",
410
+ "..owppwwwwppwo..",
411
+ "..owppwwwwppwo..",
412
+ "..owwwwwwwwwo...",
413
+ "..oooooooooo....",
414
+ "................",
415
+ "................",
416
+ ],
417
+ },
418
+ {
419
+ file: "management.png",
420
+ seed: 13,
421
+ bg: { base: "#2c3350", dark: "#1f2440", light: "#3a4266" },
422
+ colors: { g: "#ffd45e", d: "#d9a92e", R: "#e05252", C: "#59c8dd" },
423
+ art: [
424
+ "................",
425
+ "................",
426
+ "................",
427
+ "................",
428
+ "..g...gg...g....",
429
+ "..gg..gg..gg....",
430
+ ".gggg.gg.gg.ggg.",
431
+ ".gggggggggggggg.",
432
+ ".gRgCggRgCggRgg.",
433
+ ".gggggggggggggg.",
434
+ ".dddddddddddddd.",
435
+ "................",
436
+ "................",
437
+ "................",
438
+ "................",
439
+ "................",
440
+ ],
441
+ },
442
+ ];
443
+
444
+ // ---- run --------------------------------------------------------------------
445
+
446
+ mkdirSync(OUT_DIR, { recursive: true });
447
+ for (const sprite of sprites) {
448
+ const png = renderSprite(sprite);
449
+ writeFileSync(join(OUT_DIR, sprite.file), png);
450
+ console.log(`✔ ${sprite.file} (${png.length} bytes)`);
451
+ }
452
+ console.log(`\n${sprites.length} avatars written to ${OUT_DIR}`);