dsh-muv-table 0.2.1 → 0.2.2
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/CHANGELOG.md +51 -20
- package/LICENSE +85 -85
- package/LICENSE.md +9 -0
- package/README.md +59 -59
- package/cordis.patch.yml +5 -5
- package/lib/block-generator.js +56 -56
- package/lib/client.js +419 -419
- package/lib/initvar-parser.js +100 -100
- package/lib/muv-parser.js +121 -121
- package/package.json +21 -20
package/CHANGELOG.md
CHANGED
|
@@ -1,21 +1,52 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## v0.2.
|
|
4
|
-
|
|
5
|
-
###
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## v0.2.2 (2026-09-13)
|
|
4
|
+
|
|
5
|
+
### 🐛 修复
|
|
6
|
+
|
|
7
|
+
- **exports 放开 `./lib/*` 子路径**:`dsh-muv-engine` 需要导入本包的
|
|
8
|
+
`lib/muv-parser.js`、`lib/block-generator.js`、`lib/initvar-parser.js`,
|
|
9
|
+
但 `exports` 只映射了 `.` 与 `./client`,子路径导入会被 Node 的 exports 门禁拦住:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
import('dsh-muv-table/lib/muv-parser.js')
|
|
13
|
+
-> ERR_PACKAGE_PATH_NOT_EXPORTED
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
新增 `"./lib/*": "./lib/*"` 后即可正常解析。
|
|
17
|
+
|
|
18
|
+
### 🔧 改进
|
|
19
|
+
|
|
20
|
+
- **`panel.html` 读取改为容错**:原先在模块加载时直接
|
|
21
|
+
`const PANEL_HTML = fs.readFileSync(...)`,一旦文件缺失就抛 `ENOENT`。
|
|
22
|
+
由于模块加载失败会让所在 loader 行激活失败,而 DSH 启动时会校验每一行,
|
|
23
|
+
这会让**整个 DSH 起不来**。改为 `let PANEL_HTML = ''` + `try/catch` 兜底。
|
|
24
|
+
此改动与已发布的 0.2.1 npm 包保持一致(git 仓库此前落后于发布版)。
|
|
25
|
+
|
|
26
|
+
### 📝 注意
|
|
27
|
+
|
|
28
|
+
- `lib/panel.html` 被 `.gitignore` 排除,因此**从 `git clone` 的目录直接
|
|
29
|
+
`dsh plugin add <路径>` 安装时该文件不存在**。容错改动后不会再导致启动失败,
|
|
30
|
+
但面板内容会为空 —— 请走 npm registry 安装。
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## v0.2.0 (2026-08-27)
|
|
35
|
+
|
|
36
|
+
### ✨ 新功能
|
|
37
|
+
- **宏测试浮窗**:点击面板 header 的「📐 宏」按钮弹出
|
|
38
|
+
- 输入宏语法 → 展开测试 → 实时看结果
|
|
39
|
+
- 展开结果支持「📋 复制」和「⬆ 填入」(回填到输入框继续编辑)
|
|
40
|
+
- 🎲 快捷骰子栏:d4/d6/d8/d10/d12/d20/2d6/3d6/1d100 一键掷骰
|
|
41
|
+
- 📌 Pick 缓存列表:展示所有缓存 key→值,单个重抽或全部清除
|
|
42
|
+
- 📖 语法帮助折叠区
|
|
43
|
+
|
|
44
|
+
### 🔧 改进
|
|
45
|
+
- Header 按钮精简:去掉重复的「🍺 酒馆」按钮(与 🔄 刷新功能重复),替换为「📐 宏」
|
|
46
|
+
- 依赖 muv-engine 升级到 `^0.2.0`
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## v0.1.0 (2026-08-26)
|
|
51
|
+
|
|
21
52
|
- 初始版本:树形变量表格编辑器、酒馆侧边栏入口、从酒馆加载角色卡、MUV 块生成
|
package/LICENSE
CHANGED
|
@@ -1,86 +1,86 @@
|
|
|
1
|
-
# PolyForm Noncommercial Copyleft License 1.0.0
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 chen731215-dev
|
|
4
|
-
|
|
5
|
-
## Acceptance
|
|
6
|
-
|
|
7
|
-
In order to get any license under these terms, you must agree to them as both
|
|
8
|
-
strict obligations and conditions to all your licenses.
|
|
9
|
-
|
|
10
|
-
## Copyright License
|
|
11
|
-
|
|
12
|
-
The licensor grants you a copyright license for the software to do everything
|
|
13
|
-
you might do with the software that would otherwise infringe the licensor's
|
|
14
|
-
copyright for any purpose except for a commercial purpose.
|
|
15
|
-
|
|
16
|
-
## Noncommercial Purposes
|
|
17
|
-
|
|
18
|
-
A noncommercial purpose is any purpose that is not a commercial purpose.
|
|
19
|
-
|
|
20
|
-
A commercial purpose is one intended for commercial advantage or monetary
|
|
21
|
-
compensation. For purposes of this license, commercial advantage or monetary
|
|
22
|
-
compensation includes but is not limited to:
|
|
23
|
-
|
|
24
|
-
1. selling, licensing, or distributing the software as part of a commercial
|
|
25
|
-
product or service
|
|
26
|
-
|
|
27
|
-
2. using the software to provide a commercial service, including but not
|
|
28
|
-
limited to software-as-a-service, platform-as-a-service, or
|
|
29
|
-
infrastructure-as-a-service offerings
|
|
30
|
-
|
|
31
|
-
3. using the software in any manner that directly or indirectly generates
|
|
32
|
-
revenue
|
|
33
|
-
|
|
34
|
-
## Copyleft
|
|
35
|
-
|
|
36
|
-
With respect to any copies or modifications of the software that you make or
|
|
37
|
-
distribute, you must license them to recipients under the same terms as this
|
|
38
|
-
license. You must make available the source code of any modifications you make.
|
|
39
|
-
|
|
40
|
-
## Notices
|
|
41
|
-
|
|
42
|
-
You must ensure that everyone who gets a copy of any part of the software
|
|
43
|
-
from you also gets a copy of these terms or a link to
|
|
44
|
-
https://polyformproject.org/licenses/noncommercial-copyleft/1.0.0/.
|
|
45
|
-
|
|
46
|
-
## Patent License
|
|
47
|
-
|
|
48
|
-
The licensor grants you a patent license for the software that covers patent
|
|
49
|
-
claims the licensor can license, or becomes able to license, that you would
|
|
50
|
-
infringe by using the software.
|
|
51
|
-
|
|
52
|
-
## No Other Rights
|
|
53
|
-
|
|
54
|
-
These terms do not allow you to sublicense or transfer any of your licenses
|
|
55
|
-
to anyone else, or prevent the licensor from granting licenses to anyone else.
|
|
56
|
-
These terms do not imply any other licenses.
|
|
57
|
-
|
|
58
|
-
## No Liability
|
|
59
|
-
|
|
60
|
-
***As far as the law allows, the software comes as is, without any warranty
|
|
61
|
-
or condition, and the licensor will not be liable to you for any damages
|
|
62
|
-
arising out of these terms or the use or nature of the software, under any
|
|
63
|
-
kind of legal claim.***
|
|
64
|
-
|
|
65
|
-
## Definitions
|
|
66
|
-
|
|
67
|
-
The **licensor** is the individual or entity offering these terms, and the
|
|
68
|
-
**software** is the software the licensor makes available under these terms.
|
|
69
|
-
|
|
70
|
-
**You** refers to the individual or entity agreeing to these terms.
|
|
71
|
-
|
|
72
|
-
**Your company** is any legal entity, sole proprietorship, or other kind of
|
|
73
|
-
organization that you work for, plus all organizations that have control over,
|
|
74
|
-
are under the control of, or are under common control with that organization.
|
|
75
|
-
Control means ownership of substantially all the assets of an entity, or the
|
|
76
|
-
power to direct its management and policies by vote, contract, or otherwise.
|
|
77
|
-
Control can be direct or indirect.
|
|
78
|
-
|
|
79
|
-
**Your licenses** are all the licenses granted to you for the software under
|
|
80
|
-
these terms.
|
|
81
|
-
|
|
82
|
-
**Use** means anything you do with the software requiring one of your licenses.
|
|
83
|
-
|
|
84
|
-
**Modify** means to copy from or adapt all or part of the work in a fashion
|
|
85
|
-
requiring copyright permission, other than the making of an exact copy. The
|
|
1
|
+
# PolyForm Noncommercial Copyleft License 1.0.0
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 chen731215-dev
|
|
4
|
+
|
|
5
|
+
## Acceptance
|
|
6
|
+
|
|
7
|
+
In order to get any license under these terms, you must agree to them as both
|
|
8
|
+
strict obligations and conditions to all your licenses.
|
|
9
|
+
|
|
10
|
+
## Copyright License
|
|
11
|
+
|
|
12
|
+
The licensor grants you a copyright license for the software to do everything
|
|
13
|
+
you might do with the software that would otherwise infringe the licensor's
|
|
14
|
+
copyright for any purpose except for a commercial purpose.
|
|
15
|
+
|
|
16
|
+
## Noncommercial Purposes
|
|
17
|
+
|
|
18
|
+
A noncommercial purpose is any purpose that is not a commercial purpose.
|
|
19
|
+
|
|
20
|
+
A commercial purpose is one intended for commercial advantage or monetary
|
|
21
|
+
compensation. For purposes of this license, commercial advantage or monetary
|
|
22
|
+
compensation includes but is not limited to:
|
|
23
|
+
|
|
24
|
+
1. selling, licensing, or distributing the software as part of a commercial
|
|
25
|
+
product or service
|
|
26
|
+
|
|
27
|
+
2. using the software to provide a commercial service, including but not
|
|
28
|
+
limited to software-as-a-service, platform-as-a-service, or
|
|
29
|
+
infrastructure-as-a-service offerings
|
|
30
|
+
|
|
31
|
+
3. using the software in any manner that directly or indirectly generates
|
|
32
|
+
revenue
|
|
33
|
+
|
|
34
|
+
## Copyleft
|
|
35
|
+
|
|
36
|
+
With respect to any copies or modifications of the software that you make or
|
|
37
|
+
distribute, you must license them to recipients under the same terms as this
|
|
38
|
+
license. You must make available the source code of any modifications you make.
|
|
39
|
+
|
|
40
|
+
## Notices
|
|
41
|
+
|
|
42
|
+
You must ensure that everyone who gets a copy of any part of the software
|
|
43
|
+
from you also gets a copy of these terms or a link to
|
|
44
|
+
https://polyformproject.org/licenses/noncommercial-copyleft/1.0.0/.
|
|
45
|
+
|
|
46
|
+
## Patent License
|
|
47
|
+
|
|
48
|
+
The licensor grants you a patent license for the software that covers patent
|
|
49
|
+
claims the licensor can license, or becomes able to license, that you would
|
|
50
|
+
infringe by using the software.
|
|
51
|
+
|
|
52
|
+
## No Other Rights
|
|
53
|
+
|
|
54
|
+
These terms do not allow you to sublicense or transfer any of your licenses
|
|
55
|
+
to anyone else, or prevent the licensor from granting licenses to anyone else.
|
|
56
|
+
These terms do not imply any other licenses.
|
|
57
|
+
|
|
58
|
+
## No Liability
|
|
59
|
+
|
|
60
|
+
***As far as the law allows, the software comes as is, without any warranty
|
|
61
|
+
or condition, and the licensor will not be liable to you for any damages
|
|
62
|
+
arising out of these terms or the use or nature of the software, under any
|
|
63
|
+
kind of legal claim.***
|
|
64
|
+
|
|
65
|
+
## Definitions
|
|
66
|
+
|
|
67
|
+
The **licensor** is the individual or entity offering these terms, and the
|
|
68
|
+
**software** is the software the licensor makes available under these terms.
|
|
69
|
+
|
|
70
|
+
**You** refers to the individual or entity agreeing to these terms.
|
|
71
|
+
|
|
72
|
+
**Your company** is any legal entity, sole proprietorship, or other kind of
|
|
73
|
+
organization that you work for, plus all organizations that have control over,
|
|
74
|
+
are under the control of, or are under common control with that organization.
|
|
75
|
+
Control means ownership of substantially all the assets of an entity, or the
|
|
76
|
+
power to direct its management and policies by vote, contract, or otherwise.
|
|
77
|
+
Control can be direct or indirect.
|
|
78
|
+
|
|
79
|
+
**Your licenses** are all the licenses granted to you for the software under
|
|
80
|
+
these terms.
|
|
81
|
+
|
|
82
|
+
**Use** means anything you do with the software requiring one of your licenses.
|
|
83
|
+
|
|
84
|
+
**Modify** means to copy from or adapt all or part of the work in a fashion
|
|
85
|
+
requiring copyright permission, other than the making of an exact copy. The
|
|
86
86
|
resulting work is called a modification of the earlier work.
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# PolyForm Noncommercial Copyleft 1.0.0
|
|
2
|
+
|
|
3
|
+
This software is licensed under the PolyForm Noncommercial Copyleft 1.0.0 license.
|
|
4
|
+
|
|
5
|
+
Full license: https://polyformproject.org/licenses/noncommercial-copyleft/1.0.0/
|
|
6
|
+
|
|
7
|
+
- ✅ Free for non-commercial use
|
|
8
|
+
- ✅ Modifications must be shared under the same license
|
|
9
|
+
- ❌ Commercial use requires a separate license
|
package/README.md
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
# 📊 dsh-muv-table
|
|
2
|
-
|
|
3
|
-
MUV 变量表格编辑器 —— 酒馆伴生插件。
|
|
4
|
-
|
|
5
|
-
> 🍺 本插件是 [dsh-tavern-v2](https://github.com/chen731215-dev/dsh-tavern-v2) 的扩展,需配合酒馆使用。
|
|
6
|
-
|
|
7
|
-
## 是什么
|
|
8
|
-
|
|
9
|
-
把酒馆角色卡的 MUV 变量渲染成结构化表格,Agent 直接编辑表格即可生成格式100%正确的 `<UpdateVariable>` 块,彻底避免 DeepSeek 漏变量、缩进错、标签不闭合的问题。
|
|
10
|
-
|
|
11
|
-
## 安装
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
# 前提:已安装 dsh-tavern-v2
|
|
15
|
-
dsh plugin --profile web add dsh-muv-table
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
或手动编辑 `~/.dsh/profiles/web/package.json`:
|
|
19
|
-
|
|
20
|
-
```json
|
|
21
|
-
{
|
|
22
|
-
"dependencies": {
|
|
23
|
-
"dsh-muv-table": "github:chen731215-dev/dsh-muv-table"
|
|
24
|
-
},
|
|
25
|
-
"dsh": {
|
|
26
|
-
"profile": {
|
|
27
|
-
"bundles": ["dsh-muv-table"]
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## 使用
|
|
34
|
-
|
|
35
|
-
### 1. 打开面板
|
|
36
|
-
左侧边栏点击「MUV 表格」,弹出变量编辑窗口。
|
|
37
|
-
|
|
38
|
-
### 2. 加载角色卡
|
|
39
|
-
- **自动同步**:面板打开时自动读取酒馆当前角色卡
|
|
40
|
-
- **手动加载**:点击「🍺 酒馆」按钮
|
|
41
|
-
- **拖放**:将角色卡 JSON 文件拖入面板
|
|
42
|
-
|
|
43
|
-
### 3. 编辑变量
|
|
44
|
-
- 点击容器行展开/折叠子变量
|
|
45
|
-
- 直接修改数值或文本
|
|
46
|
-
- 修改过的字段金色高亮
|
|
47
|
-
|
|
48
|
-
### 4. 生成 MUV 块
|
|
49
|
-
点击「⚡ 生成 MUV 块」→ 复制 → 粘贴到酒馆对话末尾。
|
|
50
|
-
|
|
51
|
-
## 支持的角色卡
|
|
52
|
-
|
|
53
|
-
| 类型 | 说明 |
|
|
54
|
-
|------|------|
|
|
55
|
-
| 有 `<initvar>` 默认数据 | 直接显示完整变量表 |
|
|
56
|
-
| 无 `<initvar>`(如瑟瑟提瓦特) | 显示空表,LLM 输出 UpdateVariable 后自动填充 |
|
|
57
|
-
|
|
58
|
-
## 协议
|
|
59
|
-
|
|
1
|
+
# 📊 dsh-muv-table
|
|
2
|
+
|
|
3
|
+
MUV 变量表格编辑器 —— 酒馆伴生插件。
|
|
4
|
+
|
|
5
|
+
> 🍺 本插件是 [dsh-tavern-v2](https://github.com/chen731215-dev/dsh-tavern-v2) 的扩展,需配合酒馆使用。
|
|
6
|
+
|
|
7
|
+
## 是什么
|
|
8
|
+
|
|
9
|
+
把酒馆角色卡的 MUV 变量渲染成结构化表格,Agent 直接编辑表格即可生成格式100%正确的 `<UpdateVariable>` 块,彻底避免 DeepSeek 漏变量、缩进错、标签不闭合的问题。
|
|
10
|
+
|
|
11
|
+
## 安装
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# 前提:已安装 dsh-tavern-v2
|
|
15
|
+
dsh plugin --profile web add dsh-muv-table
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
或手动编辑 `~/.dsh/profiles/web/package.json`:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"dsh-muv-table": "github:chen731215-dev/dsh-muv-table"
|
|
24
|
+
},
|
|
25
|
+
"dsh": {
|
|
26
|
+
"profile": {
|
|
27
|
+
"bundles": ["dsh-muv-table"]
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 使用
|
|
34
|
+
|
|
35
|
+
### 1. 打开面板
|
|
36
|
+
左侧边栏点击「MUV 表格」,弹出变量编辑窗口。
|
|
37
|
+
|
|
38
|
+
### 2. 加载角色卡
|
|
39
|
+
- **自动同步**:面板打开时自动读取酒馆当前角色卡
|
|
40
|
+
- **手动加载**:点击「🍺 酒馆」按钮
|
|
41
|
+
- **拖放**:将角色卡 JSON 文件拖入面板
|
|
42
|
+
|
|
43
|
+
### 3. 编辑变量
|
|
44
|
+
- 点击容器行展开/折叠子变量
|
|
45
|
+
- 直接修改数值或文本
|
|
46
|
+
- 修改过的字段金色高亮
|
|
47
|
+
|
|
48
|
+
### 4. 生成 MUV 块
|
|
49
|
+
点击「⚡ 生成 MUV 块」→ 复制 → 粘贴到酒馆对话末尾。
|
|
50
|
+
|
|
51
|
+
## 支持的角色卡
|
|
52
|
+
|
|
53
|
+
| 类型 | 说明 |
|
|
54
|
+
|------|------|
|
|
55
|
+
| 有 `<initvar>` 默认数据 | 直接显示完整变量表 |
|
|
56
|
+
| 无 `<initvar>`(如瑟瑟提瓦特) | 显示空表,LLM 输出 UpdateVariable 后自动填充 |
|
|
57
|
+
|
|
58
|
+
## 协议
|
|
59
|
+
|
|
60
60
|
PolyForm-Noncommercial-Copyleft-1.0.0 — 详见 [LICENSE](./LICENSE)
|
package/cordis.patch.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# dsh-muv-table bundle patch: mounts the MUV table editor plugin.
|
|
2
|
-
# The plugin parses MUV character cards, renders Zod schemas as
|
|
3
|
-
# structured tables, and generates correct <UpdateVariable> blocks.
|
|
4
|
-
- insert:
|
|
5
|
-
- id: muv-table
|
|
1
|
+
# dsh-muv-table bundle patch: mounts the MUV table editor plugin.
|
|
2
|
+
# The plugin parses MUV character cards, renders Zod schemas as
|
|
3
|
+
# structured tables, and generates correct <UpdateVariable> blocks.
|
|
4
|
+
- insert:
|
|
5
|
+
- id: muv-table
|
|
6
6
|
name: 'dsh-muv-table'
|
package/lib/block-generator.js
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
// MUV Block Generator: takes structured table data and generates
|
|
2
|
-
// a correctly formatted <UpdateVariable><initvar> block.
|
|
3
|
-
|
|
4
|
-
import { serializeInitvar } from './initvar-parser.js'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Generate a complete <UpdateVariable> block from a nested data object.
|
|
8
|
-
* @param {object} data - The full variable data (nested object)
|
|
9
|
-
* @returns {string} The formatted <UpdateVariable><initvar>...</initvar></UpdateVariable> block
|
|
10
|
-
*/
|
|
11
|
-
export function generateMuvBlock(data) {
|
|
12
|
-
const inner = serializeInitvar(data)
|
|
13
|
-
return `<UpdateVariable>\n<initvar>\n${inner}</initvar>\n</UpdateVariable>`
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Apply table edits to the data tree and generate the MUV block.
|
|
18
|
-
* @param {object} originalData - The original parsed initvar data
|
|
19
|
-
* @param {Array<{path: string, value: any}>} edits - Array of path-value edits
|
|
20
|
-
* @returns {string} The generated MUV block
|
|
21
|
-
*/
|
|
22
|
-
export function applyEditsAndGenerate(originalData, edits) {
|
|
23
|
-
const data = JSON.parse(JSON.stringify(originalData)) // deep clone
|
|
24
|
-
|
|
25
|
-
for (const edit of edits) {
|
|
26
|
-
setNestedValue(data, edit.path, edit.value)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return generateMuvBlock(data)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Set a deeply nested value by dot-separated path.
|
|
34
|
-
* @param {object} obj
|
|
35
|
-
* @param {string} path - e.g. "Player.资产.黄金"
|
|
36
|
-
* @param {*} value
|
|
37
|
-
*/
|
|
38
|
-
function setNestedValue(obj, path, value) {
|
|
39
|
-
const keys = path.split('.')
|
|
40
|
-
let current = obj
|
|
41
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
42
|
-
const key = keys[i]
|
|
43
|
-
if (!(key in current)) {
|
|
44
|
-
current[key] = {}
|
|
45
|
-
}
|
|
46
|
-
current = current[key]
|
|
47
|
-
}
|
|
48
|
-
const lastKey = keys[keys.length - 1]
|
|
49
|
-
|
|
50
|
-
// Coerce types
|
|
51
|
-
if (typeof current[lastKey] === 'number' || (!isNaN(current[lastKey]) && current[lastKey] !== '' && current[lastKey] !== null && current[lastKey] !== undefined)) {
|
|
52
|
-
const num = Number(value)
|
|
53
|
-
current[lastKey] = isNaN(num) ? value : num
|
|
54
|
-
} else {
|
|
55
|
-
current[lastKey] = value
|
|
56
|
-
}
|
|
1
|
+
// MUV Block Generator: takes structured table data and generates
|
|
2
|
+
// a correctly formatted <UpdateVariable><initvar> block.
|
|
3
|
+
|
|
4
|
+
import { serializeInitvar } from './initvar-parser.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Generate a complete <UpdateVariable> block from a nested data object.
|
|
8
|
+
* @param {object} data - The full variable data (nested object)
|
|
9
|
+
* @returns {string} The formatted <UpdateVariable><initvar>...</initvar></UpdateVariable> block
|
|
10
|
+
*/
|
|
11
|
+
export function generateMuvBlock(data) {
|
|
12
|
+
const inner = serializeInitvar(data)
|
|
13
|
+
return `<UpdateVariable>\n<initvar>\n${inner}</initvar>\n</UpdateVariable>`
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Apply table edits to the data tree and generate the MUV block.
|
|
18
|
+
* @param {object} originalData - The original parsed initvar data
|
|
19
|
+
* @param {Array<{path: string, value: any}>} edits - Array of path-value edits
|
|
20
|
+
* @returns {string} The generated MUV block
|
|
21
|
+
*/
|
|
22
|
+
export function applyEditsAndGenerate(originalData, edits) {
|
|
23
|
+
const data = JSON.parse(JSON.stringify(originalData)) // deep clone
|
|
24
|
+
|
|
25
|
+
for (const edit of edits) {
|
|
26
|
+
setNestedValue(data, edit.path, edit.value)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return generateMuvBlock(data)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Set a deeply nested value by dot-separated path.
|
|
34
|
+
* @param {object} obj
|
|
35
|
+
* @param {string} path - e.g. "Player.资产.黄金"
|
|
36
|
+
* @param {*} value
|
|
37
|
+
*/
|
|
38
|
+
function setNestedValue(obj, path, value) {
|
|
39
|
+
const keys = path.split('.')
|
|
40
|
+
let current = obj
|
|
41
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
42
|
+
const key = keys[i]
|
|
43
|
+
if (!(key in current)) {
|
|
44
|
+
current[key] = {}
|
|
45
|
+
}
|
|
46
|
+
current = current[key]
|
|
47
|
+
}
|
|
48
|
+
const lastKey = keys[keys.length - 1]
|
|
49
|
+
|
|
50
|
+
// Coerce types
|
|
51
|
+
if (typeof current[lastKey] === 'number' || (!isNaN(current[lastKey]) && current[lastKey] !== '' && current[lastKey] !== null && current[lastKey] !== undefined)) {
|
|
52
|
+
const num = Number(value)
|
|
53
|
+
current[lastKey] = isNaN(num) ? value : num
|
|
54
|
+
} else {
|
|
55
|
+
current[lastKey] = value
|
|
56
|
+
}
|
|
57
57
|
}
|