feat: TS 构建管线、Spine 抓取器与 wallpapers/ 唯一真相来源
把项目从「手写 dist/」改成「wallpapers/ 是唯一真相来源,dist/ 由 pnpm build 生成」,
并补上配套的类型、门禁与抓取器。一次提交落地整条管线,因为拆开会留下不能构建的中间态。
- src/:运行时与模拟器源码(TS,strict),编译到 build/ 再拷进各分发
- tools/:build / dev / check-{syntax,paths,dist},以及抓取器与回归门禁 tools/checks/
(.scratch/ 下那批一次性脚本移入 tools/checks/ 并入库为长期门禁)
- wallpapers/:七档壁纸的源数据 + README.md(id/音频/预设的完整规范)
- docs/adr/0005-0008:构建管线与分发拓扑、模拟器契约、自包含 sim、每骨架资源布局
- .gitignore:排除 .scratch/ 的参考资料副本(上游 spine 整仓克隆 ~1.2 GB、
抓取侦查数据 ~680 MB)与调试转储;这些是本地调查材料,补偿会让仓库无法克隆
- 归一化 .gitignore/CONTEXT.md 行尾(工作区 CRLF、索引 LF 造成的整文件假 diff)
同时修掉三档卡住构建的未完工壁纸:
- kv45 的 meta.json 里 id 还是抓取期场景名 scene_main,经 downloader promote 正名为 kv45
- shajin / zhigengniao_juheye 的 meta.json 误用了骨架描述文件(name/spine/animations/pages)、
且都缺 preset.template.json;现按规范重建:骨架沉到 spines/<名>/(spine-ts 按 atlas 所在
目录解析贴图页)、补上元数据与单骨架预设,并清掉 zhigengniao 骨架里指向作者机的绝对路径
- 顺带 promote 已在 sources.yml 里的 kv46(月升之前,与兽共舞)
pnpm check 五道门全绿:10 个分发 / 7 档壁纸 / 141 处引用自包含。
This commit is contained in:
1 parent
b8eee05d78
commit
3f11426964
297 files changed
+216627
-1926
No files matched your search
@@ -0,0 +1,365 @@
|
||||
# SpineWallpaper
|
||||
|
||||
**把米哈游活动页里的 Spine 立绘与整页场景,做成一份可以直接上传 Wallpaper Engine 的网页壁纸。**
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||

