dsh-wisp 0.6.0 → 1.25.1
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/README.md +869 -10
- package/assets/canon/attn.webp +0 -0
- package/assets/canon/happy.webp +0 -0
- package/assets/canon/idle.webp +0 -0
- package/assets/canon/poked.webp +0 -0
- package/assets/canon/proud.webp +0 -0
- package/assets/canon/sleepy.webp +0 -0
- package/assets/canon/work.webp +0 -0
- package/assets/classic/attn.webp +0 -0
- package/assets/classic/happy.webp +0 -0
- package/assets/classic/idle.webp +0 -0
- package/assets/classic/poked.webp +0 -0
- package/assets/classic/proud.webp +0 -0
- package/assets/classic/sleepy.webp +0 -0
- package/assets/classic/work.webp +0 -0
- package/assets/deepsea/attn.webp +0 -0
- package/assets/deepsea/happy.webp +0 -0
- package/assets/deepsea/idle.webp +0 -0
- package/assets/deepsea/poked.webp +0 -0
- package/assets/deepsea/proud.webp +0 -0
- package/assets/deepsea/sleepy.webp +0 -0
- package/assets/deepsea/work.webp +0 -0
- package/assets/night/attn.webp +0 -0
- package/assets/night/happy.webp +0 -0
- package/assets/night/idle.webp +0 -0
- package/assets/night/poked.webp +0 -0
- package/assets/night/proud.webp +0 -0
- package/assets/night/sleepy.webp +0 -0
- package/assets/night/work.webp +0 -0
- package/assets/pajama/attn.webp +0 -0
- package/assets/pajama/happy.webp +0 -0
- package/assets/pajama/idle.webp +0 -0
- package/assets/pajama/poked.webp +0 -0
- package/assets/pajama/proud.webp +0 -0
- package/assets/pajama/sleepy.webp +0 -0
- package/assets/pajama/work.webp +0 -0
- package/audit/generation-audit.jsonl +35 -0
- package/build.mjs +93 -30
- package/cordis.patch.yml +2 -0
- package/lib/client.js +1293 -41
- package/lib/client.template.js +1248 -37
- package/lib/index.js +115 -12
- package/package.json +8 -1
- package/tools/CHARACTER-PROMPT.md +221 -3
- package/tools/assets.mjs +39 -16
- package/tools/audit-log.mjs +245 -0
- package/tools/bundle-cost.mjs +105 -0
- package/tools/pack-check.mjs +78 -0
- package/tools/perf.mjs +186 -0
- package/tools/smoke.mjs +577 -0
- package/tools/tiers.mjs +104 -0
- package/verify-wisp.mjs +2681 -872
- package/assets/happy.webp +0 -0
- package/assets/happy_hi.webp +0 -0
- package/assets/happy_md.webp +0 -0
- package/assets/happy_sm.webp +0 -0
- package/assets/idle.webp +0 -0
- package/assets/idle_hi.webp +0 -0
- package/assets/idle_md.webp +0 -0
- package/assets/idle_sm.webp +0 -0
- package/assets/sleepy.webp +0 -0
- package/assets/sleepy_hi.webp +0 -0
- package/assets/sleepy_md.webp +0 -0
- package/assets/sleepy_sm.webp +0 -0
- package/assets/work.webp +0 -0
- package/assets/work_hi.webp +0 -0
- package/assets/work_md.webp +0 -0
- package/assets/work_sm.webp +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{"index":0,"prev":"genesis","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.298Z","name":"canon_idle","skin":"canon","mood":"idle","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T18:55:39.243Z","localPath":"assets/image/canon_idle_20260929185539.png"},"master":{"path":"F:\\孤屿\\assets\\image\\canon_idle_20260929185539.png","sha256":"8a783a679ae8d9f4f28449741d8d941acae641377f864126c28e623531d04c2c"},"output":{"path":"assets/canon/idle.webp","sha256":"9174b21d6852d86debfed174889d96b2bf00d0b7952e34ad62bca547cd397718","bytes":127654},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"15d6e4ef4bf8130b2bd6427dabe787a0380613fc484794bb0bf2bdf9ece65c6f"}
|
|
2
|
+
{"index":1,"prev":"15d6e4ef4bf8130b2bd6427dabe787a0380613fc484794bb0bf2bdf9ece65c6f","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.319Z","name":"canon_happy","skin":"canon","mood":"happy","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T18:55:39.243Z","localPath":"assets/image/canon_happy_20260929185539.png"},"master":{"path":"F:\\孤屿\\assets\\image\\canon_happy_20260929185539.png","sha256":"32056f976afbc67a946b8a48be7af0fda4adac47addb34412c6177cd4f30d6db"},"output":{"path":"assets/canon/happy.webp","sha256":"9b0fa81076cf4b02a98285e88342098cadac05833d6523a532442ad62758e1b3","bytes":142168},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"9324e910d706ed0ec7533cad7e910a43a9c5f802560e78bc4dc066fb802a4a3f"}
|
|
3
|
+
{"index":2,"prev":"9324e910d706ed0ec7533cad7e910a43a9c5f802560e78bc4dc066fb802a4a3f","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.332Z","name":"canon_sleepy","skin":"canon","mood":"sleepy","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T18:55:39.243Z","localPath":"assets/image/canon_sleepy_20260929185539.png"},"master":{"path":"F:\\孤屿\\assets\\image\\canon_sleepy_20260929185539.png","sha256":"c92d56846c975b834292a937c4473ebb0d38a4d108ec1fb8cb0e6b5d668869d9"},"output":{"path":"assets/canon/sleepy.webp","sha256":"46b7c22d182aa29831756b6ced708c1398584e4289650378a8d51e070eb1f42a","bytes":123758},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"4e788be0a802428d1d21a66e2bf460becf51db7006d2f91018bcf382456f4c98"}
|
|
4
|
+
{"index":3,"prev":"4e788be0a802428d1d21a66e2bf460becf51db7006d2f91018bcf382456f4c98","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.345Z","name":"canon_work","skin":"canon","mood":"work","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T18:55:39.243Z","localPath":"assets/image/canon_work_20260929185539.png"},"master":{"path":"F:\\孤屿\\assets\\image\\canon_work_20260929185539.png","sha256":"57bd85febfbda157e9fe1d6775c93414763443b1781fda922069ec800ae480a0"},"output":{"path":"assets/canon/work.webp","sha256":"7c35eb87f563a05a99d26c4ebba1fc0bfee051a3bf52a5815bc596a9b6286eca","bytes":149982},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"8bb71551d74d7d95fa4d98a13e71ef808b4edcdfdc050f68cc60e0d5268b26e1"}
|
|
5
|
+
{"index":4,"prev":"8bb71551d74d7d95fa4d98a13e71ef808b4edcdfdc050f68cc60e0d5268b26e1","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.357Z","name":"canon_attn","skin":"canon","mood":"attn","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T18:55:39.243Z","localPath":"assets/image/canon_attn_20260929185539.png"},"master":{"path":"F:\\孤屿\\assets\\image\\canon_attn_20260929185539.png","sha256":"e28c2e204e6bb0666ff8c862dd59d91470830ac7362d7a5027051f995c256a3d"},"output":{"path":"assets/canon/attn.webp","sha256":"1f7dfd6a69253e28824b200ffca767c9f651a76f86517a82d670f5fdfd018bc3","bytes":140564},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"c7f6190dc071fb03b2630c5271e6a4ddeb440780f4414e6be092cfce0d0c0684"}
|
|
6
|
+
{"index":5,"prev":"c7f6190dc071fb03b2630c5271e6a4ddeb440780f4414e6be092cfce0d0c0684","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.370Z","name":"canon_poked","skin":"canon","mood":"poked","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T18:55:39.243Z","localPath":"assets/image/canon_poked_20260929185539.png"},"master":{"path":"F:\\孤屿\\assets\\image\\canon_poked_20260929185539.png","sha256":"98817f78a9c01d9e3648abf71413d54bd8890a01bf3c67a3aa18053ac4dba4b2"},"output":{"path":"assets/canon/poked.webp","sha256":"4985bb577c2a49585654efd08246897ad7c9c7d434f27c5b497b7b2d3842434b","bytes":138386},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"89580b20e033bb0b26c5b94f70d003ab67e77e700e1c414caff937e22d2e163e"}
|
|
7
|
+
{"index":6,"prev":"89580b20e033bb0b26c5b94f70d003ab67e77e700e1c414caff937e22d2e163e","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.378Z","name":"canon_proud","skin":"canon","mood":"proud","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T18:55:39.243Z","localPath":"assets/image/canon_proud_20260929185539.png"},"master":{"path":"F:\\孤屿\\assets\\image\\canon_proud_20260929185539.png","sha256":"b15bc63be53650bec6abd9a7ee5b081766bc63a03b95af83873b4fe103422f4a"},"output":{"path":"assets/canon/proud.webp","sha256":"66f2a008cc98d4348877e7aaa9ecdb125c11d80d79bbf90a7ffa516effd4b3f2","bytes":124790},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"1ec1dd07061f458ed00ccfc1dd1d230d42b69f7699316340baeab0f7ecd4056f"}
|
|
8
|
+
{"index":7,"prev":"1ec1dd07061f458ed00ccfc1dd1d230d42b69f7699316340baeab0f7ecd4056f","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.391Z","name":"ds2_idle","skin":"deepsea","mood":"idle","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:11:36.911Z","localPath":"assets/image/ds2_idle_20260929191136.png"},"master":{"path":"F:\\孤屿\\assets\\image\\ds2_idle_20260929191136.png","sha256":"a77a3f62f253dff5f64f069091cfad4004bc31eb82f30af3e3a976baa2b487b2"},"output":{"path":"assets/deepsea/idle.webp","sha256":"bc396c646d8a45b6796d23f790db85af148e7c79323175aa328ee9fd208bf6b8","bytes":107130},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"1bdbc9d854996d0fae1db579be27665958a854ebdc44008f171037c1fc072416"}
|
|
9
|
+
{"index":8,"prev":"1bdbc9d854996d0fae1db579be27665958a854ebdc44008f171037c1fc072416","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.398Z","name":"ds2_happy","skin":"deepsea","mood":"happy","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:11:36.911Z","localPath":"assets/image/ds2_happy_20260929191136.png"},"master":{"path":"F:\\孤屿\\assets\\image\\ds2_happy_20260929191136.png","sha256":"cf589754e8b6eb69abc84e28634c4bebd990b60151d8e78c15de81cc46c3dfa3"},"output":{"path":"assets/deepsea/happy.webp","sha256":"df00f27cf0bcd880a1e4d59e86971dcf2321c09ca8495c7eca507f2caf979195","bytes":114128},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"e9d9010d1c09954f63841904a884280ff8d5cba808f079aa867ce33113b536a8"}
|
|
10
|
+
{"index":9,"prev":"e9d9010d1c09954f63841904a884280ff8d5cba808f079aa867ce33113b536a8","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.406Z","name":"ds2_sleepy","skin":"deepsea","mood":"sleepy","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:11:36.911Z","localPath":"assets/image/ds2_sleepy_20260929191136.png"},"master":{"path":"F:\\孤屿\\assets\\image\\ds2_sleepy_20260929191136.png","sha256":"fa074e2609e73710d188a22a23f9e516032ca0bf6caf0a432459047e838e3d29"},"output":{"path":"assets/deepsea/sleepy.webp","sha256":"49a6f6e7397669703bf6a3f5d75f36e410cef5d732b1bc0dcdb362bbcea55d32","bytes":119086},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"0d06b5a71af7780de15e5842e6218488b947d8776bb070c685227ae175e70cf5"}
|
|
11
|
+
{"index":10,"prev":"0d06b5a71af7780de15e5842e6218488b947d8776bb070c685227ae175e70cf5","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.413Z","name":"ds2_work","skin":"deepsea","mood":"work","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:11:36.911Z","localPath":"assets/image/ds2_work_20260929191136.png"},"master":{"path":"F:\\孤屿\\assets\\image\\ds2_work_20260929191136.png","sha256":"65be6ab099bd98a3d9880ee97dccb25be76b8a0d0efa0802a196babfc7aa6fca"},"output":{"path":"assets/deepsea/work.webp","sha256":"c866fc507ca6173222c1a80ae49f6657aa5068fece93ae8e014ddca35c8b60e8","bytes":110934},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"8f0cb34856c53f3fcea92ec0c8ae637bd3bb71ee70fe7a4d82e52ce6e7a2a059"}
|
|
12
|
+
{"index":11,"prev":"8f0cb34856c53f3fcea92ec0c8ae637bd3bb71ee70fe7a4d82e52ce6e7a2a059","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.420Z","name":"ds2_attn","skin":"deepsea","mood":"attn","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:11:36.911Z","localPath":"assets/image/ds2_attn_20260929191136.png"},"master":{"path":"F:\\孤屿\\assets\\image\\ds2_attn_20260929191136.png","sha256":"3bcfe7ac73469daf1ad3c303db1fd1dea9719ec5d0dd7c7a0b64f01261e6cc67"},"output":{"path":"assets/deepsea/attn.webp","sha256":"7debb4a21ecc4e25ed45c913eb248978d11725325b0dc82426b058d7451528b3","bytes":99666},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"3a4594e088a2b5c241601dfea68cf319b88a4047fe6ab16fc1c4e3dd3e7cb441"}
|
|
13
|
+
{"index":12,"prev":"3a4594e088a2b5c241601dfea68cf319b88a4047fe6ab16fc1c4e3dd3e7cb441","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.428Z","name":"ds2_poked","skin":"deepsea","mood":"poked","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:11:36.911Z","localPath":"assets/image/ds2_poked_20260929191136.png"},"master":{"path":"F:\\孤屿\\assets\\image\\ds2_poked_20260929191136.png","sha256":"8383d5294c26873c1ed9e134bba0c7be5a53df5a046caeba5a15ed721cbc12b2"},"output":{"path":"assets/deepsea/poked.webp","sha256":"780dbe8ea3680ce6d59b6e28c37319f49d7c56c6e25010187f5a9c3896751351","bytes":108474},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"e676a785f7104154390c23ba06778bafffcf736d6277e857f3c6216fcf7af056"}
|
|
14
|
+
{"index":13,"prev":"e676a785f7104154390c23ba06778bafffcf736d6277e857f3c6216fcf7af056","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.435Z","name":"ds2_proud","skin":"deepsea","mood":"proud","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:11:36.911Z","localPath":"assets/image/ds2_proud_20260929191136.png"},"master":{"path":"F:\\孤屿\\assets\\image\\ds2_proud_20260929191136.png","sha256":"0809dbc6e92280a811d613b9562e2e295a19a9fa2fce725d91d76826d825fec9"},"output":{"path":"assets/deepsea/proud.webp","sha256":"f345e814c54b926c6fa96765fa0de1e9ff2b9bb3909c0a0d534d5c7bc5d7574a","bytes":99244},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"1e3b15612c6e94699298850086ab3ecf44d98f2ca1cd59925b8b1a43a4cdd69d"}
|
|
15
|
+
{"index":14,"prev":"1e3b15612c6e94699298850086ab3ecf44d98f2ca1cd59925b8b1a43a4cdd69d","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.443Z","name":"cl2_idle","skin":"classic","mood":"idle","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:12:47.023Z","localPath":"assets/image/cl2_idle_20260929191247.png"},"master":{"path":"F:\\孤屿\\assets\\image\\cl2_idle_20260929191247.png","sha256":"a69ad868558b9efa366ee8925d866758c8b95c47b7342b64a22ae3af7c75e7b6"},"output":{"path":"assets/classic/idle.webp","sha256":"c6393fa555c6986493f0b8d95bbb538d6bdd99415b019e2fc0078d346a7a476a","bytes":88366},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"cb25df478bc1111916e415dc72e3c1ce1cb0db50e1de9abdb7390ea1945c11f1"}
|
|
16
|
+
{"index":15,"prev":"cb25df478bc1111916e415dc72e3c1ce1cb0db50e1de9abdb7390ea1945c11f1","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.449Z","name":"cl2_happy","skin":"classic","mood":"happy","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:12:47.023Z","localPath":"assets/image/cl2_happy_20260929191247.png"},"master":{"path":"F:\\孤屿\\assets\\image\\cl2_happy_20260929191247.png","sha256":"5c7e0e245dfab050ebd31d57dd2685eb356a5c000c8d8b830791854e63acc50e"},"output":{"path":"assets/classic/happy.webp","sha256":"f7e7007f07a7e97398769ef70fec54b48c2f27a3d2301e0bcbc4f28ecd59366c","bytes":108522},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"9435e761fb1171539c3e25712f64b47d5d8314f93cc774f1e22955e21e5602b7"}
|
|
17
|
+
{"index":16,"prev":"9435e761fb1171539c3e25712f64b47d5d8314f93cc774f1e22955e21e5602b7","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.456Z","name":"cl2_sleepy","skin":"classic","mood":"sleepy","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:12:47.023Z","localPath":"assets/image/cl2_sleepy_20260929191247.png"},"master":{"path":"F:\\孤屿\\assets\\image\\cl2_sleepy_20260929191247.png","sha256":"9dc80c6c74740808f9f9fc96c5b0606fd2da6f3c52ec6bdb6fe070952593a551"},"output":{"path":"assets/classic/sleepy.webp","sha256":"706b718e4ea9fcaa882c41e21721d1ea1bdcb70de4015621946db6b8b9c7a5a8","bytes":99548},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"fea15f42792ad86d4cfdc7e2864e06709cb8660f5b8bbebb5d5017e8f5b11246"}
|
|
18
|
+
{"index":17,"prev":"fea15f42792ad86d4cfdc7e2864e06709cb8660f5b8bbebb5d5017e8f5b11246","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.462Z","name":"cl2_work","skin":"classic","mood":"work","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:12:47.023Z","localPath":"assets/image/cl2_work_20260929191247.png"},"master":{"path":"F:\\孤屿\\assets\\image\\cl2_work_20260929191247.png","sha256":"28e68495eb2fa2d94839899c3468af3470eaa18b62b1ff9bc82ed5f944a2fd98"},"output":{"path":"assets/classic/work.webp","sha256":"771acaf447a12582766f12ea36a8c9fe55406e177660337e5a1ba9ff92745f0f","bytes":93002},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"e574de66e7b953d8409688423777e876388f7a524793427de569d05d3f789382"}
|
|
19
|
+
{"index":18,"prev":"e574de66e7b953d8409688423777e876388f7a524793427de569d05d3f789382","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.470Z","name":"cl2_attn","skin":"classic","mood":"attn","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:12:47.023Z","localPath":"assets/image/cl2_attn_20260929191247.png"},"master":{"path":"F:\\孤屿\\assets\\image\\cl2_attn_20260929191247.png","sha256":"b1ff0d8f1253bed3537cdfae9af5e36aeb90c61661406f1ad1d66d724ba9ef70"},"output":{"path":"assets/classic/attn.webp","sha256":"9b4b1e589a3bdab1c838e0aabed9194931b4179a6a6d3f0635d68224f686370b","bytes":98708},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"2ac82169391a9796708877205340dee915e03cf518a111e97b6608fb5b8c9ffa"}
|
|
20
|
+
{"index":19,"prev":"2ac82169391a9796708877205340dee915e03cf518a111e97b6608fb5b8c9ffa","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.477Z","name":"cl2_poked","skin":"classic","mood":"poked","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:12:47.023Z","localPath":"assets/image/cl2_poked_20260929191247.png"},"master":{"path":"F:\\孤屿\\assets\\image\\cl2_poked_20260929191247.png","sha256":"c570d4d8e085745f70c472bbc6a7c9c0f4902cd068d6c926b3b8c1fbffc2d4a4"},"output":{"path":"assets/classic/poked.webp","sha256":"bd1ffc78b8534a68df36b28a9482a1ca1c0d02d618c21add5e01d92e8eed924e","bytes":93084},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"213effbecc7233a3cb74706b5c4f6dd731399ddc8b91d4f4d963c1cb9c407e10"}
|
|
21
|
+
{"index":20,"prev":"213effbecc7233a3cb74706b5c4f6dd731399ddc8b91d4f4d963c1cb9c407e10","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.485Z","name":"cl2_proud","skin":"classic","mood":"proud","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:12:47.023Z","localPath":"assets/image/cl2_proud_20260929191247.png"},"master":{"path":"F:\\孤屿\\assets\\image\\cl2_proud_20260929191247.png","sha256":"37577b9fb448bca9ec4edcdd14d261681fa647d8f8487611e271bc518eb17683"},"output":{"path":"assets/classic/proud.webp","sha256":"32247eb59fbb7c0e951397811184c73b96705469fa945cc214744787f696e69e","bytes":91558},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"ece594c365aa5119980b713e09a1cc377c67801b7667d42b0078ffbf1f5c30a2"}
|
|
22
|
+
{"index":21,"prev":"ece594c365aa5119980b713e09a1cc377c67801b7667d42b0078ffbf1f5c30a2","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.492Z","name":"ng2_idle","skin":"night","mood":"idle","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:15:12.600Z","localPath":"assets/image/ng2_idle_20260929191512.png"},"master":{"path":"F:\\孤屿\\assets\\image\\ng2_idle_20260929191512.png","sha256":"434087975a49405aa0fd5d4a796c2dfa0312eb017ce6e949821c77c7ef0db1a2"},"output":{"path":"assets/night/idle.webp","sha256":"722ade879efb6504cb5214cbe22ecd58bffa8e2d65859f0a3a0ca40d5579d861","bytes":106974},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"2094c90fba21b38255d7016454dd99914a2c3f2085aad198d8afd5f6c9c40d5c"}
|
|
23
|
+
{"index":22,"prev":"2094c90fba21b38255d7016454dd99914a2c3f2085aad198d8afd5f6c9c40d5c","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.500Z","name":"ng2_happy","skin":"night","mood":"happy","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:15:12.600Z","localPath":"assets/image/ng2_happy_20260929191512.png"},"master":{"path":"F:\\孤屿\\assets\\image\\ng2_happy_20260929191512.png","sha256":"e96494f22c2dda357952e3795dd1ca5aa83184439185be20587864b0b2ac56ed"},"output":{"path":"assets/night/happy.webp","sha256":"8d4dca267d79274445872b50c61927dd7d25c8eacd6e6081cfee3b1903b31616","bytes":115850},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"518de521e5e4c282798771fa708004effb1c573427c1d9ca5f28f19893ac8f42"}
|
|
24
|
+
{"index":23,"prev":"518de521e5e4c282798771fa708004effb1c573427c1d9ca5f28f19893ac8f42","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.511Z","name":"ng2_sleepy","skin":"night","mood":"sleepy","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:15:12.600Z","localPath":"assets/image/ng2_sleepy_20260929191512.png"},"master":{"path":"F:\\孤屿\\assets\\image\\ng2_sleepy_20260929191512.png","sha256":"f35cf70f37849e7f3873e4b849cdc202402b3b04379cdc83bc1370d5af7223b0"},"output":{"path":"assets/night/sleepy.webp","sha256":"4b6d773fddfc8c8d9c46a0791eb278e42a3c8477ece65606e3507b8d685be21b","bytes":101618},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"92950e3c7f9ae77742ce4a8759aec32b07cb67e0843751680cdfcded9a459436"}
|
|
25
|
+
{"index":24,"prev":"92950e3c7f9ae77742ce4a8759aec32b07cb67e0843751680cdfcded9a459436","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.520Z","name":"ng2_work","skin":"night","mood":"work","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:15:12.600Z","localPath":"assets/image/ng2_work_20260929191512.png"},"master":{"path":"F:\\孤屿\\assets\\image\\ng2_work_20260929191512.png","sha256":"867295660089b85e17c39ae230bebf8cb5fc29fc26ee928ac606dbab356ea621"},"output":{"path":"assets/night/work.webp","sha256":"e335ca07b47f38e4adbabe0ac5bd10129d68f7d73842523ca513cf2178c4a254","bytes":110360},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"c5b3546a709d32ab89089cea464ee6c42faf7a8d5be8ab682094489a868b8e09"}
|
|
26
|
+
{"index":25,"prev":"c5b3546a709d32ab89089cea464ee6c42faf7a8d5be8ab682094489a868b8e09","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.530Z","name":"ng2_attn","skin":"night","mood":"attn","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:15:12.600Z","localPath":"assets/image/ng2_attn_20260929191512.png"},"master":{"path":"F:\\孤屿\\assets\\image\\ng2_attn_20260929191512.png","sha256":"4efabc805024f00b456dc18533ddb1c409064b0ef78759463ee36b00f182efd1"},"output":{"path":"assets/night/attn.webp","sha256":"1d3c5208bbf4ad6135a27c5184fdddc4d76b6fc815c2ec38dfdde67b7501684d","bytes":98214},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"bf66d2d13302e29575042e3a7dde276459c54590e156ec11de890b93bb76379f"}
|
|
27
|
+
{"index":26,"prev":"bf66d2d13302e29575042e3a7dde276459c54590e156ec11de890b93bb76379f","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.537Z","name":"ng2_poked","skin":"night","mood":"poked","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:15:12.600Z","localPath":"assets/image/ng2_poked_20260929191512.png"},"master":{"path":"F:\\孤屿\\assets\\image\\ng2_poked_20260929191512.png","sha256":"c886b7b6f4661f107a4b66a4fec7811988b74ca75ae20e33ce264b32b2c38f82"},"output":{"path":"assets/night/poked.webp","sha256":"ddead75b17aa57f81d61ac9cd54c5c1b86710f53ce2c0d945f7f2f3d737bc14d","bytes":102968},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"192315ad89a95c24be97d4a8618535500a63a00057adb90c2a0c97de5a508643"}
|
|
28
|
+
{"index":27,"prev":"192315ad89a95c24be97d4a8618535500a63a00057adb90c2a0c97de5a508643","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.544Z","name":"ng2_proud","skin":"night","mood":"proud","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:15:12.600Z","localPath":"assets/image/ng2_proud_20260929191512.png"},"master":{"path":"F:\\孤屿\\assets\\image\\ng2_proud_20260929191512.png","sha256":"cd357b4416515c02fc6356a603c9ad1a86c7d08fd9d88065f83141bce2afcdc6"},"output":{"path":"assets/night/proud.webp","sha256":"28ca2084b5ca77fbc15ae463a75f085e1d88e054bf1c11e0d20934fa22065107","bytes":106622},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"645c768ecf6d4702053abfcc869b51951272dba73d309d0200870268014b14ad"}
|
|
29
|
+
{"index":28,"prev":"645c768ecf6d4702053abfcc869b51951272dba73d309d0200870268014b14ad","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.551Z","name":"pj2_idle","skin":"pajama","mood":"idle","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:16:09.300Z","localPath":"assets/image/pj2_idle_20260929191609.png"},"master":{"path":"F:\\孤屿\\assets\\image\\pj2_idle_20260929191609.png","sha256":"c30757d40d1a2c7bc1ccedced44250249c96dd31714a9a9140bb57e2c663ee88"},"output":{"path":"assets/pajama/idle.webp","sha256":"959ac8345222a3e9b30afad6d971cf2217038b1f10d44fd177cf0d9146c87692","bytes":115700},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"45e3a2cf17b4a02bdca56af234eb219d270ded7666401046ec6c6bc6e9baa389"}
|
|
30
|
+
{"index":29,"prev":"45e3a2cf17b4a02bdca56af234eb219d270ded7666401046ec6c6bc6e9baa389","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.558Z","name":"pj2_happy","skin":"pajama","mood":"happy","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:16:09.300Z","localPath":"assets/image/pj2_happy_20260929191609.png"},"master":{"path":"F:\\孤屿\\assets\\image\\pj2_happy_20260929191609.png","sha256":"5f0bf3604e2b5f873927fea497b9a9f7892c4ef61cdce497573d65a205042501"},"output":{"path":"assets/pajama/happy.webp","sha256":"59611660dd486e4d8965c1f43f0d3b03b843f25d51c8dacdc6ecaafad1a9f608","bytes":124802},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"432106ebdec273ead79d5cb4bd12af50f96da5a169cb7b804838549483bde2e9"}
|
|
31
|
+
{"index":30,"prev":"432106ebdec273ead79d5cb4bd12af50f96da5a169cb7b804838549483bde2e9","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.567Z","name":"pj2_sleepy","skin":"pajama","mood":"sleepy","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:16:09.300Z","localPath":"assets/image/pj2_sleepy_20260929191609.png"},"master":{"path":"F:\\孤屿\\assets\\image\\pj2_sleepy_20260929191609.png","sha256":"381cfe7555f75238d0927a42df998cb7f44c64c2e4439f12767c491905ee83d3"},"output":{"path":"assets/pajama/sleepy.webp","sha256":"d45fdd86f4dd5a585245ae18af051b285853da657746eb41a2e6ad24d28c0fe1","bytes":113010},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"1d445b3691f0fe443fd20fecdc7da78021493e0f31e5a5d9c34013a3d3ee19e7"}
|
|
32
|
+
{"index":31,"prev":"1d445b3691f0fe443fd20fecdc7da78021493e0f31e5a5d9c34013a3d3ee19e7","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.577Z","name":"pj2_work","skin":"pajama","mood":"work","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:16:09.300Z","localPath":"assets/image/pj2_work_20260929191609.png"},"master":{"path":"F:\\孤屿\\assets\\image\\pj2_work_20260929191609.png","sha256":"4aabcd79db49036dd9c2514456a8adf136de3b20ae9488a4ea3dccd0f46acaf5"},"output":{"path":"assets/pajama/work.webp","sha256":"e68c2d74f11866d4c2222329690d5fcfeb3108e50af89adcc8537103f83f8f2d","bytes":110346},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"0cf1a63cf80010ebbd60732da414c498e737982541bd99cd6ff17630dc400be8"}
|
|
33
|
+
{"index":32,"prev":"0cf1a63cf80010ebbd60732da414c498e737982541bd99cd6ff17630dc400be8","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.585Z","name":"pj2_attn","skin":"pajama","mood":"attn","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:16:09.300Z","localPath":"assets/image/pj2_attn_20260929191609.png"},"master":{"path":"F:\\孤屿\\assets\\image\\pj2_attn_20260929191609.png","sha256":"88c210219d8ec51d06a0cbf0688501b63edfbfe4e8483560cb27cf26770b1ed5"},"output":{"path":"assets/pajama/attn.webp","sha256":"4b83d0824414b2010512bf69adca90a67a52c2a900dee768480c892d08f18b7d","bytes":120264},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"87af13c5d179617c97ee9c0af6d4bc25a7f90d0ce670bb033fe2accfa977e01e"}
|
|
34
|
+
{"index":33,"prev":"87af13c5d179617c97ee9c0af6d4bc25a7f90d0ce670bb033fe2accfa977e01e","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.593Z","name":"pj2_poked","skin":"pajama","mood":"poked","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:16:09.300Z","localPath":"assets/image/pj2_poked_20260929191609.png"},"master":{"path":"F:\\孤屿\\assets\\image\\pj2_poked_20260929191609.png","sha256":"ddc769a7d748a076dd555af189410851ef73af2cb141f75a876de602b296ecda"},"output":{"path":"assets/pajama/poked.webp","sha256":"f61e303037c9a67bc2ec769ae240f88a4ba8722311e8975258ea8a0a2350ef03","bytes":110922},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"15e5ec5b886db9837bb139d644c7999e3afa1dec60355a8314585ea4c042feeb"}
|
|
35
|
+
{"index":34,"prev":"15e5ec5b886db9837bb139d644c7999e3afa1dec60355a8314585ea4c042feeb","kind":"confirm","source":"registry-backfill","at":"2026-09-29T19:38:40.602Z","name":"pj2_proud","skin":"pajama","mood":"proud","registry":{"tool":"batch_generate_images","createdAt":"2026-09-29T19:16:09.300Z","localPath":"assets/image/pj2_proud_20260929191609.png"},"master":{"path":"F:\\孤屿\\assets\\image\\pj2_proud_20260929191609.png","sha256":"565c20a42a41c5ee5e3b25eb460e2baa8e67b1c58cf2ceef3d8b94e1add8ae44"},"output":{"path":"assets/pajama/proud.webp","sha256":"bb70bd99c8cb259edf4291414fca4d93fa7a3245d95433f611b8e4ddcd34d7a9","bytes":102080},"declared":null,"note":"回溯补录:只有代理登记表的事实,没有当次自我声明的参数","hash":"79943856f73dff0063ac4c91efb2e4c447b0b73e3aa95739f002f0cba56b0d3d"}
|
package/build.mjs
CHANGED
|
@@ -11,23 +11,22 @@
|
|
|
11
11
|
extra route, and no missing-asset failure mode.
|
|
12
12
|
|
|
13
13
|
RUN
|
|
14
|
-
node build.mjs # default tier: 1024x1536
|
|
15
|
-
node build.mjs --tier=hi # 2048x3072
|
|
14
|
+
node build.mjs # default tier: 1024x1536 —— 这一档进包,也是唯一被显示的
|
|
15
|
+
node build.mjs --tier=hi # 2048x3072(需先 tools/assets.mjs --all-tiers 生成 _hi)
|
|
16
16
|
node build.mjs --tier=md # 512x768
|
|
17
17
|
node build.mjs --tier=sm # 256x384 (--small is an alias)
|
|
18
18
|
node build.mjs --from assets/ # optional, defaults to ./assets
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
ONLY ONE TIER SHIPS. assets/ now carries just <mood>.webp (1024x1536) per skin.
|
|
21
|
+
The other three tiers are no longer published: runtime never reads them, and
|
|
22
|
+
_hi measured no sharper than the default (DPR 2: 0.3% high-frequency
|
|
23
|
+
difference; DPR 1/3: 1024 was 4~5% BETTER — 2048 gets resampled harder, and
|
|
24
|
+
resampling is itself a low-pass filter). They cost 9.9 MB of the package for
|
|
25
|
+
nothing. Regenerate on demand with `tools/assets.mjs --all-tiers`; the TIERS
|
|
26
|
+
map below falls back down its chain when a preferred file is absent.
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<mood>_md.webp 512x768 the pre-0.4 size
|
|
26
|
-
<mood>_sm.webp 256x384 smallest
|
|
27
|
-
<mood>_hi.webp 2048x3072 headroom for a much larger wisp
|
|
28
|
-
|
|
29
|
-
The default is the smallest tier that is sharp on every realistic display; the
|
|
30
|
-
tiers above it add bytes, not visible pixels, until she is drawn much bigger.
|
|
28
|
+
The default is the smallest tier that is sharp on every realistic display:
|
|
29
|
+
sharp to devicePixelRatio ~4.9 at the shipped render size (210x315 CSS px).
|
|
31
30
|
========================================================================== */
|
|
32
31
|
|
|
33
32
|
import { readFileSync, writeFileSync, existsSync, readdirSync } from 'node:fs'
|
|
@@ -46,7 +45,20 @@ const assetsDir = resolve(here, flagValue('--from', 'assets'))
|
|
|
46
45
|
const templatePath = join(here, 'lib', 'client.template.js')
|
|
47
46
|
const outPath = join(here, 'lib', 'client.js')
|
|
48
47
|
|
|
49
|
-
const MOODS = ['idle', 'happy', 'sleepy', 'work']
|
|
48
|
+
const MOODS = ['idle', 'happy', 'sleepy', 'work', 'attn', 'poked', 'proud']
|
|
49
|
+
|
|
50
|
+
/* 皮肤 = assets/ 下的一个子目录,里面是这套皮肤的 <mood>[_tier].webp。
|
|
51
|
+
如果没有子目录含精灵图,就把 assets/ 本身当作一个名为 default 的皮肤 ——
|
|
52
|
+
这样 --from <任意目录> 的单套素材用法仍然成立。 */
|
|
53
|
+
const SKIN_LABELS = { deepsea: '深海女仆', canon: '原版女仆', classic: '素绘女仆', default: '默认' }
|
|
54
|
+
const skinLabel = (id) => SKIN_LABELS[id] ?? id
|
|
55
|
+
/* 顺序即优先级:列表里第一个就是默认皮肤。不这么写的话默认值会由目录名的字母序
|
|
56
|
+
决定 —— 那是构建实现的偶然,不该变成产品行为。未列出的排在后面。 */
|
|
57
|
+
const SKIN_PRIORITY = ['deepsea', 'canon', 'classic', 'night', 'pajama']
|
|
58
|
+
const skinRank = (id) => {
|
|
59
|
+
const at = SKIN_PRIORITY.indexOf(id)
|
|
60
|
+
return at < 0 ? SKIN_PRIORITY.length : at
|
|
61
|
+
}
|
|
50
62
|
|
|
51
63
|
/** Preference order per tier: the first hit wins, later entries are fallbacks. */
|
|
52
64
|
const TIERS = {
|
|
@@ -67,30 +79,48 @@ if (!existsSync(assetsDir)) {
|
|
|
67
79
|
process.exit(1)
|
|
68
80
|
}
|
|
69
81
|
|
|
70
|
-
const pickFile = (mood) => {
|
|
82
|
+
const pickFile = (dir, mood) => {
|
|
71
83
|
for (const suffix of TIERS[tier]) {
|
|
72
84
|
for (const ext of ['.webp', '.png']) {
|
|
73
|
-
const p = join(
|
|
85
|
+
const p = join(dir, `${mood}${suffix}${ext}`)
|
|
74
86
|
if (existsSync(p)) return p
|
|
75
87
|
}
|
|
76
88
|
}
|
|
77
89
|
return null
|
|
78
90
|
}
|
|
91
|
+
const hasSprite = (dir) => MOODS.some((mood) => pickFile(dir, mood) !== null)
|
|
92
|
+
|
|
93
|
+
const skinIds = readdirSync(assetsDir, { withFileTypes: true })
|
|
94
|
+
.filter((e) => e.isDirectory())
|
|
95
|
+
.map((e) => e.name)
|
|
96
|
+
.filter((name) => hasSprite(join(assetsDir, name)))
|
|
97
|
+
.sort((a, b) => skinRank(a) - skinRank(b) || a.localeCompare(b))
|
|
98
|
+
const legacySingleSkin = skinIds.length === 0 && hasSprite(assetsDir)
|
|
99
|
+
const skins = legacySingleSkin ? ['default'] : skinIds
|
|
100
|
+
if (skins.length === 0) {
|
|
101
|
+
console.error(`build: no sprites anywhere under ${assetsDir}`)
|
|
102
|
+
process.exit(1)
|
|
103
|
+
}
|
|
79
104
|
|
|
80
105
|
const sprites = {}
|
|
81
106
|
let total = 0
|
|
82
|
-
for (const
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
107
|
+
for (const skin of skins) {
|
|
108
|
+
const dir = skin === 'default' ? assetsDir : join(assetsDir, skin)
|
|
109
|
+
sprites[skin] = {}
|
|
110
|
+
console.log(` ${skin}(${skinLabel(skin)})`)
|
|
111
|
+
for (const mood of MOODS) {
|
|
112
|
+
const file = pickFile(dir, mood)
|
|
113
|
+
if (!file) {
|
|
114
|
+
console.error(`build: skin "${skin}" has no sprite for mood "${mood}"`)
|
|
115
|
+
process.exit(1)
|
|
116
|
+
}
|
|
117
|
+
const bytes = readFileSync(file)
|
|
118
|
+
total += bytes.length
|
|
119
|
+
const ext = file.slice(file.lastIndexOf('.') + 1).toLowerCase()
|
|
120
|
+
const mime = ext === 'png' ? 'image/png' : 'image/webp'
|
|
121
|
+
sprites[skin][mood] = `data:${mime};base64,${bytes.toString('base64')}`
|
|
122
|
+
console.log(` ${mood.padEnd(7)} ${String(Math.round(bytes.length / 1024)).padStart(4)} KB <- ${file.slice(here.length + 1)}`)
|
|
87
123
|
}
|
|
88
|
-
const bytes = readFileSync(file)
|
|
89
|
-
total += bytes.length
|
|
90
|
-
const ext = file.slice(file.lastIndexOf('.') + 1).toLowerCase()
|
|
91
|
-
const mime = ext === 'png' ? 'image/png' : 'image/webp'
|
|
92
|
-
sprites[mood] = `data:${mime};base64,${bytes.toString('base64')}`
|
|
93
|
-
console.log(` ${mood.padEnd(7)} ${String(Math.round(bytes.length / 1024)).padStart(4)} KB <- ${file.slice(here.length + 1)}`)
|
|
94
124
|
}
|
|
95
125
|
|
|
96
126
|
const PLACEHOLDER = '__SPRITES_LITERAL__'
|
|
@@ -105,7 +135,11 @@ if (placeholderCount !== 1) {
|
|
|
105
135
|
process.exit(1)
|
|
106
136
|
}
|
|
107
137
|
|
|
108
|
-
const literal = '{\n' +
|
|
138
|
+
const literal = '{\n' + skins.map((skin) => (
|
|
139
|
+
` ${JSON.stringify(skin)}: {\n`
|
|
140
|
+
+ MOODS.map((m) => ` ${m}: '${sprites[skin][m]}',`).join('\n')
|
|
141
|
+
+ '\n },'
|
|
142
|
+
)).join('\n') + '\n }'
|
|
109
143
|
const out = template.replace(PLACEHOLDER, literal)
|
|
110
144
|
|
|
111
145
|
if (out.includes(PLACEHOLDER)) {
|
|
@@ -146,10 +180,23 @@ if (!table || MOODS.some((m) => !new RegExp(`\\b${m}:\\s*'data:image/`).test(tab
|
|
|
146
180
|
process.exit(1)
|
|
147
181
|
}
|
|
148
182
|
try {
|
|
149
|
-
// Evaluate exactly that statement to be certain it is not commented out
|
|
183
|
+
// Evaluate exactly that statement to be certain it is not commented out, and
|
|
184
|
+
// walk every skin/mood pair — a missing pair is a blank companion, not an error
|
|
185
|
+
// anyone would see at build time.
|
|
150
186
|
const value = new Function(`${table[0]}\nreturn SPRITES`)()
|
|
151
|
-
|
|
152
|
-
|
|
187
|
+
const broken = []
|
|
188
|
+
for (const skin of skins) {
|
|
189
|
+
for (const mood of MOODS) {
|
|
190
|
+
const uri = value?.[skin]?.[mood]
|
|
191
|
+
if (typeof uri !== 'string' || uri.indexOf('data:image/') !== 0) broken.push(`${skin}/${mood}`)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (broken.length > 0) {
|
|
195
|
+
console.error(`build: SPRITES is missing ${broken.join(', ')}; aborting`)
|
|
196
|
+
process.exit(1)
|
|
197
|
+
}
|
|
198
|
+
if (Object.keys(value).length !== skins.length) {
|
|
199
|
+
console.error(`build: SPRITES holds ${Object.keys(value).length} skins, expected ${skins.length}; aborting`)
|
|
153
200
|
process.exit(1)
|
|
154
201
|
}
|
|
155
202
|
} catch (error) {
|
|
@@ -164,6 +211,22 @@ console.log(`\n sprites total ${kb(total)} KB`)
|
|
|
164
211
|
console.log(` base64 inlined ${kb(out.length)} KB`)
|
|
165
212
|
console.log(` wrote lib/client.js`)
|
|
166
213
|
|
|
214
|
+
/* 体积与锐度是同一个决定的两面,所以把账算在构建输出里,而不是只写在文档里:
|
|
215
|
+
她在屏上是 140*size x 210*size CSS px,需要多少设备像素只取决于当前屏幕的 DPR。 */
|
|
216
|
+
const SOURCE_WIDTH = { hi: 2048, full: 1024, md: 512, sm: 256 }[tier]
|
|
217
|
+
const drawnW = 140 * 4
|
|
218
|
+
const drawnH = 210 * 4
|
|
219
|
+
console.log(`\n tier ${tier} (${SOURCE_WIDTH}px wide per sprite)`)
|
|
220
|
+
console.log(` she is drawn ${drawnW}x${drawnH} CSS px (size 4)`)
|
|
221
|
+
for (const dpr of [1, 1.5, 2, 3]) {
|
|
222
|
+
const need = drawnW * dpr
|
|
223
|
+
const ratio = SOURCE_WIDTH / need
|
|
224
|
+
const verdict = ratio >= 1
|
|
225
|
+
? `downscale ${ratio.toFixed(2)}x — crisp`
|
|
226
|
+
: `UPSCALE ${(1 / ratio).toFixed(2)}x — slightly soft`
|
|
227
|
+
console.log(` DPR ${String(dpr).padEnd(3)} needs ${String(Math.round(need)).padStart(4)}px → ${verdict}`)
|
|
228
|
+
}
|
|
229
|
+
|
|
167
230
|
if (assetsDir !== join(here, 'assets') && readdirSync(assetsDir).length === 0) {
|
|
168
231
|
console.warn('\n warning: assets directory is empty')
|
|
169
232
|
}
|
package/cordis.patch.yml
CHANGED
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
# wander stroll around on her own while idle (default true)
|
|
36
36
|
# wanderMs how often she considers a stroll (default 45000)
|
|
37
37
|
# wanderRange how far one stroll may travel, in px (default 260)
|
|
38
|
+
# skin name a skin from assets/<skin>/ (default '' = last used)
|
|
39
|
+
# hidden start hidden behind a mini tab (default false)
|
|
38
40
|
#
|
|
39
41
|
# Example — add a `config:` block to the row below:
|
|
40
42
|
#
|