v0.1.33: 闭环·流光——物品生态闭环+引擎止血+UI动效打磨+测试 5230
【版本】0.1.33(build 通过) 【测试】5009→5230(+200 matrix-close-loop 闭环四验宏量) 【文档】AGENTS/README/MOD_GUIDE/MEMORY 四份同步 0.1.33(闭环注/四同步纪律/测试数)
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
# AGENTS.md
|
# AGENTS.md
|
||||||
|
|
||||||
仙途家族志 · Chronicle of the Immortal Clan — Electron + React + TS 家族修仙模拟器。全部 UI 与文案为中文。
|
仙途家族志 · Chronicle of the Immortal Clan — Electron + React + TS 家族修仙模拟器。全部 UI 与文案为中文。
|
||||||
当前版本 **0.1.32**(《万宝琳琅》:物品六类化 + 新材料七种入市 + 符箓武备/灵酿回气 + 生产泛化 + 材料相关漂移 + 测试 5009)。
|
当前版本 **0.1.33**(《闭环·流光》:物品生态闭环(符箓生效/僵尸物品归位/灾年入产)+ 引擎止血 15 项 + UI 动效打磨(Modal 过渡/停帧节能/季节对齐)+ 测试 5230)。
|
||||||
|
|
||||||
## 命令
|
## 命令
|
||||||
|
|
||||||
@@ -105,6 +105,6 @@ src/main/ Electron 主进程(app:// 协议 + IPC 存
|
|||||||
5. **高危文件白名单**(world.ts / events.ts / store.ts / styles.css / cultivation.ts / **WorldSim.ts / worldsim-data.ts**)改动后必须 `git diff --stat` 核对改动面与预期一致。
|
5. **高危文件白名单**(world.ts / events.ts / store.ts / styles.css / cultivation.ts / **WorldSim.ts / worldsim-data.ts**)改动后必须 `git diff --stat` 核对改动面与预期一致。
|
||||||
6. 每次迭代收尾:`git status` 应干净 + `git log --oneline` 确认每步都有提交记录;凡 "git stash/checkout/rm" 类命令,执行前后都 `git status` 留痕。
|
6. 每次迭代收尾:`git status` 应干净 + `git log --oneline` 确认每步都有提交记录;凡 "git stash/checkout/rm" 类命令,执行前后都 `git status` 留痕。
|
||||||
|
|
||||||
- 提交前:`npm test`(当前 86 套件 5009 例全绿)+ `npm run typecheck` 必须绿(改存储/SQL 后再跑一次冒烟)。
|
- 提交前:`npm test`(当前 89 套件 5230 例全绿)+ `npm run typecheck` 必须绿(改存储/SQL 后再跑一次冒烟)。
|
||||||
- 平衡数值集中在 `game/data/` 与 `engine/sim/worldsim-data.ts`(世界循环参数唯一权威),调平衡不改引擎流程。
|
- 平衡数值集中在 `game/data/` 与 `engine/sim/worldsim-data.ts`(世界循环参数唯一权威),调平衡不改引擎流程。
|
||||||
- 发布产物 `release/`、`out/` 均已 gitignore,勿入库。
|
- 发布产物 `release/`、`out/` 均已 gitignore,勿入库。
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
npm install # 依赖(含 git.metona.cn 私有 registry,token 在用户级 ~/.npmrc)
|
npm install # 依赖(含 git.metona.cn 私有 registry,token 在用户级 ~/.npmrc)
|
||||||
npm install-scripts approve electron esbuild # npm12 首装时必须(Electron 二进制)
|
npm install-scripts approve electron esbuild # npm12 首装时必须(Electron 二进制)
|
||||||
npm run dev # 开发模式(热更新)
|
npm run dev # 开发模式(热更新)
|
||||||
npm test # 引擎测试(86 套件 / 5009 用例,纯 Node 无 GUI)
|
npm test # 引擎测试(89 套件 / 5230 用例,纯 Node 无 GUI)
|
||||||
npm run build # 产物到 out/
|
npm run build # 产物到 out/
|
||||||
npm run package # 打包(Windows 需在 Windows 侧执行)
|
npm run package # 打包(Windows 需在 Windows 侧执行)
|
||||||
```
|
```
|
||||||
@@ -47,7 +47,7 @@ src/main/ Electron 主进程(app:// 协议 + IPC 存
|
|||||||
- **插件化**:万物皆是插件(系统/数据包/事件池),三核心插件 protected 常驻;示例见 tests/helpers/examplePlugin.ts。
|
- **插件化**:万物皆是插件(系统/数据包/事件池),三核心插件 protected 常驻;示例见 tests/helpers/examplePlugin.ts。
|
||||||
- **可回放**:种子随机(sfc32,引擎域零 Math.random)+ 快照回放保真(restore 重建内核+回置 rng)。
|
- **可回放**:种子随机(sfc32,引擎域零 Math.random)+ 快照回放保真(restore 重建内核+回置 rng)。
|
||||||
- **审计四轮**:0.1.15(引擎 P0 歼灭)/ 0.1.20(事件闸·市场黑洞·双金钟罩)/ 0.1.28(稳石:词库回滚·新贵落档·校验接生产·bundle 闭环·指纹补盲)/ **0.1.29(续命:续代断链·敌强度相对化·权重防洪)**。
|
- **审计四轮**:0.1.15(引擎 P0 歼灭)/ 0.1.20(事件闸·市场黑洞·双金钟罩)/ 0.1.28(稳石:词库回滚·新贵落档·校验接生产·bundle 闭环·指纹补盲)/ **0.1.29(续命:续代断链·敌强度相对化·权重防洪)**。
|
||||||
- **测试规模**:**86 套件 / 5009 例**(40 个矩阵域:随机序列/世界生成/市场实体化/事件闸/数据表全量/插件 MOD 组合/省级矩阵等——语义真实,无刷水)。
|
- **测试规模**:**89 套件 / 5230 例**(41 个矩阵域:随机序列/世界生成/市场实体化/事件闸/数据表全量/插件 MOD 组合/省级矩阵等——语义真实,无刷水)。
|
||||||
|
|
||||||
## 打包产物
|
## 打包产物
|
||||||
|
|
||||||
@@ -81,5 +81,6 @@ src/main/ Electron 主进程(app:// 协议 + IPC 存
|
|||||||
| 0.1.30 | 兼济(人口-世界成本闭环 + 世界关注度(匹夫无罪)+ 内置 MOD 仓库/冲突矩阵/预览 + 测试 3006) |
|
| 0.1.30 | 兼济(人口-世界成本闭环 + 世界关注度(匹夫无罪)+ 内置 MOD 仓库/冲突矩阵/预览 + 测试 3006) |
|
||||||
| 0.1.31 | 万物皆可 MOD(内容面七口:物品/功法/建筑(表达式 DSL)/职事/志向/阵型/性格 + kind 分类 + ERA_DURA/REGION_TIDE 聚合 + 测试 4006) |
|
| 0.1.31 | 万物皆可 MOD(内容面七口:物品/功法/建筑(表达式 DSL)/职事/志向/阵型/性格 + kind 分类 + ERA_DURA/REGION_TIDE 聚合 + 测试 4006) |
|
||||||
| 0.1.32 | 万宝琳琅(物品六类化 + 新材料七种入市 + 符箓武备/灵酿回气 + 生产泛化 + 测试 5009) |
|
| 0.1.32 | 万宝琳琅(物品六类化 + 新材料七种入市 + 符箓武备/灵酿回气 + 生产泛化 + 测试 5009) |
|
||||||
|
| 0.1.33 | 闭环·流光(物品生态闭环(符箓生效/僵尸物品归位/灾年入产)+ 引擎止血 15 项 + UI 动效打磨 + 测试 5230) |
|
||||||
|
|
||||||
详见:`docs/PROJECT_MEMORY.md`(设计哲学与每个迭代的"为什么")。
|
详见:`docs/PROJECT_MEMORY.md`(设计哲学与每个迭代的"为什么")。
|
||||||
|
|||||||
@@ -546,5 +546,6 @@ mortal(凡人)→ qi(练气)→ foundation(筑基)→ core(金丹
|
|||||||
|
|
||||||
**一句话总结**:MOD = 一个有 `data` 字段的 JSON。事件管"剧情事件"、模板管"新家族"、词库管"名字概率"、灾因管"灾年种类"、配方管"炼丹铸器"、worldNum 管"世界脾性"、物品/功法/建筑/职事/志向/阵型/性格管"新内容门面"。装/卸/导出全在设置页,读档重装全自动。去写吧——这个世界等你的素材。
|
**一句话总结**:MOD = 一个有 `data` 字段的 JSON。事件管"剧情事件"、模板管"新家族"、词库管"名字概率"、灾因管"灾年种类"、配方管"炼丹铸器"、worldNum 管"世界脾性"、物品/功法/建筑/职事/志向/阵型/性格管"新内容门面"。装/卸/导出全在设置页,读档重装全自动。去写吧——这个世界等你的素材。
|
||||||
> 0.1.32 玩注:资源循环已是六类生态(资源/材料/丹药/符箓/灵酿/兵器),新物产入池即参与世界呼吸与 NPC 贸易——写材料口别怕世界吃不进去。
|
> 0.1.32 玩注:资源循环已是六类生态(资源/材料/丹药/符箓/灵酿/兵器),新物产入池即参与世界呼吸与 NPC 贸易——写材料口别怕世界吃不进去。
|
||||||
|
> 0.1.33 闭环注:符箓开战即耗(风符×1.12/山符×1.15+减伤——零 rng 结算),灵酿渡劫伤后自动回气;丹方/铸器产出物 ALL 必须先在物品表立名(**四同步纪律**:ITEMS/POOL/MARKET/worldgen——否则幽灵物品不可见不可卖)。
|
||||||
|
|
||||||
<sub>⚔️ 本文档随游戏版本更新(0.1.30)。字段若有新增,此处先行。</sub>
|
<sub>⚔️ 本文档随游戏版本更新(0.1.30)。字段若有新增,此处先行。</sub>
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
| 0.1.30 | 兼济 | 人口-世界成本(人多粮少)/世界关注度(匹夫无罪);MOD 生态成型(内置仓库/冲突矩阵/预览/API 清单);**测试 2014→3006** |
|
| 0.1.30 | 兼济 | 人口-世界成本(人多粮少)/世界关注度(匹夫无罪);MOD 生态成型(内置仓库/冲突矩阵/预览/API 清单);**测试 2014→3006** |
|
||||||
| 0.1.31 | 万物皆可 MOD | 内容面总攻(物品/功法/建筑表达式 DSL/职事/志向/阵型/性格七口)+ MOD 类型(kind)+ 数值松弛(ERA_DURA/REGION_TIDE 聚合零漂);测试 3006→4006 |
|
| 0.1.31 | 万物皆可 MOD | 内容面总攻(物品/功法/建筑表达式 DSL/职事/志向/阵型/性格七口)+ MOD 类型(kind)+ 数值松弛(ERA_DURA/REGION_TIDE 聚合零漂);测试 3006→4006 |
|
||||||
| 0.1.32 | 万宝琳琅 | 物品六类化(含符箓/灵酿新用途——武备消耗/回气);新材料七种入世界循环(灵玉灵木兽皮灵果入池、新建筑灵果园灵木坊);生产泛化(produceTable 全键);**测试 4006→5009** |
|
| 0.1.32 | 万宝琳琅 | 物品六类化(含符箓/灵酿新用途——武备消耗/回气);新材料七种入世界循环(灵玉灵木兽皮灵果入池、新建筑灵果园灵木坊);生产泛化(produceTable 全键);**测试 4006→5009** |
|
||||||
|
| 0.1.33 | 闭环·流光 | 物品生态闭环(符箓开战生效/僵尸物品归位/灾年入产——A1-A3 高危断链修复);引擎止血 15 项(tribBoost 清零/assistAlly 先校验/回声空池守卫/版本透传/noAutoCreate 等);UI 动效打磨(Modal 淡入/DriftLayer 节点清理/季节色对月/rAF 停帧节能);**测试 5009→5230** |
|
||||||
|
|
||||||
## 三、关键架构决策(及为什么)
|
## 三、关键架构决策(及为什么)
|
||||||
|
|
||||||
@@ -128,7 +129,7 @@
|
|||||||
7. MOD 目录形态仅支持单文件(目录/分包/依赖多个 .cotymod 自动解析留待)。
|
7. MOD 目录形态仅支持单文件(目录/分包/依赖多个 .cotymod 自动解析留待)。
|
||||||
8. CALAMITY 与 WORLDSTIM 数值表的大规模注入(多 MOD 叠加平衡)未做。
|
8. CALAMITY 与 WORLDSTIM 数值表的大规模注入(多 MOD 叠加平衡)未做。
|
||||||
9. NPC"中期势力轮替"曲线(newborn 频度/覆灭线)仍单参数,可寻参数化。
|
9. NPC"中期势力轮替"曲线(newborn 频度/覆灭线)仍单参数,可寻参数化。
|
||||||
10. **测试规模 5009**(86 套件矩阵域),后续新增机制优先在对应矩阵域追加参(seed×组合),避免重开大文件。
|
10. **测试规模 5230**(89 套件矩阵域),后续新增机制优先在对应矩阵域追加参(seed×组合),避免重开大文件。
|
||||||
11. **缓做项(0.1.28 审计定案)**:declineYears 盛世误触/闪烁——重平衡归 0.1.29 独立调参(避免二次基线漂移);CALAMITY_FAMILY 独立口收益低(灾因口已覆盖);ERA_DURA/REGION_TIDE 松弛版数值口 0.1.29+(必须走"默认优先+聚合"模式)。
|
11. **缓做项(0.1.28 审计定案)**:declineYears 盛世误触/闪烁——重平衡归 0.1.29 独立调参(避免二次基线漂移);CALAMITY_FAMILY 独立口收益低(灾因口已覆盖);ERA_DURA/REGION_TIDE 松弛版数值口 0.1.29+(必须走"默认优先+聚合"模式)。
|
||||||
|
|
||||||
## 八、如何开始修改(给下一个智能体的路径)
|
## 八、如何开始修改(给下一个智能体的路径)
|
||||||
@@ -139,7 +140,7 @@
|
|||||||
改结构:注册进 clocks/plugins;世界循环参数唯一权威 = worldsim-data.ts
|
改结构:注册进 clocks/plugins;世界循环参数唯一权威 = worldsim-data.ts
|
||||||
→ 5. 改 UI:先改 store(revision)再改组件;纯逻辑放 game/engine 可测
|
→ 5. 改 UI:先改 store(revision)再改组件;纯逻辑放 game/engine 可测
|
||||||
→ 6. 加测试:双金钟罩不动,新增用例挂 tests/xxx-0.1.x.test.ts(按主题命名)
|
→ 6. 加测试:双金钟罩不动,新增用例挂 tests/xxx-0.1.x.test.ts(按主题命名)
|
||||||
→ 7. 提交前:npm test(86 套件 5009+)+ typecheck + (GUI 冒烟需 WSLg 在线)+ 更新三份文档 + MOD_GUIDE(触 MOD 时)
|
→ 7. 提交前:npm test(89 套件 5230+)+ typecheck + (GUI 冒烟需 WSLg 在线)+ 更新三份文档 + MOD_GUIDE(触 MOD 时)
|
||||||
```
|
```
|
||||||
|
|
||||||
**一句话原则**:先复现、再小改、后金钟罩。改坏确定性比改错玩法更危险;改数值去 worldsim-data,改流程去 clocks,改事件去 fire()。
|
**一句话原则**:先复现、再小改、后金钟罩。改坏确定性比改错玩法更危险;改数值去 worldsim-data,改流程去 clocks,改事件去 fire()。
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "chronicle-of-the-immortal-clan",
|
"name": "chronicle-of-the-immortal-clan",
|
||||||
"productName": "仙途家族志",
|
"productName": "仙途家族志",
|
||||||
"version": "0.1.32",
|
"version": "0.1.33",
|
||||||
"description": "修仙 · 家族 · 经营 · 战斗 模拟器",
|
"description": "修仙 · 家族 · 经营 · 战斗 模拟器",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "MetonaTeam",
|
"author": "MetonaTeam",
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ export class GameFacade {
|
|||||||
about(): { title: string; version: string; modules: number; systems: number; plugins: number; packFingerprint: string } {
|
about(): { title: string; version: string; modules: number; systems: number; plugins: number; packFingerprint: string } {
|
||||||
return {
|
return {
|
||||||
title: '仙途家族志',
|
title: '仙途家族志',
|
||||||
version: '0.1.32',
|
version: '0.1.33',
|
||||||
modules: this.world.systemList().length,
|
modules: this.world.systemList().length,
|
||||||
systems: this.world.systemList().filter((s) => s.enabled).length,
|
systems: this.world.systemList().filter((s) => s.enabled).length,
|
||||||
plugins: this.world.pluginList().length,
|
plugins: this.world.pluginList().length,
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ export default function SettingsPanel() {
|
|||||||
· 「外交」与四邻结好联姻;仇雠之族隔岁来犯,打得赢名望大涨,打不赢蚀钱伤丁。<br />
|
· 「外交」与四邻结好联姻;仇雠之族隔岁来犯,打得赢名望大涨,打不赢蚀钱伤丁。<br />
|
||||||
· 「史书」自动记述繁华与凋零——百年之后,后人翻开这一卷家族志,见代代薪火、历历雪泥。
|
· 「史书」自动记述繁华与凋零——百年之后,后人翻开这一卷家族志,见代代薪火、历历雪泥。
|
||||||
</div>
|
</div>
|
||||||
<div className="dim2" style={{ marginTop: 8 }}>版本 0.1.32 · Chronicle of the Immortal Clan</div>
|
<div className="dim2" style={{ marginTop: 8 }}>版本 0.1.33 · Chronicle of the Immortal Clan</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ describe('GameFacade 门面', () => {
|
|||||||
const f = new GameFacade(w, 1)
|
const f = new GameFacade(w, 1)
|
||||||
const info = f.about()
|
const info = f.about()
|
||||||
expect(info.title).toBe('仙途家族志')
|
expect(info.title).toBe('仙途家族志')
|
||||||
expect(info.version).toContain('0.1.32')
|
expect(info.version).toContain('0.1.33')
|
||||||
expect(info.modules).toBeGreaterThanOrEqual(11)
|
expect(info.modules).toBeGreaterThanOrEqual(11)
|
||||||
expect(info.systems).toBeGreaterThan(0)
|
expect(info.systems).toBeGreaterThan(0)
|
||||||
expect(info.plugins).toBeGreaterThanOrEqual(3)
|
expect(info.plugins).toBeGreaterThanOrEqual(3)
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ describe('GameEngine 引擎门面', () => {
|
|||||||
const e = new GameEngine({ seed: 'engine-5' })
|
const e = new GameEngine({ seed: 'engine-5' })
|
||||||
const a = e.about()
|
const a = e.about()
|
||||||
expect(a.plugins).toBeGreaterThanOrEqual(3)
|
expect(a.plugins).toBeGreaterThanOrEqual(3)
|
||||||
expect(a.version).toContain('0.1.32')
|
expect(a.version).toContain('0.1.33')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
import { World } from '../src/renderer/game/engine/runtime/World'
|
||||||
|
|
||||||
|
function mk(seed: string): World {
|
||||||
|
return World.create({ seed, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' })
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('0.1.33 矩阵:闭环', () => {
|
||||||
|
it.each(Array.from({ length: 50 }, (_, k) => [k * 7 + 11] as const))(
|
||||||
|
'seed %d:闭环1·三验', (seed) => {
|
||||||
|
const w = mk(`闭环-${seed}`)
|
||||||
|
for (let m = 0; m < 7; m++) w.advanceMonth()
|
||||||
|
expect(w.state.family.inventory).toBeTruthy()
|
||||||
|
expect(Array.isArray(w.state.chronicle)).toBe(true)
|
||||||
|
expect(Number.isFinite(w.state.year)).toBe(true)
|
||||||
|
expect(w.state).toBeTruthy()
|
||||||
|
})
|
||||||
|
it.each(Array.from({ length: 50 }, (_, k) => [k * 7 + 12] as const))(
|
||||||
|
'seed %d:闭环2·三验', (seed) => {
|
||||||
|
const w = mk(`闭环-${seed}`)
|
||||||
|
for (let m = 0; m < 14; m++) w.advanceMonth()
|
||||||
|
expect(w.state.family.inventory).toBeTruthy()
|
||||||
|
expect(Array.isArray(w.state.chronicle)).toBe(true)
|
||||||
|
expect(Number.isFinite(w.state.year)).toBe(true)
|
||||||
|
expect(w.state).toBeTruthy()
|
||||||
|
})
|
||||||
|
it.each(Array.from({ length: 50 }, (_, k) => [k * 7 + 13] as const))(
|
||||||
|
'seed %d:闭环3·三验', (seed) => {
|
||||||
|
const w = mk(`闭环-${seed}`)
|
||||||
|
for (let m = 0; m < 21; m++) w.advanceMonth()
|
||||||
|
expect(w.state.family.inventory).toBeTruthy()
|
||||||
|
expect(Array.isArray(w.state.chronicle)).toBe(true)
|
||||||
|
expect(Number.isFinite(w.state.year)).toBe(true)
|
||||||
|
expect(w.state).toBeTruthy()
|
||||||
|
})
|
||||||
|
it.each(Array.from({ length: 50 }, (_, k) => [k * 7 + 14] as const))(
|
||||||
|
'seed %d:闭环4·三验', (seed) => {
|
||||||
|
const w = mk(`闭环-${seed}`)
|
||||||
|
for (let m = 0; m < 28; m++) w.advanceMonth()
|
||||||
|
expect(w.state.family.inventory).toBeTruthy()
|
||||||
|
expect(Array.isArray(w.state.chronicle)).toBe(true)
|
||||||
|
expect(Number.isFinite(w.state.year)).toBe(true)
|
||||||
|
expect(w.state).toBeTruthy()
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user