|
||||
|
||||
## 📚 目录
|
||||
|
||||
- [✨ 项目简介](#-项目简介)
|
||||
- [🧩 特性](#-特性)
|
||||
- [🚀 快速开始](#-快速开始)
|
||||
- [📦 三种产物](#-三种产物)
|
||||
- [🧪 本地调试](#-本地调试)
|
||||
- [🛠 命令与配置](#-命令与配置)
|
||||
- [🗂 目录结构](#-目录结构)
|
||||
- [🏗 架构与数据流](#-架构与数据流)
|
||||
- [🔬 取景算法](#-取景算法)
|
||||
- [✅ 质量门禁](#-质量门禁)
|
||||
- [📥 资源抓取](#-资源抓取)
|
||||
- [🚧 已知约束](#-已知约束)
|
||||
- [🧠 决策记录](#-决策记录)
|
||||
- [🤝 参与与反馈](#-参与与反馈)
|
||||
- [📄 许可证](#-许可证)
|
||||
- [🙏 致谢](#-致谢)
|
||||
|
||||
## ✨ 项目简介
|
||||
|
||||
这是一个 **Wallpaper Engine 网页壁纸(Web 类型)作品 + 围绕它的构建与验证管线**。源数据只有一份
|
||||
(`wallpapers/`),其余全部由 `pnpm build` 生成:单档分发、游戏合集、全部合集,各自都能整体拷到别的机器直接上传。
|
||||
|
||||
当前收录 3 档壁纸、2 个游戏,共 6 个分发:
|
||||
|
||||
| 分发目录 | 内容 | 体积 |
|
||||
| -------------------- | --------------------------------------------------------- | -------- |
|
||||
| `single-hsr-xilian` | 昔涟立绘(单骨架) | 86.0 MB |
|
||||
| `single-hsr-kv37` | 「成为昨日的明天」专题页(单骨架 + 显式像素视口) | 11.6 MB |
|
||||
| `single-ys-nico-tea` | 魔女尼可的茶会(多骨架 + 场景合成) | 9.7 MB |
|
||||
| `collection-hsr` | 上面前两档的切换合集 | 97.0 MB |
|
||||
| `collection-ys` | 原神这一档 | 9.7 MB |
|
||||
| `collection-all` | 全部壁纸合集(**已发布**的那一档,创意工坊 `3604974793`) | 106.3 MB |
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> `dist/` 是纯产物目录(全量约 390 MB),已 gitignore;真相永远在 `wallpapers/` 与 `src/`。
|
||||
> 术语(作品 / 分发 / 合集 / 单档 / 预设 / 视口 / 对拍……)见 [CONTEXT.md](CONTEXT.md)。
|
||||
|
||||
## 🧩 特性
|
||||
|
||||
- 🎞 **保留作者原始观感**:Spine 骨架按原始世界单位渲染,不做矩形归一化;16:9 下与作者取景逐像素一致。
|
||||
- 🖼 **跨比例构图同步**:立绘层的缩放跟着背景图的 `cover` 走,竖屏 / 带鱼屏不会出现「特效与插画脱节」。
|
||||
- 🔀 **多预设切换**:合集分发用 WE 的 `preset` 下拉在壁纸之间切换,音源、背景、骨架整套跟随。
|
||||
- 🎵 **音源可切换**:每档壁纸自带音源清单(无损 FLAC 优先),另有「随预设」与自定义 URL 两种模式。
|
||||
- 🔊 **音量 / 作者信息 / 主题配色**:全部走 WE 原生属性表,样式与官方面板对齐。
|
||||
- 🧪 **可在没有 WE 的机器上调试**:内置一层严格还原官方 API 面的 WE 模拟器,另可产出双击即看的自包含包。
|
||||
- 🧱 **自包含产物**:每个分发目录都是完整的字节副本,不出现任何绝对链接与跨目录相对链接。
|
||||
- 📐 **带门禁**:从源数据校验、产物自包含、逐像素对拍到面板还原度,共 24 个验收脚本(见 [质量门禁](#-质量门禁))。
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
环境要求:
|
||||
|
||||
| 依赖 | 版本 | 用途 |
|
||||
| ------- | ------------------------------ | --------------------------------------------------------- |
|
||||
| Node.js | ≥ 24(开发用 26) | 构建、调试服、验收脚本 |
|
||||
| pnpm | 11.x | 包管理与任务入口 |
|
||||
| Python | 3.10+ 与 PyYAML | **只有**资源抓取(`tools/downloader/`)需要,不需要浏览器 |
|
||||
| 浏览器 | Chromium 内核(Edge / Chrome) | 调试服、对拍与面板验收 |
|
||||
|
||||
```shell
|
||||
# 1) 装依赖(只有 typescript 与 @types/node)
|
||||
pnpm install
|
||||
|
||||
# 2) 全量编译六个分发到 dist/releases/
|
||||
pnpm build
|
||||
|
||||
# 3) 起调试服(默认注入 WE 模拟器),浏览器打开 /release/<分发目录>/
|
||||
node tools/dev.ts --port 5173
|
||||
|
||||
# 4) 跑一遍全部质量门禁(类型 + 构建 + 语法 + 路径 + 产物自包含 + 文案归属)
|
||||
pnpm check
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> 只想看某几档、不想等全量拷贝时,用 `pnpm build <壁纸id>` / `pnpm build collect hsr` /
|
||||
> `pnpm build single`;产物目录默认会清掉本次未构建的旧分发,保留用 `--no-clean`。
|
||||
|
||||
## 📦 三种产物
|
||||
|
||||
「产物形态」是这个项目最容易混的地方,`pnpm build` 的三档开关分别对应三种用途:
|
||||
|
||||
| 用途 | 命令 | 产物 | 关键性质 |
|
||||
| ------------------------------ | ----------------------- | ---------------------------------- | -------------------------------------------------- |
|
||||
| 📤 上传创意工坊 | `pnpm build` | `dist/releases/<分发目录>/` | 干净,**没有**任何模拟器痕迹 |
|
||||
| 🌐 静态托管(如 GitHub Pages) | `pnpm build --with-sim` | 同上,`index.html` 里多一段驱动 | 地址必须是**相对**路径(子路径下根绝对路径会 404) |
|
||||
| 🖱 双击即看 / 离线分享 | `pnpm build sim` | 额外产出 `<分发根>/sim/index.html` | 资源全内联(单页 15 MB~129 MB),`file://` 可用 |
|
||||
|
||||
类型只有两种:**单档**与**合集**,区别在收档范围(`scope: "game" | "all"`)——
|
||||
「全部合集」也是合集,不是第三种类型。
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> 自包含包会因为体积被 GitHub 的单文件上限挡住(合集约 128.7 MB > 100 MB),
|
||||
> 所以静态托管走的是「分发目录 + 构建期注入」,而不是直接发布 `sim/index.html`。
|
||||
|
||||
## 🧪 本地调试
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Q{"这次要做什么?"} --> A["改 runtime / 模拟器源码"]
|
||||
Q --> B["验证渲染是否逐像素一致"]
|
||||
Q --> C["发给别人看 / 静态托管"]
|
||||
Q --> D["上传创意工坊"]
|
||||
Q --> E["离线分享,双击即看"]
|
||||
A --> A1["node tools/dev.ts --port 5173<br/>热更新 + WE 模拟面板"]
|
||||
B --> B1["node tools/serve.mjs 8190 --root dist/releases/collection-all<br/>+ tools/capture.mjs + verify-visual-equivalence"]
|
||||
C --> C1["pnpm build --with-sim"]
|
||||
D --> D1["pnpm build(默认产物,无注入痕迹)"]
|
||||
E --> E1["pnpm build sim"]
|
||||
```
|
||||
|
||||
模拟器只在需要时出现,**永不进发布产物**:调试服按路由注入、静态托管构建期注入、上传 WE 用默认产物零注入。
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> 调试服监听 `src/` 与 `wallpapers/`,改 CSS 只换样式表、改 runtime 整页刷新。
|
||||
> **跑 `test-inline-guard` 前必须先停掉调试服**——它会故意改坏 `src/vendor/` 来验证守卫,两者会抢构建。
|
||||
|
||||
## 🛠 命令与配置
|
||||
|
||||
### npm scripts
|
||||
|
||||
| 命令 | 作用 |
|
||||
| ------------------ | --------------------------------------------------------------------- |
|
||||
| `pnpm dev` | 调试服(SSE 热更新 + 按路由注入 WE 模拟器) |
|
||||
| `pnpm build` | 全编:所有单档 + 每个游戏合集 + 全部合集 |
|
||||
| `pnpm build:pages` | 静态托管用产物(`--with-sim`) |
|
||||
| `pnpm typecheck` | `tsc` 全量类型检查(含验收脚本) |
|
||||
| `pnpm check` | 门禁总入口:类型 → 构建 → 语法 → 路径 → 产物自包含 → 合集文案归属 |
|
||||
| `pnpm serve` | 静态服务器(对拍用),`node tools/serve.mjs <端口> --root <分发目录>` |
|
||||
| `pnpm capture` | 按 CDP 真实时间拍摄渲染图 |
|
||||
|
||||
### 构建开关
|
||||
|
||||
| 开关 | 作用 |
|
||||
| ------------------ | ----------------------------------------------------- |
|
||||
| `--with-sim` | 让分发自带模拟器驱动(静态托管预览用) |
|
||||
| `--sim` | 额外产出双击可看的自包含包 |
|
||||
| `--no-embed-audio` | `--sim` 时音频不内联(包更小,但 `file://` 下播不了) |
|
||||
| `--strict` | 把 warning 升级为 failure |
|
||||
| `--no-clean` | 保留本次未构建的旧分发目录 |
|
||||
| `--dry-run` | 只打印计划,不落盘 |
|
||||
|
||||
### 源数据配置
|
||||
|
||||
- `wallpapers/<游戏id>/<壁纸id>/meta.json`:显示名、发布文案(BBCode)、预览图、音源清单。
|
||||
- `wallpapers/<游戏id>/<壁纸id>/preset.template.json`:背景图、骨架 / 场景、动画名、取景。
|
||||
- `wallpapers/<游戏id>/meta.json`:游戏显示名、共享音频、`title`(该游戏合集的标题,**必填**)。
|
||||
- `wallpapers/meta.json`:全局文案与 `defaultPresetId`(决定 `preset` 下拉首项)。
|
||||
- `wallpapers/sources.yml`:抓取目标页清单(**不是构建输入**)。
|
||||
- `VERSION`:写进 `project.json.version`(WE 要求数字)。
|
||||
|
||||
完整字段表与目录规则见 [wallpapers/README.md](wallpapers/README.md) —— **动 `wallpapers/` 之前先读它**。
|
||||
|
||||
## 🗂 目录结构
|
||||
|
||||
```text
|
||||
SpineWallpaper/
|
||||
├── wallpapers/ ← 唯一真相来源(构建的全部输入)
|
||||
│ ├── meta.json ← 全局文案(= collection-all 那一档)
|
||||
│ ├── preview.gif
|
||||
│ └── <游戏id>/
|
||||
│ ├── meta.json ← 游戏显示名 / 共享音频 / 合集标题
|
||||
│ └── <壁纸id>/
|
||||
│ ├── meta.json ← 发布文案 + 音源清单
|
||||
│ ├── preset.template.json ← 运行时配置(背景 / 骨架 / 取景)
|
||||
│ ├── spines/<骨架名>/ ← 一具骨架一组:json + atlas + 贴图页
|
||||
│ ├── scene/ ← 场景图与背景图
|
||||
│ ├── audios/ ← 音源
|
||||
│ └── preview.gif
|
||||
├── src/
|
||||
│ ├── runtime/ ← 运行时(preset / 背景 / 骨架 / 场景 / 音频 / 取景)
|
||||
│ ├── simulator/ ← WE 模拟器(严格还原官方 API 面)
|
||||
│ ├── styles/ templates/ ← 页面骨架与样式
|
||||
│ ├── vendor/spine-player.js ← spine-ts 运行时副本
|
||||
│ └── project.template.json ← project.json 的骨架
|
||||
├── tools/
|
||||
│ ├── build.ts dev.ts serve.mjs capture.mjs
|
||||
│ ├── lib/{vault,generate,bundle,types,fs,drivers}.ts
|
||||
│ ├── checks/ ← 验收套件(24 个脚本)
|
||||
│ └── downloader/ ← 米哈游活动页 Spine 抓取器(Python)
|
||||
├── docs/adr/0001–0008 ← 架构决策记录
|
||||
├── CONTEXT.md ← 领域术语表
|
||||
└── dist/, build/ ← 产物与编译中间物(gitignore)
|
||||
```
|
||||
|
||||
## 🏗 架构与数据流
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph SRC["源数据 · wallpapers/(唯一真相)"]
|
||||
W["壁纸目录<br/>spines/ · scene/ · audios/<br/>meta.json · preset.template.json"]
|
||||
end
|
||||
subgraph FETCH["抓取器(可选)"]
|
||||
DL["tools/downloader<br/>fetch → staging → promote"]
|
||||
end
|
||||
subgraph BUILD["pnpm build"]
|
||||
V["lib/vault.ts<br/>读取 + 校验"]
|
||||
G["lib/generate.ts<br/>合成 preset.js / project.json"]
|
||||
B["lib/bundle.ts<br/>自包含包"]
|
||||
end
|
||||
subgraph OUT["dist/releases/"]
|
||||
S["single-游戏-壁纸"]
|
||||
C["collection-游戏 / collection-all"]
|
||||
SIM["分发根/sim/index.html"]
|
||||
end
|
||||
WE["Wallpaper Engine<br/>浏览器 / 静态托管"]
|
||||
DL -->|promote 后再进源数据| W
|
||||
W --> V --> G
|
||||
G --> S
|
||||
G --> C
|
||||
G --> B --> SIM
|
||||
S --> WE
|
||||
C --> WE
|
||||
SIM -->|file:// 双击| WE
|
||||
```
|
||||
|
||||
构建只做**拷贝**,不做链接:早先考虑过 NTFS 硬链接省磁盘,被否掉了——链接会让「产物自包含」这条
|
||||
基本性质失效,拷到别的机器或只拷一个分发目录时,链接目标不在产物就残了。
|
||||
|
||||
## 🔬 取景算法
|
||||
|
||||
背景图走 CSS `background-size: cover`(铺满、按需裁切),而播放器默认按「含住作者视口」(contain)
|
||||
映射立绘层——两者只在作者调参的那个比例(16:9)下一致。项目让立绘层跟着背景的缩放走:
|
||||
|
||||
$$
|
||||
\operatorname{coverScale}(a,\ a_{\text{img}}) = \max\!\left(\frac{a}{a_{\text{img}}},\ 1\right)
|
||||
$$
|
||||
|
||||
$$
|
||||
V_h = V_0.h \times \frac{\operatorname{coverScale}(16/9,\ a_{\text{img}})}{\operatorname{coverScale}(a,\ a_{\text{img}})},
|
||||
\qquad V_w = V_h \cdot a
|
||||
$$
|
||||
|
||||
其中 $a$ 是当前画布宽高比,$a_{\text{img}}$ 是背景图自身的宽高比(运行时读 `naturalWidth / naturalHeight`,
|
||||
不在预设里重复写容易写错的数字),$V_0$ 是作者视口换算到 16:9 后的可见矩形。中心不变,
|
||||
等价于「立绘层相对背景插画永远 cover」。实现是纯函数,见
|
||||
[viewport-fitter.ts](src/runtime/viewport-fitter.ts),决策见 [ADR 0003](docs/adr/0003-spine-follows-background-cover.md)。
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> 应用方式是**原地改写** `config.viewport` 的字段后调 `player.setViewport(动画名)`,
|
||||
> 绝不整体替换该对象——`setViewport()` 会无条件读 `config.viewport.animations[name]`,
|
||||
> 换掉整个对象会在 `spine-player.js` 第 14973 行崩溃。维护时机挂在 `config.frame` 回调上。
|
||||
|
||||
## ✅ 质量门禁
|
||||
|
||||
`pnpm check` 是最小闭环(类型 + 构建 + 语法 + 路径 + 产物自包含 + 合集文案归属)。其余脚本前置条件不同,
|
||||
**没有一条命令能全跑完**;完整清单与逐条调用方式见 [tools/checks/README.md](tools/checks/README.md)。
|
||||
|
||||
```shell
|
||||
# ① 不需要服务器
|
||||
pnpm check
|
||||
pnpm build sim
|
||||
node tools/checks/diff-project.mts # 产物 project.json vs 已发布基线
|
||||
node tools/checks/check-collection-copy.mts # 游戏合集的文案必须是"它自己那个游戏"的
|
||||
node tools/checks/verify-sim-page.mts <分发名> # 自包含包 file:// 可用(含"零 http 请求")
|
||||
|
||||
# ② 需要 tools/serve.mjs(对拍驱动 window.__test 只有它注入)
|
||||
node tools/serve.mjs 8190 --root dist/releases/collection-all # 另开一个终端
|
||||
node tools/checks/test-props.mjs test-resize.mjs test-acceptance.mjs
|
||||
|
||||
# ③ 需要 pnpm dev(模拟器面板)
|
||||
node tools/dev.ts --port 5173 --no-build
|
||||
node tools/checks/verify-panel.mts http://127.0.0.1:5173 # 面板还原度(12 组)
|
||||
node tools/checks/check-single-bgm.mts http://127.0.0.1:5173 # 单档里切歌真的换音源
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> **一个从不失败的检查等于没有检查。** 门禁类脚本必须先证明它会红(注入一个坏东西、确认报错、再还原)。
|
||||
> 写 `.mjs` 时不要加类型注解——它是纯 JS,`tsc` 不管它,注解会在运行时抛 SyntaxError。
|
||||
> 另外:不要与调试服同时跑会写 `dist/` 的构建,watcher 会和你抢。
|
||||
|
||||
## 📥 资源抓取
|
||||
|
||||
`tools/downloader/`(Python)从 `wallpapers/sources.yml` 列出的活动页抓 Spine 骨架、贴图与场景装配信息到
|
||||
staging(`_out/`)。**每个有内容的场景各产出一个可直接搬走的壁纸目录**——整个目录挪进
|
||||
`wallpapers/<游戏id>/` 就能用,也可以让 `promote` 代劳。它**不是构建输入**:
|
||||
|
||||
```shell
|
||||
python -m tools.downloader fetch --page kv45 # 抓一页的全部场景(结尾自动 verify)
|
||||
python -m tools.downloader fetch # 抓 sources.yml 里的全部页面
|
||||
python -m tools.downloader fetch --interactive # 逐页问:这一页推荐哪个场景(不影响落盘范围)
|
||||
python -m tools.downloader select --page nico-tea # 只做选择,写 selection.yml
|
||||
python -m tools.downloader verify # 只自检产物
|
||||
python -m tools.downloader fetch --offline # 只用缓存 + 已落盘产物重跑,不发任何请求
|
||||
python -m tools.downloader promote --page kv45/scene_ava --game hsr --id scene_ava … # 搬进 wallpapers/
|
||||
node tools/checks/check-downloader.mts # 门:编译 + 夹具绿 + 四处破坏必红
|
||||
```
|
||||
|
||||
场景装配信息写成 `scene.json` 侧车(在每个场景目录内),**构建期烘焙进 `preset.js`**,运行时不再读侧车。
|
||||
详见 [tools/downloader/README.md](tools/downloader/README.md)。
|
||||
|
||||
## 🚧 已知约束
|
||||
|
||||
- **WE 运行时(本机 2.8.0.485 / CEF 146)**:官方只注入 `window.wallpaperPropertyListener`
|
||||
(`applyUserProperties` / `applyGeneralProperties` / `setPaused` / `userDirectoryFiles*`),
|
||||
`window.wallpaperRegisterListener` **不存在**——按它自检会在真实 WE 里误判。属性事件可能在 `window.load`
|
||||
之前到达,注册必须在模块顶层。
|
||||
- **音频编码**:CEF 的 FFmpeg 白名单含 flac / vorbis / opus / mp3 / pcm,**不含 aac**,所以 m4a 大概率不可用;
|
||||
项目按 [ADR 0004](docs/adr/0004-lossless-audio.md) 优先无损 FLAC,不按体积取舍。
|
||||
- **帧率**:WE 不限流 `requestAnimationFrame`,用户的 fps 上限经 `applyGeneralProperties` 下发,由壁纸自己实现。
|
||||
- **源码语法**:Node 的 strip-only TS 模式不支持 `enum`、构造函数参数属性、`namespace`,源码里禁用这三种写法
|
||||
(`pnpm check:syntax` 会拦);类型检查交给 `tsc`。
|
||||
- **第三方体积**:`src/vendor/spine-player.js` 是 spine-ts 运行时的打包副本,修改前请先确认上游授权。
|
||||
- **无托管 CI**:`package.json` 是 `private`,没有 `.github/workflows`;门禁全部在本地跑(见上节)。
|
||||
|
||||
## 🧠 决策记录
|
||||
|
||||
| ADR | 决策 |
|
||||
| --------------------------------------------------------- | --------------------------------------------------------------------------------- |
|
||||
| [0001](docs/adr/0001-resource-layout.md) | 资源按「游戏 / 壁纸」分层,目录用 id、显示名只进元数据 |
|
||||
| [0002](docs/adr/0002-preset-as-es-module.md) | 预设用 ES module(`preset.js`)而不是 JSON,路径相对自身推导 |
|
||||
| [0003](docs/adr/0003-spine-follows-background-cover.md) | 立绘层取景跟随背景图的 cover 缩放(16:9 为参考比例) |
|
||||
| [0004](docs/adr/0004-lossless-audio.md) | 音频用无损,不按体积取舍 |
|
||||
| [0005](docs/adr/0005-build-pipeline-and-dist-topology.md) | 构建管线与分发拓扑:id 化目录、不产生任何链接、合集层级 |
|
||||
| [0006](docs/adr/0006-simulator-contract.md) | 模拟器契约:还原 WE 的 API 面、不自检、替身显式化 |
|
||||
| [0007](docs/adr/0007-self-contained-sim-build.md) | 自包含调试包的产出方式与两个基准 |
|
||||
| [0008](docs/adr/0008-asset-layout-per-skeleton.md) | 资源布局按「一具骨架一组」(`spines/` + `scene/`),取代 0001 / 0005 的按类型分层 |
|
||||
|
||||
## 🤝 参与与反馈
|
||||
|
||||
这是作者个人的壁纸作品仓库,但欢迎反馈问题与建议:
|
||||
|
||||
- 🐛 **问题与规格**按仓库约定写在 `.scratch/<feature>/` 下(见 [docs/agents/issue-tracker.md](docs/agents/issue-tracker.md)),
|
||||
而不是只留在聊天里。
|
||||
- 🧭 **改代码前**:先读 [CONTEXT.md](CONTEXT.md)(术语)与相关 ADR(决策),
|
||||
再读 [AGENTS.md](AGENTS.md)(本仓库给 agent 的约定)。
|
||||
- ✅ **提交前**:`pnpm check` 必须全绿;新增门禁要先证明它会红。
|
||||
- 📦 **改 `wallpapers/` 前**:先读 [wallpapers/README.md](wallpapers/README.md)。
|
||||
- 🎨 **改面板 / 模拟器前**:先看 [ADR 0006](docs/adr/0006-simulator-contract.md) 与 `tools/checks/verify-panel.mts`。
|
||||
|
||||
## 📄 许可证
|
||||
|
||||
仓库当前**没有声明开源许可证**(`package.json` 为 `private`),代码与素材默认保留所有权利;
|
||||
若要复用,请先联系作者。第三方组件遵循其各自授权:
|
||||
|
||||
- Spine 运行时(`src/vendor/spine-player.js`):spine-ts,授权随上游
|
||||
[Spine Runtimes License](https://esotericsoftware.com/spine-runtimes-license)。
|
||||
- 壁纸中的立绘、场景与音频素材版权归米哈游 / 相关权利人所有,本仓库仅作个人壁纸作品使用。
|
||||
|
||||
## 🙏 致谢
|
||||
|
||||
- [Spine](https://esotericsoftware.com/) / spine-ts:骨架动画运行时。
|
||||
- [Wallpaper Engine](https://www.wallpaperengine.io/):宿主与属性面板 API。
|
||||
- 米哈游活动页:立绘与场景的原始来源(各档来源 URL 见 `wallpapers/sources.yml` 与各壁纸的 `preset.template.json`)。
|
||||
Reference in new issue
Block a user