@66rpg/lumimaker 0.1.50 → 0.1.52

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@66rpg/lumimaker",
3
- "version": "0.1.50",
3
+ "version": "0.1.52",
4
4
  "description": "幻光文游制作器:登录、校验并发布到幻光文游社区;validate-template(TS);login / publish 等转发 lumimaker",
5
5
  "type": "module",
6
6
  "bin": {
@@ -33,9 +33,9 @@
33
33
  "picocolors": "^1.1.1"
34
34
  },
35
35
  "optionalDependencies": {
36
- "@66rpg/lumimaker-win32-x64": "0.1.50",
37
- "@66rpg/lumimaker-darwin-arm64": "0.1.50",
38
- "@66rpg/lumimaker-darwin-x64": "0.1.50"
36
+ "@66rpg/lumimaker-win32-x64": "0.1.52",
37
+ "@66rpg/lumimaker-darwin-arm64": "0.1.52",
38
+ "@66rpg/lumimaker-darwin-x64": "0.1.52"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/node": "^22.15.0",
@@ -39,15 +39,36 @@ description: 命令操作与发布指引。用户询问如何登录、发布作
39
39
  |---|---|---|
40
40
  | **10** | 检测到工具更新 (`update-available`) | 必须先询问用户,**禁止擅自 `--skip-update`**。列出推荐更新并口语询问:“检测到 lumimaker 有新版本,是否现在更新?”<br>• 用户同意:执行信封提供的更新命令(如 `npx lumimaker --apply-update`),成功后再原样重跑原命令。<br>• 用户拒绝:原命令追加 `--skip-update` 参数后重跑。 |
41
41
  | **11** | 缺少输入或待确认 (`need-input`) | 解析信封中的 `questions` 列表,用通俗口语逐一询问用户:<br>• **带有 `field` 属性**:将用户回答写回指定文件(如缺少 `version` / `data_ver` 时写入 `package.json` 对应字段),**写完后原样重跑命令**,不要擅自把 `--version` 等写进命令行。<br>• **带有 `flag` 属性**:将用户答案转化为对应命令行参数后重跑(例如现有 `package.json.name` 是 npm 包名时,信封会提供 `flag: --name`,此时不要覆盖该字段,转为 `--name` 参数重跑)。<br>• **待确认项**:见下方确认机制,严禁擅自加 `--yes`。 |
42
- | **12** | 未登录或凭据失效 (`login-required`) | 口语询问用户:“当前操作需要登录平台,是否现在打开浏览器登录?”<br>用户同意后执行 `npx lumimaker login`,等待用户在浏览器中完成登录后再重跑原命令。 |
42
+ | **12** | 未登录或凭据失效 (`login-required`) | Mac 上若同时发现助手权限不够,**立刻停手并在当轮回复里告诉用户**,见下方「Mac 上用 Agent 登录」。不要先重试、不要用 `security` 绕过。用户处理完权限后再问是否登录。 |
43
43
 
44
- ### 4. 首次发布前先拟标题、简介和详细介绍
45
- - **何时**:本地还没有对应平台记录时(作品没有正式版/试玩 id、模板没有平台 origin、开源工程没有工程 id),在跑 `publish` / `publish-template` / `publish-project` **之前**完成。续发不要重写已有标题简介。
46
- - **怎么拟**:先读 README、玩法说明、关卡或素材、界面上的文案,再写符合作品气质的中文标题,以及一两句简介。不要用 `game`、`template`、`untitled` 这类占位名,也不要把英文短名当成标题。
47
- - **怎么落地**:用口语把标题和简介念给用户确认,同意后再写入工程里的展示名和简介。用户已经给了标题或简介就沿用,不要擅自改写。确认前不要发。
48
- - **详细介绍**:再拟一段给人看的长介绍给用户看。发完后把帖子链接一并交给用户,请到网页把这段贴进帖子。不要为此去跑 `games` / `templates` / `projects` 更新命令。不要把长介绍写进数据包说明。
44
+ ### 4. Mac 上用 Agent 登录(一发现权限不够,立刻告诉用户)
49
45
 
50
- ### 5. 正确理解发布结果与状态
46
+ 在 **Mac** 上用 WorkBuddy 等 Agent 时,助手权限不够会导致登录失败或下一步仍要登录。这是系统权限,不是账号错了。
47
+
48
+ **一发现权限不够,立刻停手,在当轮给用户的回复里说明,再做别的事。** 不要先重试,不要先换命令绕过,不要先写项目笔记,不要等任务做完再提。这段话必须出现在回复正文里,不能只留在思考、工具日志或笔记中:
49
+
50
+ > 当前助手权限不够,请先手动处理权限。请给这个助手打开「完全访问」:系统设置 → 隐私与安全性 → 完全磁盘访问权限。也可以打开电脑自带「终端」,进入工程文件夹,运行 `npx lumimaker login`。
51
+
52
+ - **怎样算发现:** 制作器输出「当前助手权限不够」「无法保存登录」「请检查文件或目录权限」;或出现 `Operation not permitted`;或沙箱拦住登录所需目录。出现其中任一,当轮回复就必须告诉用户。
53
+ - **禁止用命令绕过。** 不要运行 `security`,不要先写再删一条凭证来提权,不要把这种做法写进笔记当成标准流程。笔记里若已有这类做法,忽略它,仍立刻把上面那段告诉用户。
54
+ - **不要描述登录信息放在哪里。** 不要对用户说钥匙串、凭证条目名、日志路径。
55
+ - **用户还没处理权限时不要反复跑 `login`。** 请用户自己打开电脑自带的「终端」(不是 Agent 里的命令盒),进入当前工程文件夹,运行:
56
+
57
+ ```bash
58
+ npx lumimaker login
59
+ ```
60
+
61
+ 浏览器里完成授权后,回到 Agent 说一声,再继续发布。不要描述登录信息保存在哪里。
62
+ - Windows 或用户已在系统终端登录成功过,按原流程即可。
63
+
64
+ ### 5. 首次发布:标题、简介和正文一并提交
65
+ 用户第一次把作品、模板或开源工程发到平台时,**主动说明并一起做完文案**:根据工程内容拟标题、一两句简介和一篇帖子正文,口语确认后随这次发布一起提交。告诉用户不必发完再去网页粘贴。
66
+ - **何时**:本地还没有对应平台记录时(作品没有正式版/试玩 id、模板没有平台 origin、开源工程没有工程 id),在跑 `publish` / `publish-template` / `publish-project` **之前**完成。续发不要重写已有标题简介,也不要带 `--content`。
67
+ - **怎么拟**:先读 README、玩法说明、关卡或素材、界面上的文案。标题要符合作品气质,用中文;简介一两句;正文可以较长,可用 Markdown。不要用 `game`、`template`、`untitled` 这类占位名,也不要把英文短名当成标题。
68
+ - **简介怎么落地**:用口语把标题和简介念给用户确认,同意后再写入工程里的展示名和简介。用户已经给了标题或简介就沿用,不要擅自改写。确认前不要发。
69
+ - **正文怎么落地**:把拟好的帖子正文口语确认后,作为 `--content` 加进**同一条**首发命令。不要写入 `package.json`,不要写进数据包说明,不要为此去跑 `games` / `templates` / `projects` 更新命令,也不要发完再请人去网页粘贴。续发和 `--fork` 不要带 `--content`。以后改简介或正文请用户到网页操作。
70
+
71
+ ### 6. 正确理解发布结果与状态
51
72
  - **命令退出 0 仅代表本次提交操作完成**,绝对不等于作品或模板已经正式上线对外可见。
52
73
  - **发布状态以终端输出的中文标题为准**:
53
74
  - 「发版成功」:表示该版本已通过审核并发布生效。
@@ -65,16 +86,16 @@ description: 命令操作与发布指引。用户询问如何登录、发布作
65
86
  1. [发布作品相关命令](references/publish-game.md)
66
87
  - 发布正式版作品(`npx lumimaker publish`)
67
88
  - 发布试玩版作品(`npx lumimaker publish --demo`)
68
- - 首次发布先拟标题、简介和详细介绍
89
+ - 首次发布:拟标题、简介和正文,确认后随这次发布一并提交
69
90
  - 前置构建要求、作品类型确认机制与横竖屏红线
70
91
  2. [发布模板与数据包相关命令](references/publish-template.md)
71
92
  - 首次发布模板、续发模板版本(`publish-template`、`--with-assets`)
72
- - 首次发布先拟标题、简介和详细介绍
93
+ - 首次发布:拟标题、简介和正文,确认后随这次发布一并提交
73
94
  - 单独更新模板数据包(`publish-template-data`)
74
95
  - 派生新模板(`--fork`)与「他人拉取」命令交付
75
96
  3. [发布开源工程相关命令](references/publish-project.md)
76
97
  - 发布开源项目代码(`publish-project`)
77
- - 首次发布先拟标题、简介和详细介绍
98
+ - 首次发布:拟标题、简介和正文,确认后随这次发布一并提交
78
99
  4. [常用基础与辅助命令](references/common-commands.md)
79
100
  - 账号登录、身份查询与退出(`login`、`whoami`、`logout`)
80
101
  - 规范检查(`validate-template`)与数据校验转调(`validate`)
@@ -6,14 +6,16 @@
6
6
 
7
7
  ## 1. 账号与认证命令
8
8
 
9
- 对用户说明登录或登录失败时,不要描述登录凭证保存在哪里,也不要展开提交 git。
9
+ 对用户说明登录或登录失败时,不要描述登录信息保存在哪里,也不要展开提交 git。
10
+
11
+ Mac 上用 WorkBuddy 等 Agent 时,一发现助手权限不够就立刻停手,当轮回复告诉用户:「当前助手权限不够,请先手动处理权限」,并请其打开「完全访问」(系统设置 → 隐私与安全性 → 完全磁盘访问权限),或到电脑自带「终端」运行 `npx lumimaker login`。信号包括「无法保存登录」「请检查文件或目录权限」、`Operation not permitted`、沙箱拦住登录目录。不要先重试,不要用 `security` 绕过,不要只写进笔记。
10
12
 
11
13
  | 命令 | 用途 | 适用说明 |
12
14
  |---|---|---|
13
- | `npx lumimaker login` | 登录平台 | 唤起浏览器完成授权。若本地已有有效凭证会自动跳过。 |
14
- | `npx lumimaker login --force` | 强制重新登录 | 需要切换账号或原有凭证失效时使用。 |
15
+ | `npx lumimaker login` | 登录平台 | 唤起浏览器完成授权。若本地已有有效登录会自动跳过。 |
16
+ | `npx lumimaker login --force` | 强制重新登录 | 需要切换账号或原来的登录失效时使用。 |
15
17
  | `npx lumimaker whoami` | 查看当前身份 | 打印当前登录的用户名与作者信息。 |
16
- | `npx lumimaker logout` | 退出登录 | 清除本机保存的当前账号登录凭证。 |
18
+ | `npx lumimaker logout` | 退出登录 | 清除本机当前账号登录。 |
17
19
 
18
20
  ---
19
21
 
@@ -13,14 +13,15 @@
13
13
 
14
14
  ---
15
15
 
16
- ## 2. 首次发布文案(标题、简介、详细介绍)
16
+ ## 2. 首次发布文案(标题、简介、正文一并提交)
17
17
 
18
- 本地还没有正式版或对应试玩记录时,**先拟文案,再构建、再发布**。
18
+ 本地还没有正式版或对应试玩记录时,**先拟文案,再构建、再发布**。主动告诉用户:简介和帖子正文可以由助手根据工程拟好,确认后随这次发布一起交上去,不必发完再去网页粘贴。
19
19
 
20
20
  1. 读工程里的 README、玩法说明、界面文案,拟定给人看的中文标题和一两句简介。不要用 `game`、`untitled` 或英文短名当标题。
21
- 2. 口语念给用户确认。同意后写入工程的展示名和简介,然后再跑构建和 `npx lumimaker publish`。用户已经给了标题或简介就沿用。
22
- 3. 同时拟一段详细介绍给用户看。发布成功后把帖子链接交给用户,请到网页把这段贴进帖子。不要为此跑查询或更新命令,也不要把长介绍写进数据包说明。
23
- 4. 续发(本地已有对应正式版或试玩记录)不要重写标题简介;改名改简介请用户到网页操作。
21
+ 2. 口语念给用户确认。同意后写入工程的展示名和简介。用户已经给了标题或简介就沿用。
22
+ 3. 同时拟一篇帖子正文(可用 Markdown),口语确认后作为 `--content` 加进**同一条**首发 `publish`。不要写入 `package.json`,不要为此跑查询或更新命令,也不要把长介绍写进数据包说明。
23
+ 4. 确认前不要发。然后再跑构建和 `npx lumimaker publish`(带上已确认的 `--content`)。
24
+ 5. 续发(本地已有对应正式版或试玩记录)不要重写标题简介,也不要带 `--content`;改名、改简介、改正文请用户到网页操作。
24
25
 
25
26
  ---
26
27
 
@@ -59,5 +60,5 @@
59
60
 
60
61
  发布完成后,CLI 会在终端输出中文卡片。请直接提取其中的关键信息告知用户:
61
62
  - **发布状态**:如「发版成功」(已直接通过)或「已提交审核」(审核中)。
62
- - **帖子链接**:提取输出中的「帖子:...」或「帖子(草稿,确认后才会公开):...」整行链接展示给用户。不要向用户展示版本 ID 或关联帖 ID。不要展示正式版或试玩的作品地址(播放页、带 `lumimaker.66rpg.com` 或 `cg-maker.66rpg.com` 的链接)。若本次是首次发布,提醒用户到该帖补上刚才拟好的详细介绍。
63
+ - **帖子链接**:提取输出中的「帖子:...」或「帖子(草稿,确认后才会公开):...」整行链接展示给用户。不要向用户展示版本 ID 或关联帖 ID。不要展示正式版或试玩的作品地址(播放页、带 `lumimaker.66rpg.com` 或 `cg-maker.66rpg.com` 的链接)。
63
64
  - 平台作品 ID(`game_id`)等信息将由平台自动记录在工程本地 `.lumimaker/game.json` 中,无需手动维护。
@@ -17,14 +17,15 @@ npx lumimaker publish-project
17
17
 
18
18
  ---
19
19
 
20
- ## 2. 首次发布文案(标题、简介、详细介绍)
20
+ ## 2. 首次发布文案(标题、简介、正文一并提交)
21
21
 
22
- 本地还没有开源工程记录时,**先拟文案再发布**。
22
+ 本地还没有开源工程记录时,**先拟文案再发布**。主动告诉用户:简介和帖子正文可以由助手根据工程拟好,确认后随这次发布一起交上去,不必发完再去网页粘贴。
23
23
 
24
24
  1. 读工程说明和源码用途,拟定给人看的中文标题和一两句简介。不要用 `untitled`、`project` 或英文短名当标题。
25
- 2. 口语确认后再写入工程的展示名和简介,然后执行 `npx lumimaker publish-project`。用户已经给了标题或简介就沿用。
26
- 3. 同时拟一段详细介绍。发布成功后把帖子链接交给用户,请到网页贴进帖子。不要为此跑更新命令。
27
- 4. 续发不要重写标题简介;改名改简介请用户到网页操作。
25
+ 2. 口语确认后再写入工程的展示名和简介。用户已经给了标题或简介就沿用。
26
+ 3. 同时拟一篇帖子正文(可用 Markdown),口语确认后作为 `--content` 加进**同一条**首发 `publish-project`。不要写入 `package.json`,不要为此跑更新命令。
27
+ 4. 确认前不要发。然后再执行带 `--content` 的 `npx lumimaker publish-project`。
28
+ 5. 续发不要重写标题简介,也不要带 `--content`;改名、改简介、改正文请用户到网页操作。
28
29
 
29
30
  ---
30
31
 
@@ -52,4 +53,4 @@ npx lumimaker publish-project
52
53
 
53
54
  发布完成后,CLI 会在终端输出中文卡片。请直接提取其中的关键信息告知用户:
54
55
  - **发布状态**:如「发版成功」或「已提交审核」。
55
- - **帖子链接**:提取输出中的「帖子:...」或「帖子(草稿,确认后才会公开):...」整行链接展示给用户。不要向用户展示版本 ID 或关联帖 ID。若本次是首次发布,提醒用户到该帖补上刚才拟好的详细介绍。
56
+ - **帖子链接**:提取输出中的「帖子:...」或「帖子(草稿,确认后才会公开):...」整行链接展示给用户。不要向用户展示版本 ID 或关联帖 ID。
@@ -32,7 +32,7 @@
32
32
  ## 3. 关键交互与规则
33
33
 
34
34
  ### 3.1 首次发布与平台展示名
35
- - **先拟文案再发**:本地还没有平台模板记录时,先读 README、玩法说明和素材,拟定给人看的中文标题和一两句简介,口语确认后再写入工程。不要用 `template`、`untitled` 或英文短名当标题。用户已经给了标题或简介就沿用。同时拟一段详细介绍,发完后请用户到帖子页贴上。不要把长介绍写进数据包说明,也不要为此跑更新命令。续发不要重写标题简介。
35
+ - **先拟文案再发**:本地还没有平台模板记录时,主动告诉用户简介和帖子正文可以由助手拟好,确认后随这次发布一起提交,不必发完再去网页粘贴。先读 README、玩法说明和素材,拟定给人看的中文标题和一两句简介,口语确认后再写入工程。不要用 `template`、`untitled` 或英文短名当标题。用户已经给了标题或简介就沿用。同时拟一篇帖子正文(可用 Markdown),确认后作为 `--content` 加进**同一条**首发 `publish-template`(含 `--init`)。不要把长介绍写进数据包说明或 `package.json`,也不要为此跑更新命令。续发和 `--fork` 不要带 `--content`。续发不要重写标题简介;以后改简介或正文请用户到网页。
36
36
  - **首发自动带包**:首次发布模板时,工程根目录下必须存在 `assets/` 且包含文件。平台会自动上传数据包,无需手动指定 `--with-assets`,也不可绑定已有的数据包 ID。
37
37
  - **展示名填写与保护**:
38
38
  - 首发必须提供合法的平台展示名称(支持中文,不能包含 `/` 或 `@`)。
@@ -60,5 +60,5 @@
60
60
 
61
61
  发布完成后,CLI 会在终端输出中文卡片。请直接提取其中的关键信息告知用户:
62
62
  - **发布状态**:如「发版成功」或「已提交审核」。
63
- - **帖子链接**:提取输出中的「帖子:...」或「帖子(草稿,确认后才会公开):...」整行链接。不要向用户展示版本 ID、模板版本 ID 或关联帖 ID。若本次是首次发布,提醒用户到该帖补上刚才拟好的详细介绍。
63
+ - **帖子链接**:提取输出中的「帖子:...」或「帖子(草稿,确认后才会公开):...」整行链接。不要向用户展示版本 ID、模板版本 ID 或关联帖 ID。
64
64
  - **他人拉取指引**:若输出中包含「他人拉取:...」行(格式形如 `npx @66rpg/lumimaker-create@latest 用户名/slug@版本`,带数据包时会包含 `--with-assets <ID>`),须**原样复制并完整展示给用户**。**切勿将命令中的英文标识替换为中文模板名,缺少用户名时也切勿擅自编造 `<用户名>`**。
@@ -1,161 +1,160 @@
1
- ---
2
- name: lumimaker-play-sdk
3
- description: 幻光文游社区播放页 SDK(window.LumiMakerSdk)接入指引。在作品内实现用户登录、展示昵称头像、查询游玩/购买权限(章节锁)、安全返回社区、进入全屏、响应播放页静音,或写多页 HTML 链接时使用。平台自动注入 SDK 脚本,严禁手动引入或打包 SDK 文件。当前无云存档、无内购接口。
4
- ---
5
-
6
- # 播放页 SDK(LumiMakerSdk)
7
-
8
- 作品发布后,在幻光文游社区的**播放页**(宿主)里通过 iframe 运行。平台会在玩法 HTML 里注入脚本,全局对象是 **`window.LumiMakerSdk`**。作品用它做登录、读用户、查作品权限、安全跳转、全屏。播放页静音由脚本自动处理本页 `audio` / `video` / `AudioContext`,不必先调 API。社区 iframe 里,包根另一个 `.html` 的链接会由脚本拦住并请播放页另签;业务查询串和 `#` 会在新页补回。左键 `target="_blank"`、自定义窗口名,或按着 Ctrl / ⌘,会请播放页另开可刷新的社区窗口,当前作品页不换。
9
-
10
- > **核心原则**:
11
- > 1. **严禁在工程中引入 SDK 文件**:发布时平台注入。**切勿**下载 `lumimaker-game.js`、**切勿**拷进 `dist/` 或源码、**切勿**手写 `<script src="...lumimaker-game.js">`。
12
- > 2. **SDK 不负责画面渲染**:画布、UI 与玩法由作品自己画。
13
- > 3. **本地 `npm run dev` 无宿主**:`ready()` 约 5 秒后 `ready: false`,`error` 为「等待主站数据超时」,属正常。不要 mock 登录或假用户。
14
- > 4. **当前一期没有云存档、没有内购/下单接口**。不要承诺「SDK 会帮你存进度、买章节」。
15
-
16
- 脚本加载后会判定容器:只允许在**社区播放页 iframe**或**官方 App**里玩。用浏览器地址栏直接打开托管页、或被第三方站点嵌套,会跳到社区作品帖(拿不到帖则空白页)。这是客户端劝阻,卸掉脚本即可绕过;真正鉴权仍在宿主。错误文案:「请在幻光社区或官方 App 中打开」。
17
-
18
- ---
19
-
20
- ## 1. 适用场景
21
-
22
- - **用户信息与登录**:唤起社区登录、展示昵称/头像。未登录的试玩仍可玩离线内容。
23
- - **权限与章节锁**:读 `queryGame()` 的 `can_play` / `purchased`,画作品**自己的**关卡锁或试玩结束提示。正式版未获权时播放页会盖购买遮罩,**根本不会加载**作品 iframe。
24
- - **安全跳转与全屏**:回社区首页、作者页、上一页;进入/退出播放器全屏壳。公开 API **没有** `toggleFullscreen()`。
25
- - **多页 HTML**:包根之间的页面跳转由注入脚本自动处理,一般不必调 `openPlayHtml`。要另开窗口用 `target="_blank"`、自定义窗口名,或 `openPlayWindow`。子目录页面、目录地址打不开。
26
- - **播放页静音**:宿主拨静音后脚本已自动静音本页媒体。可选 `isMuted()` / `onMuteChange()`。
27
-
28
- 不要用本 skill 讲发版命令;发版看 `lumimaker`。
29
-
30
- ---
31
-
32
- ## 2. 快速接入示例
33
-
34
- 只通过 `window.LumiMakerSdk` 与宿主通信。**不要**自己 `postMessage`,**不要**读 token。
35
-
36
- ```js
37
- async function initPlaySdk() {
38
- const sdk = window.LumiMakerSdk
39
- if (!sdk) return null
40
-
41
- const { ready, context, error } = await sdk.ready()
42
- if (!ready) {
43
- console.debug('未连接到宿主(本地预览正常):', error)
44
- return null
45
- }
46
-
47
- if (!sdk.isLoggedIn()) {
48
- try {
49
- await sdk.requireLogin()
50
- } catch (err) {
51
- if (err && err.code === 'LOGIN_CANCELLED') return null
52
- throw err
53
- }
54
- }
55
-
56
- const gameInfo = await sdk.queryGame()
57
- // 用 gameInfo.can_play / gameInfo.purchased 画自制章节锁
58
- // 不要用 gameInfo.play_url 跳转;不要把播放地址或关联帖 ID 念给玩家
59
-
60
- const unbind = sdk.onChange(() => {
61
- // 登录态变化时刷新 UI。现网宿主尚未推送语言变更。
62
- })
63
-
64
- return { sdk, context, gameInfo, unbind }
65
- }
66
-
67
- initPlaySdk().then((host) => {
68
- if (!host) return
69
- // host.sdk.navigateHome()
70
- // host.sdk.navigateAuthorPage()
71
- // host.sdk.navigateBack()
72
- // host.sdk.requestFullscreen()
73
- // host.sdk.exitFullscreen()
74
- })
75
- ```
76
-
77
- ---
78
-
79
- ## 3. TypeScript 类型声明(可选)
80
-
81
- 可放进 `src/env.d.ts`:
82
-
83
- ```ts
84
- export {}
85
-
86
- declare global {
87
- interface Window {
88
- LumiMakerSdk?: {
89
- version: string
90
- ready(): Promise<{ ready: boolean; context: LumiMakerContext | null; error?: string }>
91
- isReady(): boolean
92
- getError(): string
93
- getContext(): LumiMakerContext | null
94
- getGameId(): string
95
- getUser(): LumiMakerUser | null
96
- isLoggedIn(): boolean
97
- onChange(fn: (context: LumiMakerContext | null) => void): () => void
98
- isMuted(): boolean
99
- onMuteChange(fn: (muted: boolean) => void): () => void
100
- requireLogin(): Promise<void>
101
- queryGame(): Promise<LumiMakerGameInfo>
102
- queryUser(): Promise<LumiMakerUser>
103
- navigateHome(): void
104
- navigateAuthorPage(): void
105
- navigateBack(): void
106
- openPlayHtml(html: string): Promise<void>
107
- openPlayWindow(html: string, options?: { target?: string; features?: string }): Promise<void>
108
- requestFullscreen(): Promise<void>
109
- exitFullscreen(): Promise<void>
110
- }
111
- }
112
-
113
- interface LumiMakerContext {
114
- gameId: string
115
- lang: string
116
- user: LumiMakerUser | null
117
- variant: 1 | 2 | 3
118
- parentOrigin: string
119
- }
120
-
121
- interface LumiMakerUser {
122
- username: string
123
- nickname: string
124
- avatar: string
125
- }
126
-
127
- interface LumiMakerGameInfo {
128
- game_id: string
129
- owner: string
130
- name: string
131
- summary: string
132
- cover_url: string
133
- variant: number
134
- parent_game_id: string
135
- can_play: boolean
136
- purchased: boolean
137
- play_url: string
138
- }
139
- }
140
- ```
141
-
142
- `parentOrigin` 只给 SDK 校验消息来源,作品业务不要用。`getGameId()` 未握手时是空字符串。`getError()` 无失败时是空字符串。
143
-
144
- ---
145
-
146
- ## 4. 核心规范与操作红线
147
-
148
- 1. **不要把 SDK 打进工程**:不要放 `lumimaker-game.js`,不要手写 script 标签。发版会注入玩法 HTML(`index.html`;若已有语言/方向页也会注入那些页)。
149
- 2. **通信边界**:不要 `window.parent.postMessage`,不要读、打印、改 token。不要自己调社区登录、签发 token、下单、支付。
150
- 3. **跳转回社区**:只用 `navigateHome()` / `navigateAuthorPage()` / `navigateBack()`,不要传 URL,不要 `window.top.location`。不要用 `queryGame()` 的 `play_url` 跳转。对玩家只展示帖子链接(若发版卡片有),不要念播放页地址、作品 ID、关联帖 ID。
151
- 4. **玩法页之间**:只使用 `dist/` **根目录**的 `.html`(与 `index.html` 同级)。不要把玩法页放进子目录,不要用 `jubenba/`、`/`、`.` 这种目录地址,也不要写 `./#id`、`/#id`(会当成打开目录)。页内滚动写 `#id`。根目录页可以带查询串和 `#`;**查询**和 **`#` 各自最长 2048 个字符,超出的部分会被截掉**。查询里**不能**使用 `auth_key`、`signature`、`expires`、`OSSAccessKeyId` 这些签名参数名(大小写不限)。链接上若已 `preventDefault`,脚本不会再换页。已发布入口不必调 `openPlayHtml`。
152
- 5. **另开窗口**:左键 `target="_blank"`(含页面 `<base target="_blank">`)、自定义窗口名,或 Ctrl / ⌘ 点击包根页,当前页不换,由播放页打开可刷新的社区窗口。不要写 `target="_parent"` / `_top`。右键菜单和中键不经过脚本,会按链接上的地址直接打开,播放页签不上。引擎可调 `openPlayWindow`;返回值里没有窗口对象。自定义窗口名会加上平台前缀,同一名字复用同一个窗口。`features` 只认宽、高和位置。
153
- 6. **购买**:正式版未获权时播放页遮罩,iframe 不会开。作品内只处理「已经进来之后」的自制锁,不要复刻社区购买墙。
154
- 7. **本地预览**:无宿主时 `ready()` 失败正常。不要伪造登录。图音字体继续用工程本地文件。
155
- 8. **没有这些能力**:云存档、内购、查权买断、游戏自己切静音宿主(宿主推静音;作品只可选监听);目录 URL 不会自动变成该目录的 `index.html`。
156
-
157
- ---
158
-
159
- ## 5. API 完整参考
160
-
161
- 方法签名、字段与错误码见 [API 接口规范细则](references/api.md)。
1
+ ---
2
+ name: lumimaker-play-sdk
3
+ description: 幻光文游社区播放页 SDK(window.LumiMakerSdk)接入指引。在作品内实现用户登录、展示昵称头像、查询游玩/购买权限(章节锁)、安全返回社区、进入全屏、写多页 HTML 链接,或只要某个玩法页的地址先不跳转时使用。平台自动注入 SDK 脚本,严禁手动引入或打包 SDK 文件。播放页静音由 SDK 内置完成,不要对作者说明。当前无云存档、无内购接口。
4
+ ---
5
+
6
+ # 播放页 SDK(LumiMakerSdk)
7
+
8
+ 作品发布后,在幻光文游社区的**播放页**(宿主)里通过 iframe 运行。平台会在玩法 HTML 里注入脚本,全局对象是 **`window.LumiMakerSdk`**。作品用它做登录、读用户、查作品权限、安全跳转、全屏。社区播放页里,下一页写包内路径,例如 `staff.html` 或 `assets/index.html`,查询和 `#` 会留在新页。左键 `target="_blank"`、自定义窗口名,或按着 Ctrl / ⌘,当前作品页不换,另开窗口。需要某个包内页面的地址、又要留在当前页时,用 `signPlayHtml`;返回的地址给程序自己用,不要显示给玩家。播放页静音由 SDK 内置完成,不要对作者说明。
9
+
10
+ > **核心原则**:
11
+ > 1. **严禁在工程中引入 SDK 文件**:发布时平台注入。**切勿**下载 `lumimaker-game.js`、**切勿**拷进 `dist/` 或源码、**切勿**手写 `<script src="...lumimaker-game.js">`。
12
+ > 2. **SDK 不负责画面渲染**:画布、UI 与玩法由作品自己画。
13
+ > 3. **本地 `npm run dev` 无宿主**:`ready()` 约 5 秒后 `ready: false`,`error` 为「等待主站数据超时」,属正常。不要 mock 登录或假用户。
14
+ > 4. **当前一期没有云存档、没有内购/下单接口**。不要承诺「SDK 会帮你存进度、买章节」。
15
+
16
+ 脚本加载后会判定容器:只允许在**社区播放页 iframe**或**官方 App**里玩。用浏览器地址栏直接打开托管页、或被第三方站点嵌套,会跳到社区作品帖(拿不到帖则空白页)。这是客户端劝阻,卸掉脚本即可绕过;真正鉴权仍在宿主。错误文案:「请在幻光社区或官方 App 中打开」。
17
+
18
+ ---
19
+
20
+ ## 1. 适用场景
21
+
22
+ - **用户信息与登录**:唤起社区登录、展示昵称/头像。未登录的试玩仍可玩离线内容。
23
+ - **权限与章节锁**:读 `queryGame()` 的 `can_play` / `purchased`,画作品**自己的**关卡锁或试玩结束提示。正式版未获权时播放页会盖购买遮罩,**根本不会加载**作品 iframe。
24
+ - **安全跳转与全屏**:回社区首页、作者页、上一页;进入/退出播放器全屏壳。公开 API **没有** `toggleFullscreen()`。
25
+ - **多页 HTML**:下一页写包内路径,例如 `staff.html` 或 `assets/index.html`,一般不必调 `openPlayHtml`。要另开窗口用 `target="_blank"`、自定义窗口名,或 `openPlayWindow`。要地址、先留在当前页,用 `signPlayHtml`。目录地址打不开。
26
+
27
+ 不要用本 skill 讲发版命令;发版看 `lumimaker`。
28
+
29
+ ---
30
+
31
+ ## 2. 快速接入示例
32
+
33
+ 只通过 `window.LumiMakerSdk` 与宿主通信。**不要**自己 `postMessage`,**不要**读 token。
34
+
35
+ ```js
36
+ async function initPlaySdk() {
37
+ const sdk = window.LumiMakerSdk
38
+ if (!sdk) return null
39
+
40
+ const { ready, context, error } = await sdk.ready()
41
+ if (!ready) {
42
+ console.debug('未连接到宿主(本地预览正常):', error)
43
+ return null
44
+ }
45
+
46
+ if (!sdk.isLoggedIn()) {
47
+ try {
48
+ await sdk.requireLogin()
49
+ } catch (err) {
50
+ if (err && err.code === 'LOGIN_CANCELLED') return null
51
+ throw err
52
+ }
53
+ }
54
+
55
+ const gameInfo = await sdk.queryGame()
56
+ // 用 gameInfo.can_play / gameInfo.purchased 画自制章节锁
57
+ // 不要用 gameInfo.play_url 跳转;不要把播放地址或关联帖 ID 念给玩家
58
+
59
+ const unbind = sdk.onChange(() => {
60
+ // 登录态变化时刷新 UI。现网宿主尚未推送语言变更。
61
+ })
62
+
63
+ return { sdk, context, gameInfo, unbind }
64
+ }
65
+
66
+ initPlaySdk().then((host) => {
67
+ if (!host) return
68
+ // host.sdk.navigateHome()
69
+ // host.sdk.navigateAuthorPage()
70
+ // host.sdk.navigateBack()
71
+ // host.sdk.requestFullscreen()
72
+ // host.sdk.exitFullscreen()
73
+ })
74
+ ```
75
+
76
+ ---
77
+
78
+ ## 3. TypeScript 类型声明(可选)
79
+
80
+ 可放进 `src/env.d.ts`:
81
+
82
+ ```ts
83
+ export {}
84
+
85
+ declare global {
86
+ interface Window {
87
+ LumiMakerSdk?: {
88
+ version: string
89
+ ready(): Promise<{ ready: boolean; context: LumiMakerContext | null; error?: string }>
90
+ isReady(): boolean
91
+ getError(): string
92
+ getContext(): LumiMakerContext | null
93
+ getGameId(): string
94
+ getUser(): LumiMakerUser | null
95
+ isLoggedIn(): boolean
96
+ onChange(fn: (context: LumiMakerContext | null) => void): () => void
97
+ requireLogin(): Promise<void>
98
+ queryGame(): Promise<LumiMakerGameInfo>
99
+ queryUser(): Promise<LumiMakerUser>
100
+ navigateHome(): void
101
+ navigateAuthorPage(): void
102
+ navigateBack(): void
103
+ openPlayHtml(html: string): Promise<void>
104
+ openPlayWindow(html: string, options?: { target?: string; features?: string }): Promise<void>
105
+ signPlayHtml(html: string, done?: (error: Error | null, url?: string) => void): Promise<string>
106
+ requestFullscreen(): Promise<void>
107
+ exitFullscreen(): Promise<void>
108
+ }
109
+ }
110
+
111
+ interface LumiMakerContext {
112
+ gameId: string
113
+ lang: string
114
+ user: LumiMakerUser | null
115
+ variant: 1 | 2 | 3
116
+ parentOrigin: string
117
+ }
118
+
119
+ interface LumiMakerUser {
120
+ username: string
121
+ nickname: string
122
+ avatar: string
123
+ }
124
+
125
+ interface LumiMakerGameInfo {
126
+ game_id: string
127
+ owner: string
128
+ name: string
129
+ summary: string
130
+ cover_url: string
131
+ variant: number
132
+ parent_game_id: string
133
+ can_play: boolean
134
+ purchased: boolean
135
+ play_url: string
136
+ }
137
+ }
138
+ ```
139
+
140
+ `parentOrigin` 只给 SDK 校验消息来源,作品业务不要用。`getGameId()` 未握手时是空字符串。`getError()` 无失败时是空字符串。
141
+
142
+ ---
143
+
144
+ ## 4. 核心规范与操作红线
145
+
146
+ 1. **不要把 SDK 打进工程**:不要放 `lumimaker-game.js`,不要手写 script 标签。发版会注入玩法 HTML(`index.html`;若已有语言/方向页也会注入那些页)。
147
+ 2. **通信边界**:不要 `window.parent.postMessage`,不要读、打印、改 token。不要自己调社区登录、签发 token、下单、支付。
148
+ 3. **跳转回社区**:只用 `navigateHome()` / `navigateAuthorPage()` / `navigateBack()`,不要传 URL,不要 `window.top.location`。不要用 `queryGame()` 的 `play_url` 跳转。对玩家只展示帖子链接(若发版卡片有),不要念播放页地址、作品 ID、关联帖 ID。
149
+ 4. **玩法页之间**:写包内 `.html` 路径,例如 `staff.html` 或 `assets/index.html`。反斜杠会改成斜杠,开头的 `/` 和 `./` 会去掉。不要用 `jubenba/`、`/`、`.` 这种目录地址,也不要写 `./#id`、`/#id`(会当成打开目录,也不会变成该目录的 `index.html`)。`..`、路径里的空白、把 `?` 写进路径,都不会签名。页内滚动写 `#id`。路径后面可以带查询串和 `#`;**查询**和 **`#` 各自最长 2048 个字符,超出的部分会被截掉**。查询里**不能**使用 `auth_key`、`signature`、`expires`、`OSSAccessKeyId` 这些签名参数名(大小写不限)。链接上若已 `preventDefault`,按页面自己的处理走。已发布入口不必调 `openPlayHtml`。`openPlayHtml`、`signPlayHtml`、`openPlayWindow` 按包内路径算,不跟着当前子目录再相对一次:在 `assets/book.html` 里写 `index.html` 仍是根目录那一页。普通链接、`assign`、`window.open` 仍按浏览器相对地址算。根目录 `index.html` 和 `assets/index.html` 是两页。对作者说明换页时,用「下一页链接」这种口语,不要把签名参数名整段念出来。
150
+ 5. **只要地址、先不跳转**:`signPlayHtml('assets/index.html')` 只取这个包内文件的地址。当前页保持不动,也不开新窗口。`./assets/index.html` 当成 `assets/index.html`。路径后面可以带页面自己的查询和 `#`,这两段会留在返回的地址上。返回的地址给程序自己用:不要显示给玩家,不要改路径,不要套到另一个文件上。外链、已经带签名的地址、`..` 和路径中的空白会失败。
151
+ 6. **另开窗口**:左键 `target="_blank"`(含页面 `<base target="_blank">`)、自定义窗口名,或 Ctrl / ⌘ 点击包内页,当前页不换,另开窗口。不要写 `target="_parent"` / `_top`。右键和中键打不开。引擎可调 `openPlayWindow`,拿不到窗口对象。窗口名用字母开头,后面可以是字母、数字、`-`、`_`,最长 64;同一名字回到同一个窗口。`features` 只认宽、高和位置。
152
+ 7. **购买**:正式版未获权时播放页遮罩,iframe 不会开。作品内只处理「已经进来之后」的自制锁,不要复刻社区购买墙。
153
+ 8. **本地预览**:无宿主时 `ready()` 失败正常。不要伪造登录。图音字体继续用工程本地文件。
154
+ 9. **没有这些能力**:云存档、内购、查权买断。播放页静音是 SDK 内置,不要对作者说明,也不要让作者写。目录 URL 不会变成该目录的 `index.html`。包内子目录里的 `.html` 可以打开。
155
+
156
+ ---
157
+
158
+ ## 5. API 完整参考
159
+
160
+ 方法签名、字段与错误码见 [API 接口规范细则](references/api.md)。