iter42-卡1: gdstyle尾波清偿批——board_view五段拆分与构建器/装板域拆BoardInstaller/wr5改址,键1-4+9+10归绿
This commit is contained in:
1 parent
3b66d1a689
commit
66e6d0452a
15 files changed
+342
-1301
No files matched your search
@@ -1,322 +0,0 @@
|
||||
# 设计——单格绘制状态件拆分(board_cell_unit 类变量键真实清偿)
|
||||
|
||||
设计讨论段过程稿 v1.0——待主会话汇总裁决。
|
||||
|
||||
结论行:推荐「绘制层域两件案」——状态件按 _draw 既有的层域轴拆成两个独立文件的绘制域件(格面基座层件 12 成员/格面标识与叠加层件 13 成员),几何与微光子件面留宿主(10 成员),绘制命令随入参同件迁移,宿主 _draw 退为六步时序器;三文件各自类变量 10/12/13,全部低于阈值 15 且不依赖任何闸机口径漏洞。
|
||||
|
||||
---
|
||||
|
||||
## 1. 现状与两项关键发现
|
||||
|
||||
### 1.1 键账现状
|
||||
|
||||
- 涉案键:`game/presentation/views/board_cell_unit.gd|quality/max-class-variables = 30`(tools/gdstyle_baseline.txt,2026-10-29 重锚版)。阈值 15(gdstyle 默认值,tools/gdstyle.toml 不设数值阈值)。
|
||||
- 源码实查(2026-10-29):全文件 33 个类级 var 声明=宿主 6+inner 状态件 `_CellPaintState` 27。闸实测 30(本会话对单文件实跑 gdstyle v0.4.0 复核)。
|
||||
- 文件头注在案:状态件职责语句「单格绘制输入集」;探针直读冻结成员(glyph/fog_state/plate/glyph_color)与 `_glow_layer` 住宿主。
|
||||
- 迭代 41 已把 `_draw` 拆成约 20 个分层私有函数——函数级键已清零,本设计只解决类变量 30 这一个键。
|
||||
|
||||
### 1.2 发现一:gdstyle 对 inner class 的计数不是均匀展平,是「首个 setter 截断」
|
||||
|
||||
主会话给的事实是「inner class 成员按宿主展平计数」。本会话实测修正:截断点在 inner class 内**第一个带 setter 的属性**。
|
||||
|
||||
| 文件 | 声明数(宿主+inner) | 闸实测 | 归因 |
|
||||
|---|---|---|---|
|
||||
| board_cell_unit.gd | 6+27=33 | 30 | 宿主 6+inner 第一个 setter(edge,30–35 行)之后的 24 个=30;setter 声明本身及其之前的 3 个(_owner/cell/edge)留在 inner 类一侧不进宿主账 |
|
||||
| standee_body.gd | 6+25=31 | 19 | 宿主 6+inner 第一个 setter(_intent_scale,37–40 行)之后的 13 个=19 |
|
||||
| board_view.gd(无 inner class) | 32 | 32 | 平面文件=声明数逐一全计 |
|
||||
| main.gd(无 inner class) | 49 | 49 | 同上 |
|
||||
|
||||
四点全部精确吻合。推论三条:
|
||||
|
||||
1. 现行登记值 30 是截断口径的**欠估**——若 gdstyle 升级修掉该解析行为,同文件键跳到 33=恶化红。任何「调整 inner class 内成员顺序/把 setter 挪位置」的降数手法都是在利用解析缺陷,工具一升级即翻车,且属「为迎合机检保留无效形态」,禁。
|
||||
2. 主会话「任何 inner class 重新分组都降不了数」的结论在截断口径下依然成立(重排不改总量级),且存在更深的坑——重排确实能改数(把首个 setter 挪到类尾=宿主账只剩 6),但那正是第 1 条禁的手法。
|
||||
3. **唯一稳健出路=拆成独立文件**:平面文件口径=声明数逐一全计(board_view/main 两点实证),预测值即实数,不依赖闸机任何解析行为。
|
||||
|
||||
### 1.3 发现二:ui_input_probe 疑似潜伏红(迭代 41 合并遗留,须 T0 先证)
|
||||
|
||||
ui_input_probe.gd 有四处**绕过 st 直接读格件成员**的断言:case① `u1.hl_visible`/`u1.hl_color`(234–235 行)、case② `.hl_color`(243–244 行)、case③ `.dot_visible`(250 行)、case⑭ `.mutation_mark`(374–379 行)。这四个成员迭代 41 已随状态件迁入 `_CellPaintState`,而 GDScript 外部实例读不到 inner class 的成员(取索引=运行时脚本错误)。
|
||||
|
||||
时间线:探针末次全绿 2026-10-28 05:03(game/tests/.gates/probe_full.log)早于状态件合入 2026-10-29 01:37(三文件同秒 mtime=合并检出);基线注记「迭代 41 两卡特许直接合回未重跑代码域闸」。合入后探针未跑过,潜伏红未经证实也未经证伪。同批 standee(u4)作者对同类问题做了宿主侧出口(fx_sweep_counters 方法返回计数器字典),u3 未处理这四处直读。
|
||||
|
||||
处置(本设计的立场):**无论潜伏红真假,本设计的拆分都把探针直读面显式化**——hl_color/hl_visible/dot_visible/mutation_mark 落入格面标识与叠加层件,探针四处断言改址 `u.face.*`(对照表申报的探针改址,断言条件与期望值零变化);四个头注冻结成员(glyph/fog_state/plate/glyph_color)留宿主不动。T0 用一次 ui_input_probe 实跑证实或证伪潜伏红,结果记实现报告。
|
||||
|
||||
### 1.4 探针/测试直读面全清单(改址与保留的依据)
|
||||
|
||||
| 消费方 | 读什么 | 现路径 | 设计后路径 |
|
||||
|---|---|---|---|
|
||||
| ui_input_probe case④b⑪ | glyph | u.glyph | u.glyph(宿主冻结,不变) |
|
||||
| ui_input_probe case⑮ | fog_state | u.fog_state | u.fog_state(宿主冻结,不变) |
|
||||
| player_copy_sweep_test wa8 | plate/glyph_color | u.plate/u.glyph_color | 不变(宿主冻结) |
|
||||
| ui_input_probe case①②③⑭ | hl_visible/hl_color/dot_visible/mutation_mark | u.X(已断——潜伏红) | u.face.X(探针改址四处) |
|
||||
| board_view.cell_rect_probe:891 | edge | u.st.edge | u.edge(board_view 内部改址) |
|
||||
| board_shot_probe/type_glow_shot_probe | 格矩形 | 经 cell_rect_probe | 不变(间接) |
|
||||
|
||||
其余状态件成员全仓零外部读方(本会话 grep 全量复核)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 现状成员全列(33 个)
|
||||
|
||||
写入方全部在 board_view.gd(唯一写方文件);行号为 2026-10-29 实查,实现批 T0 重核。setter→重绘语义列=该成员 setter 的现行副作用(无 setter=普通赋值不重绘)。
|
||||
|
||||
### 2.1 宿主 6 个
|
||||
|
||||
| 成员 | 类型 | 重绘语义 | 写入方 | 读取方 | 绘制消费层 |
|
||||
|---|---|---|---|---|---|
|
||||
| st | _CellPaintState 聚合 | — | 宿主 _init:147 | 全部绘制函数经 st.X | 载体 |
|
||||
| glyph | String | setter→queue_redraw | _paint_cell:667 | _draw_glyph_layer:200/205、_draw_fog_memory:344 | 字形层+迷雾记忆态(探针冻结) |
|
||||
| glyph_color | Color(UiKit.INK) | setter→queue_redraw | _paint_cell:668/674 | _draw_glyph_layer:205 | 字形层(探针冻结) |
|
||||
| plate | bool | 无 setter | _paint_cell:675 | **绘制侧零消费**(_draw_digit_plate 由 glyph 非空无条件触发,plate 不参与判据);读方仅 player_copy_sweep_test:138 | 无(探针冻结成员,禁删禁接线——接线即行为变化) |
|
||||
| fog_state | int | 守卫 setter→queue_redraw | _paint_cell:734/736 | _draw_fog_layer:247 | 迷雾层(探针冻结) |
|
||||
| _glow_layer | Node2D 子件 | — | _sync_glow_layer:407–412 | edge/badge_glyph 两 setter、_sync_glow_layer | 微光子件(头注在案住宿主) |
|
||||
|
||||
### 2.2 状态件 27 个
|
||||
|
||||
| 成员 | 类型 | 重绘语义 | 写入方(board_view) | 读取方 | 绘制消费层 |
|
||||
|---|---|---|---|---|---|
|
||||
| _owner | Node2D 回引 | — | 宿主 _init:147 | 各 setter 内部 | — |
|
||||
| cell | Vector2i | 无 setter | rebuild:250 | **全仓零读方** | 无(诊断观测面,待裁点 3) |
|
||||
| edge | float | setter→glow setup+queue_redraw | set_cell_area:204、rebuild:251;读 _paint_cell:704、cell_rect_probe:891 | 全部层 | 全层(rect 尺寸基准) |
|
||||
| bg_sb | StyleBoxFlat | 无 setter | _paint_cell:666 | _draw_base_layer:174、_draw_contact_or_fallback:187、_draw_bevel:314 | 基座层 |
|
||||
| contact_bands | Array[int] | 无 setter | _apply_contact_bands:804 | _draw_contact_bands:271 | 接触带 |
|
||||
| contact_corners | Array[int] | 无 setter | :805 | :279 | 接触带 |
|
||||
| contact_col | Color | 无 setter | _process 呼吸:780/787、_apply_contact_bands:810/816 | _draw_contact_or_fallback:183、_draw_contact_bands:278、_draw_contact_corner:293–305 | 接触带 |
|
||||
| outline_sides | Array[int] | 无 setter | _paint_cell:676(assign)/:700(append) | _draw_base_layer:166、_draw_outline_sides:257 | 描边 |
|
||||
| facade_south | bool | setter→queue_redraw | _paint_cell:677/690;读 :696 | _draw_south_facade:352 | 南立面 |
|
||||
| proj_band | float | setter→queue_redraw | _paint_cell:678/704 | _draw_north_projection:367 | 地面投影 |
|
||||
| badge_glyph | String | setter→glow mask+queue_redraw | _paint_cell:719/726 | _draw_glyph_layer:206–210、_sync_glow_layer:413 | 徽章 |
|
||||
| dot_visible | bool | setter→queue_redraw | 路径预览:549/554 | _draw_overlay_layers:230 | 叠加层(探针直读 case③) |
|
||||
| hl_visible | bool | setter→queue_redraw | 悬停:512/517/521/525/534 | :233 | 叠加层(探针直读 case①) |
|
||||
| hl_color | Color | setter→queue_redraw | :513/518/522/526 | :235 | 叠加层(探针直读 case①②) |
|
||||
| font | Font | 无 setter | set_world_font:185、rebuild:260 | _draw_glyph:392、_draw_badge:418 | 字形/徽章/迷雾记忆 |
|
||||
| bevel | float | setter→queue_redraw | rebuild:253 | _draw_bevel:312–321 | 倒角 |
|
||||
| tex_base | Texture2D | 无 setter | _paint_cell:665 | _draw_base_layer:161、_draw_fog_memory:341 | 基座+迷雾记忆 |
|
||||
| tex_mutation | Texture2D | 无 setter | 无(素材槽位恒 null) | _draw_glyph_layer:197 | 纹带槽 |
|
||||
| tex_glyph | Texture2D | 无 setter | 无(槽位) | :202 | 数字槽 |
|
||||
| tex_badge | Texture2D | 无 setter | 无(槽位) | :207 | 徽章槽 |
|
||||
| tex_seal | Texture2D | 守卫 setter→queue_redraw | _paint_cell:614/618 | :212 | 封印槽 |
|
||||
| tex_facade | Texture2D | 无 setter | _paint_cell:679/709 | _draw_e_facade:380–386 | E 格墙面 |
|
||||
| facade_strip | bool | setter→queue_redraw | _paint_cell:680/708 | :380 | E 格墙面 |
|
||||
| treasure_mark | String | 守卫 setter→queue_redraw | _paint_cell:713 | _draw_mutation_marks:326 | 变异标记 |
|
||||
| mutation_mark | String | 守卫 setter→queue_redraw | _paint_cell:723/725 | :330 | 变异标记(探针直读 case⑭) |
|
||||
| glow_group | int | 守卫 setter→_owner._sync_glow_layer() | _paint_cell:727、_sync_glow_to_units:768 | _sync_glow_layer:404/412 | 微光子件 |
|
||||
| removed_dim | bool | setter→queue_redraw | _paint_cell:737 | _draw_overlay_layers:239 | 退色层 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 方案形态——三条路的评估
|
||||
|
||||
### 3.1 路 A:状态件升格独立文件×N(推荐,取「绘制域件」形态)
|
||||
|
||||
按 _draw 已有的层域轴切。迭代 41 拆函数时已经沿这条轴走了(基座/字形/叠加/迷雾/描边/接触带/倒角……),本设计把同一条轴从函数级升到类级:**每个件=一个绘制层的入参+该层的绘制命令**。件有行为(draw 方法族+setter 重绘语义)、有职责语句、单一变化原因=该层的视觉规格(art-bible 对应条款族),满足 code-conventions §1.1 全部五条拆分判据与 §1.2「功能=类」。这是对迭代 41「被动数据袋」否决的正面回答:成员不再是「剩下的装一起」,而是「这一层画什么、怎么画」的完整领域单元。
|
||||
|
||||
细化两个子形态:
|
||||
|
||||
- **A2 绘制命令随迁(推荐)**:件的 draw 方法持有绘制命令本体,宿主 _draw 退为时序器。真内聚(状态+行为同件);宿主从 423 行缩到约 150 行,退离 §1.1 的 400 行审视线。
|
||||
- **A1 纯入参件(淘汰)**:件只装数据,绘制函数留宿主。宿主仍有约 20 个绘制函数经 st 间接取值,件本质=把一个被动数据袋拆成两个被动数据袋,迭代 41 的否决理由原样复活;§1.1-① 立不住。
|
||||
|
||||
### 3.2 路 B:成员真实削减(淘汰为主出路,保留两处微收割)
|
||||
|
||||
要降到 15 需削 18 个成员,而可削的只有:
|
||||
|
||||
- `cell`:全仓零读方(写入仅 rebuild 一处)。可删,零行为变化(待裁点 3)。
|
||||
- `plate`:绘制侧零消费,**但**是探针冻结成员(player_copy_sweep_test wa8 直读)——禁删;给它接上绘制判据反而改变 golden 现状(「人」回退格会少画牌),禁。
|
||||
- tex_mutation/tex_glyph/tex_badge 三槽位:从未被写入但被 _draw 消费(elif 程序化回退路径),是 art-bible §8.2 在册素材槽位——结构承载,非无效成员,留。
|
||||
|
||||
削减上限 1–2 个,差 16 个以上,**单独不可达**。上移 board_view 方向被堵死:board_view 类变量 32 已按尾波卡 D5 裁豁免终局(键永久基线内、禁再恶化),上移任何成员都构成禁再恶化的恶化。
|
||||
|
||||
### 3.3 路 A3:整体搬成一个大状态件文件(淘汰)
|
||||
|
||||
状态件 24–27 个成员整体独立成文件,新文件自身 24–27>15=基线外新键——任务简报预警的陷阱,实测确认。拆是必须的,问题只是切几刀、沿什么轴。
|
||||
|
||||
### 3.4 路 C:重绘回引形态三选(随 A2 定案)
|
||||
|
||||
| 形态 | 判定 |
|
||||
|---|---|
|
||||
| **_owner 直引(推荐,现状形态)** | Node 持 RefCounted 成员、RefCounted 持 Node 回引——Node 引用不参与引用计数,**无环无泄漏**(现行 inner class 同款,先例在役)。setter 语句逐字保形,零新契约。Godot 官方判据下 RefCounted 值对象持宿主回引是常规形态。 |
|
||||
| Callable 注入 | 淘汰。edge/badge_glyph/glow_group 三个 setter 的副作用不止 queue_redraw(glow 层 setup/badge mask/子件同步),一个 Callable 表达不了,得注两三个=每件多 1–2 成员+setter 体改写=语义面重写而非迁移。 |
|
||||
| 信号 | 淘汰。Godot 信号同步派发、时序等价,但守卫式 setter(tex_seal/treasure_mark/mutation_mark/fog_state 的判重)与 glow 副作用都得改写成发射+宿主分发,新增每信号一行的 §2.1 成文义务,换不来任何行为收益。 |
|
||||
| 弱引用 | 淘汰。解的是不存在的环引用问题,白白加 is_instance_valid 守卫复杂度。 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 拆分定案(推荐案 A2 两件案)
|
||||
|
||||
### 4.1 总账
|
||||
|
||||
| 文件 | 类变量(全计) | 构成 |
|
||||
|---|---|---|
|
||||
| board_cell_unit.gd(宿主) | **10** | edge/cell/glow_group/glyph/glyph_color/plate/fog_state/_glow_layer/base/face |
|
||||
| cell_base_layer.gd(新) | **12** | _owner/bg_sb/contact_bands/contact_corners/contact_col/outline_sides/facade_south/proj_band/bevel/tex_base/tex_facade/facade_strip |
|
||||
| cell_mark_overlay.gd(新) | **13** | _owner/badge_glyph/dot_visible/hl_visible/hl_color/font/tex_mutation/tex_glyph/tex_badge/tex_seal/treasure_mark/mutation_mark/removed_dim |
|
||||
|
||||
对账:原 33 声明=新 10+12+13=35;差额 2=每件各持一个 _owner(原仅一个)。edge/cell/glow_group 上收宿主的理由:edge 是格件自身几何且其 setter 驱动宿主自有 _glow_layer(收编后 setter 体少两处跨对象回引);glow_group 驱动微光子件生命周期(加/撤子节点是 Node 职责,RefCounted 件做不了);cell 是格件身份。三者上收后,跨对象回引只剩「件→宿主 queue_redraw/glow mask」这一类,与头注「setter 触发宿主重绘语义经 _owner 回引保持逐字」完全同形。
|
||||
|
||||
### 4.2 件 A:cell_base_layer.gd(格面基座层绘制件)
|
||||
|
||||
- 落点:`game/presentation/views/cell_base_layer.gd`;extends **RefCounted**(godot-master 判据:瞬态逻辑/数据容器用 RefCounted,Resource 是给可序列化、要进 Inspector 的数据——绘制入参每拍重写、永不落盘,Resource 只带来共享默认值陷阱与序列化包袱);无 class_name(类名缓存面纪律,同宿主与 cell_type_glow_layer 先例),经宿主 preload 引用。
|
||||
- 职责语句:格面基座层绘制域——底面/描边/高墙立面/地面投影/接触带微光/顶面倒角的全部绘制入参与绘制命令。
|
||||
- 单一变化原因:art-bible 基座层视觉规格(§1.2 叠层序/§3.2 接触带/§8.5 结构归程序/v3.5 冻结①立面条款族)——瓦片、立面、投影、微光的画法变了改本件,不触字形与迷雾。
|
||||
- 成员:上表 4.1 行所列 12 个;类型与默认值逐字继承,四个 setter(facade_south/proj_band/bevel/facade_strip)体逐字(_owner.queue_redraw())。
|
||||
- 绘制命令:现宿主九个私有函数随迁——_draw_base_layer/_draw_outline_sides/_draw_south_facade/_draw_north_projection/_draw_e_facade/_draw_contact_or_fallback/_draw_contact_bands/_draw_contact_corner/_draw_bevel——逐字搬运,三处机械改写:`st.X`→裸成员名、`draw_X(...)`→`canvas.draw_X(...)`、`st.edge`→`rect.size.x`;公开入口一个 `draw_base(canvas: CanvasItem, rect: Rect2)`,其余私有。九函数现役零超标键(基线无其函数级键),搬运不改行数与分支=零新函数级键。
|
||||
- 常量随迁:FACADE_HIGHLIGHT_PX/FACADE_NEAR_FRAC/FACADE_FAR_FRAC/FACADE_NEAR_COL/FACADE_FAR_COL/PROJECTION_NEAR_COL/PROJECTION_MID_COL/PROJECTION_EDGE_COL/E_FACADE_FRAC 九个 D/E 档常量(本会话 grep 实查全仓零外部引用,宿主头注「绘制侧单点」句随迁改写)。UiKit.E_FACADE_FOOT_COL 是 UiKit 自己的成员,不动。
|
||||
- 素材槽位 tex_base 例外消费:迷雾记忆态画底纹(宿主 _draw_fog_memory)读 base.tex_base——公开成员读,单向、成文于宿主头注。
|
||||
|
||||
### 4.3 件 B:cell_mark_overlay.gd(格面标识与顶层叠加绘制件)
|
||||
|
||||
- 落点:`game/presentation/views/cell_mark_overlay.gd`;extends RefCounted;无 class_name。
|
||||
- 职责语句:格面标识与顶层叠加绘制域——变异标记/数字色牌与字形/奖励徽章/封印/路径点迹/焦点高亮/中立移除退色的全部绘制入参与绘制命令。
|
||||
- 单一变化原因:art-bible 标识与叠加层视觉规格(冻结④色牌/徽章金字/真视红框/悬停高亮/退色降档条款族)——「格面上标什么记号」变了改本件,不触底面与迷雾。
|
||||
- 成员:上表 4.1 行所列 13 个;八个守卫/非守卫 setter 体逐字(含 badge_glyph 的 glow mask 回引 `_owner._glow_layer`——头注在案的回引语义原样保留)。
|
||||
- 绘制命令:现宿主六个私有函数随迁——_draw_mutation_marks/_draw_glyph_layer/_draw_digit_plate/_draw_glyph/_draw_badge+_draw_overlay_layers 的 dot/hl/removed 三段。字形文字与色(glyph/glyph_color)是宿主冻结成员,作**参数**传入(`draw_glyph_layer(canvas, rect, glyph, glyph_color)`,4 参≤5);文字渲染单点化为本件公开方法 `draw_centered_text(canvas, rect, text, color, font_size)`(5 参合规),宿主迷雾记忆态复用它画记忆墨数字——零复制。
|
||||
- 拆出两个绘制入口的原因:迷雾(fog_state 宿主冻结成员)在原 _draw_overlay_layers 内部夹在 hl 与 removed 之间,宿主时序器在两入口之间插雾层——见 §6。
|
||||
|
||||
### 4.4 宿主保留面(10 成员)
|
||||
|
||||
- 职责语句:被动绘制壳——绘制时序器+视野迷雾域(fog_state 冻结成员+记忆态换装)+微光子件生命周期(_glow_layer/glow_group/_sync_glow_layer)+格件几何(edge/cell)+探针冻结面(glyph/glyph_color/plate)。
|
||||
- 单一变化原因:迷雾规格(art-bible §6.5)与格件节点生命周期。迷雾居基座与标识两件之上、又读件 A 的 tex_base 与件 B 的字体渲染——把它留在宿主是三域中唯一不产生跨件回引的落点。
|
||||
- 头注改写要点(S10 口径 ≤8 行、无日期、无链接):状态件句改为两件句;「探针直读冻结成员」清单照旧(glyph/fog_state/plate/glyph_color+_glow_layer);新增一句「hl_color/hl_visible/dot_visible/mutation_mark 探针读 u.face.*」。
|
||||
|
||||
### 4.5 宿主 _init 与建件
|
||||
|
||||
```
|
||||
const _BASE_LAYER := preload("res://presentation/views/cell_base_layer.gd")
|
||||
const _MARK_OVERLAY := preload("res://presentation/views/cell_mark_overlay.gd")
|
||||
|
||||
func _init() -> void:
|
||||
base = _BASE_LAYER.new(self)
|
||||
face = _MARK_OVERLAY.new(self)
|
||||
```
|
||||
|
||||
件侧 `func _init(owner: Node2D) -> void: _owner = owner`(S9 R3 对 _init 参数豁免——构造注入面形态自由)。每格三对象(Node2D+两 RefCounted)与现状每格两对象同量级;尾波卡 T1 的 `_build_cell_unit` 构建器里仍只有一处 `_CELL_UNIT.new()`,件在宿主 _init 内自建,不触发 allocation-in-loop 新键(该规则扫循环体内的 .new() 文本,构建器函数体不在循环体内)。
|
||||
|
||||
### 4.6 类型闸与头注义务
|
||||
|
||||
两个新件全量类型标注(S9 R1/R2/R3 同尺度);文件头 `##` 注释 ≤8 行、零日期、零链接、零变更叙事(S10);每件头注写职责语句与 _owner 回引语义(§2.1 精神——回引不是跨类信号,无信号成文义务)。
|
||||
|
||||
---
|
||||
|
||||
## 5. setter→重绘语义零变化论证(写入路径逐点对账)
|
||||
|
||||
原则:全部 setter 体逐字搬家或原位不动;改址只改 board_view 侧赋值表达式的路径段。queue_redraw 本身合帧(同帧多次申请一次重绘),时序逐字=写入点顺序不变。
|
||||
|
||||
### 5.1 board_view 写入面改址对照(行号 2026-10-29,T0 重核)
|
||||
|
||||
| 现写点 | 新写点 | 语义 |
|
||||
|---|---|---|
|
||||
| u.st.edge(:204/:251 写;:704/:891 读) | u.edge | 宿主 setter 体:原 `_owner._glow_layer`→`_glow_layer`、`_owner.queue_redraw()`→`queue_redraw()`——glow setup+重绘的执行序逐字等价(语句同、对象同、时机同) |
|
||||
| u.st.glow_group(:727/:768) | u.glow_group | 守卫 setter 调 _sync_glow_layer()(原经 _owner 转发,现直调——同一函数同一时机) |
|
||||
| u.st.cell(:250) | u.cell(或随待裁点 3 删除) | 无 setter,纯数据 |
|
||||
| u.st.bg_sb(:666) | u.base.bg_sb | 无 setter |
|
||||
| u.st.tex_base(:665) | u.base.tex_base | 无 setter |
|
||||
| u.st.outline_sides(:676 assign/:700 append) | u.base.outline_sides | 无 setter;**assign 保持数组引用语义**——件内成员同为一处 Array[int],引用不变 |
|
||||
| u.st.facade_south(:677/:690 写;:696 读) | u.base.facade_south | setter→queue_redraw 逐字;双写触发两次申请=现状同形 |
|
||||
| u.st.proj_band(:678/:704) | u.base.proj_band | 同上 |
|
||||
| u.st.tex_facade(:679/:709) | u.base.tex_facade | 无 setter |
|
||||
| u.st.facade_strip(:680/:708) | u.base.facade_strip | setter→queue_redraw 逐字 |
|
||||
| u.st.contact_bands/corners(:804/:805) | u.base.contact_* | 无 setter(整组引用换新) |
|
||||
| u.st.contact_col(:780/:787/:810/:816) | u.base.contact_col | 无 setter(_process 逐拍呼吸色) |
|
||||
| u.st.bevel(:253) | u.base.bevel | setter→queue_redraw 逐字 |
|
||||
| u.st.badge_glyph(:719/:726) | u.face.badge_glyph | setter:`_owner._glow_layer` mask+queue_redraw 逐字(回引体原样) |
|
||||
| u.st.dot_visible(:549/:554) | u.face.dot_visible | setter→queue_redraw 逐字 |
|
||||
| u.st.hl_visible/hl_color(:512–526/:534) | u.face.hl_* | setter→queue_redraw 逐字 |
|
||||
| u.st.tex_mutation/tex_glyph/tex_badge | u.face.tex_* | 无 setter |
|
||||
| u.st.tex_seal(:614/:618) | u.face.tex_seal | 守卫 setter 逐字(判重防覆盖语义是 case④b 回归断言的守护对象,禁动) |
|
||||
| u.st.treasure_mark/mutation_mark(:713/:723/:725) | u.face.*_mark | 守卫 setter 逐字 |
|
||||
| u.st.removed_dim(:737) | u.face.removed_dim | setter→queue_redraw 逐字 |
|
||||
| u.st.font(:185/:260) | u.face.font | 无 setter |
|
||||
| u.glyph/u.glyph_color/u.plate/u.fog_state | 不变 | 宿主冻结面 |
|
||||
| u.queue_redraw()(:738 终写) | 不变 | paint 尾部全格重绘申请原样 |
|
||||
|
||||
### 5.2 宿主内消费改址
|
||||
|
||||
- _sync_glow_layer:st.glow_group→glow_group、st.edge→edge、st.badge_glyph→face.badge_glyph(公开成员读);setup/set_badge_mask 调用序逐字。
|
||||
- _draw_fog_memory:st.tex_base→base.tex_base;字形重画改调 face.draw_centered_text(self, rect, glyph, UiKit.FOG_MEMORY_INK, maxi(18, int(ceil(edge * 0.5))))——同公式同字号(§7.4 冻结式)。
|
||||
- cell_rect_probe:u.st.edge→u.edge。
|
||||
|
||||
---
|
||||
|
||||
## 6. 绘制命令序零变化论证(golden 判据本体)
|
||||
|
||||
新宿主 _draw=六步时序器,命令序与现行四函数调用树**逐命令等价**:
|
||||
|
||||
```
|
||||
func _draw() -> void:
|
||||
var rect := Rect2(Vector2.ZERO, Vector2(edge, edge))
|
||||
base.draw_base(self, rect) # 原青 _draw_base_layer 整树(含描边/立面/投影/接触带/倒角与其补画序)
|
||||
face.draw_marks(self, rect) # 原青 _draw_mutation_marks
|
||||
face.draw_glyph_layer(self, rect, glyph, glyph_color) # 原青 _draw_glyph_layer+_draw_digit_plate+_draw_glyph+_draw_badge
|
||||
face.draw_overlay_under(self, rect) # 原青 _draw_overlay_layers 前两段(点迹+高亮)
|
||||
_draw_fog_layer(rect) # 宿主(原位不变——雾夹在 hl 与 removed 之间)
|
||||
face.draw_removed_dim(self, rect) # 原青 _draw_overlay_layers 末段(退色)
|
||||
```
|
||||
|
||||
等价性来源:①层间顺序=原 _draw 的四调用序+_draw_overlay_layers 内部序,一步未动;②件内顺序=九+六函数逐字搬运,`draw_*` 引擎调用全部经 canvas 参数落到同一 CanvasItem(宿主 self),命令流与命令参数逐位相同;③接触带回退路径(contact_col.a>0 时补画投影/E 墙面/接触带;elif bg_sb 路径补画立面/投影/倒角)整体在件 A 内部,补画序逐字;④浮点面:rect.size.x 与 st.edge 同值同源,推导式零改动。结论:绘制命令流逐位一致 ⇒ golden 三张差异 0.00% 可预期。
|
||||
|
||||
---
|
||||
|
||||
## 7. gdstyle 键账预期(逐文件,平面口径=声明数全计)
|
||||
|
||||
| 文件 | 类变量(阈值 15) | 公开方法(阈值 20) | 函数级键预测 |
|
||||
|---|---|---|---|
|
||||
| board_cell_unit.gd | 10(余量 5) | 6(5 setter+_draw) | 无——_draw 时序器约 10 行;_draw_fog_layer/_draw_fog_memory/_sync_glow_layer 原体(现役零键) |
|
||||
| cell_base_layer.gd | 12(余量 3) | 5(draw_base+4 setter) | 无——九函数逐字搬运,行数/分支/局部/返回不变,现役零键 |
|
||||
| cell_mark_overlay.gd | 13(余量 2) | 13(5 绘制入口+8 setter) | 无——同上;draw_glyph_layer 4 参、draw_centered_text 5 参(max-parameters 5=合规上限内) |
|
||||
|
||||
三件全无 inner class ⇒ 不受 §1.2 截断口径影响,预测值即闸实测值。余量最小 2(件 B)——后续 art-bible 加标记类成员的余量,恶化守卫(WORSENED)在位兜底。
|
||||
|
||||
---
|
||||
|
||||
## 8. 行为零变化风险点
|
||||
|
||||
1. **golden 三张(L1 dungeon/L2 underdark/L3 deep_underdark)**:判据=§6 命令流逐位一致;差异非零即停机呈报,禁换锚。最大实操风险=搬运时手误(常量值、rect 推导式)——对照表逐函数「逐字搬运」核对。
|
||||
2. **探针冻结成员**:glyph/fog_state/plate/glyph_color 宿主保留、名称路径零变化(ui_input case④b⑪⑮+player_copy wa8 断言零改动);hl_*/dot_visible/mutation_mark 探针改址四处(断言条件与期望值零变化,只改路径段——对照表申报行)。
|
||||
3. **绘制调用序**:见 §6——含「平色回退+微光并发的英雄格补画」这种跨层重复绘制路径,必须原样保形(重复无害是现行为的一部分)。
|
||||
4. **setter 双写时序**:_paint_cell 内 facade_south(:677/:690)、badge_glyph(:719/:726)、mutation_mark(:723/:725)的多写多触发序不变。
|
||||
5. **`_glow_layer` 生命周期**:宿主成员不动;glow_group/edge 上收后其 setter 直调宿主自有面——子件 add/free 时机零漂移(type_glow_shot_probe/type_glow_probe 断言面)。
|
||||
6. **潜伏红变量**:T0 先跑 ui_input_probe——若现状已红(§1.3 判定),红因与本设计无关但同批修复(改址四处);若绿(本会话对 GDScript 取索引语义判断有误),改址四处照做(新路径本就不同),结论记实现报告。
|
||||
|
||||
---
|
||||
|
||||
## 9. 验收载体建议(全部既有载体,零新增断言面)
|
||||
|
||||
| 载体 | 钉什么 |
|
||||
|---|---|
|
||||
| render_gate 棋盘 golden 三张 | 绘制命令流逐位一致(本批主判据;对拍差异 0.00%) |
|
||||
| ui_input_probe(probe_gate 默认段) | case①②③④b⑪⑭⑮——悬停/禁入/点迹/封印槽/字形回退/变异角标/迷雾直读面全链路 |
|
||||
| probe_gate --click(ui_click_probe) | dig/seal/chord 输入路径(hl 状态写入面的行为侧) |
|
||||
| probe_gate --full(type_glow_shot_probe/board_shot_probe/fx_probe) | 微光子件与格矩形取证面 |
|
||||
| run_all --only=player_copy,theme_projection,type_glow | u.plate/u.glyph_color 直读面+字形墨族+微光派生 |
|
||||
| run_smoke+run_system_test+static_scan(三件保险恒跑) | 启活面+真实玩法路径+S9/S10/S13 键账对账 |
|
||||
|
||||
批末跑 `tools/run_all_gates.sh --code`(改动全为代码面);改址探针断言与对应表申报同批落地。
|
||||
|
||||
---
|
||||
|
||||
## 10. 估时
|
||||
|
||||
| 段 | 内容 | 估时 |
|
||||
|---|---|---|
|
||||
| T0 | 读数复核(33 声明/30 闸账对账)+ui_input_probe 潜伏红一跑定谳 | 0.25–0.5 日 |
|
||||
| T1 | 建 cell_base_layer.gd(成员+九函数+九常量随迁) | 0.5–0.75 日 |
|
||||
| T2 | 建 cell_mark_overlay.gd(成员+六函数随迁+draw_centered_text 单点化) | 0.5–0.75 日 |
|
||||
| T3 | 宿主瘦身(时序器/雾/glow/edge/glow_group setter 上收)+board_view 写入面约 40 处改址 | 0.5 日 |
|
||||
| T4 | 探针改址四处+孤立验证(run_all 选档+probe_gate --click) | 0.25–0.5 日 |
|
||||
| T5 | 批末代码域全量闸+键账对账(10/12/13 实测核对) | 0.25–0.5 日 |
|
||||
|
||||
合计 2.25–3.5 工作日。出红只跑红件最小单元(闸机轮次纪律)。
|
||||
|
||||
---
|
||||
|
||||
## 11. 待裁点清单(呈主会话)
|
||||
|
||||
1. **潜伏红处置**:ui_input_probe 四处直读疑似已被迭代 41 打断(§1.3)。方案=本设计批内改址 u.face.* 并 T0 实跑定谳;若用户希望不等本批,可先走最小工程批把四处改 u.st.* 恢复(后续本批再改一次)。取哪个时序,裁。
|
||||
2. **与尾波清偿卡的编排关系**:尾波卡 T1 把 _paint_cell 拆五段(传值句写明「经 u.st/glyph/digit_col」)。本设计改变状态件路径名——同批编队时 T1 段函数传值句改指 u.base./u.face.(T0 对账自然兜住);先后皆可,同批省一次 golden 全套。取哪个编队,裁。
|
||||
3. **cell 成员去留**:全仓零读方(写入仅 rebuild:250)。删除=真实削减+§1.1-⑤ 无效成员归零;保留=「诊断观测面」注释语义。本设计倾向删(宿主降为 9),删/留,裁。
|
||||
4. **gdstyle 截断口径的登记**:§1.2 发现属工具行为事实(基线欠估、工具升级可能翻键),建议经反哺点通道在 gdstyle_gate 头注或审计报告补一句注记(工程改动,防后人按「均匀展平」误判键账)。落不落、落哪里,裁。
|
||||
|
||||
---
|
||||
|
||||
## 12. 把握度声明
|
||||
|
||||
把握最低的一点:**潜伏红判定**——它建立在「GDScript 外部实例读不到 inner class 成员」这一语义判断与时间线推断上,本会话禁跑测试无法实证,T0 一次 ui_input_probe 即可证实或证伪;即便误判(现状可读),设计本身不受影响(改址四处照做,冻结四面照留)。次低:gdstyle 截断口径系两点反推(30=6+24、19=6+13 双双精确吻合),未读工具源码;设计不依赖该口径——三文件平面化后预测=实数。
|
||||
@@ -1,183 +0,0 @@
|
||||
# 设计——战斗编排类变量归约(S13 真修复方案)
|
||||
|
||||
> 设计讨论段过程稿 v1.0——待主会话汇总裁决(2026-10-29)。输入=用户裁定「不允许任何豁免:battle_orchestrator.gd 的 max-class-variables 必须真实修复到阈值 15 内,architecture S13 豁免登记第三条注销」。读者=主会话(裁决)与后续写卡段(转需求卡片)。
|
||||
|
||||
## 结论
|
||||
|
||||
宿主 38 个类变量经「BoardInstaller 已定稿退役 1 + 两枚新件收编 19 + 库存注入改址 1 + 攻基线快照转派生读 1」收敛到 **15(=阈值,合规)**。两枚新件:RoundCycle(轮循环驱动件——五段段件持有、段序执行、结算重入门闸、开轮摇号、踩雷计数账)与 BattleFacts(战斗事实件——受理事实、轮 facts 缓冲、封印判定账、装板溯源、条件计数、同调装配快照)。已实装两拆件 BattleFxHost/RewardGrant 与五段段类构造、呈现层、A2 订阅面、封闭流全部零触碰或仅改指。
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标形态——battle_orchestrator 改后保留什么
|
||||
|
||||
宿主保留的是「编排」本身,全部在 architecture「战斗编排域拆件定稿」第 1 款的在册职责面内(attune 一款按本文件第 5 节重裁决为「状态归事实件、行为留宿主」):
|
||||
|
||||
1. **状态机与生命周期**:`begin_battle` 受理四段序列(受理/装板/运行态/预告经济)、`_exit_distribution` 轮间转移、`_battle_over` 终局序列、`battle_result` 与 `_fatal` 唯一写点、`round_index` 轮时钟。
|
||||
2. **A2 三事件订阅与事件处理**:三条 connect 留 `_init`(订阅面逐字);`_on_cell_revealed`(旁路守卫→积点自动兑付触发→身份快照捕获→缓冲追加)、`_on_seal_judged`、`_on_round_end` 三个处理器留宿主——它们是多件协作的编排判断点,不是纯缓冲。
|
||||
3. **行发射基建**:`_emit_row`/`_assert_row_source`/`_fatal`+SOURCE_EXEMPT 两常量词表——协议面单点,零迁移。
|
||||
4. **呈现投影**:`presentation_snapshot`/`diagnostic_snapshot`/`_emit_settlement_snapshot` 三出口——签名与载荷逐字不变,内部读数改指两件投影。
|
||||
5. **刷新面**:`can_refresh`/`player_request_refresh`。
|
||||
6. **attune 编排读数与触发面**(重裁决后):`attune_has`/`attune_param_sum`/`attune_convert_state`/`_attune_charge_safe_row`/`_reseed_attune_charges`/`_hook_attune_consume`/`_attune_safe_seen_read`/积点自动兑付体——读数出口与外部面零改址(见第 5 节)。
|
||||
7. **账本读面**:`_journal`/`_attune_loadout`/`_battle_hooks` 三派生读与回调束。
|
||||
8. **装板薄壳**:`_install_and_reset`(轴丙定稿形态——五处计数清零、板序推进、board_changed 发射、叠加层退役,时序逐字)。
|
||||
9. **B2/B3/B4 协作者持有**:S7「唯一调用方=B1 域文件集」的承载面。
|
||||
|
||||
搬出去的只有两类东西:**轮结算周期的推进机构**(谁持有段件、按什么顺序跑、开轮怎么摇号、重入怎么挡——归 RoundCycle)与**发生过什么与本战是什么的记录**(事实账——归 BattleFacts)。两件的职责语句与单一变化原因见第 3、4 节。
|
||||
|
||||
## 2. 逐成员去向对账表(38 项)
|
||||
|
||||
| # | 成员 | 去向 | 依据(一句话) |
|
||||
|---|---|---|---|
|
||||
| 1 | db | 留宿主 | B1 跨系统调用权的表读取面,宿主级协作者 |
|
||||
| 2 | rng | 留宿主 | encounter/gp_drop 两封闭流在宿主函数体内,behavior_roll 随摇号件经 oc 取用 |
|
||||
| 3 | _board_generator | **随 BoardInstaller 退役** | 轴丙已定稿(v1.24):实例随件自建自接线 |
|
||||
| 4 | minesweeper | 留宿主 | A2 订阅面+HUD 公有消费面(API Boundaries 在册)双锁定 |
|
||||
| 5 | action_economy | 留宿主 | A3 回发面+HUD 公有消费面双锁定 |
|
||||
| 6 | _enemy_system | 留宿主 | B2 生命周期(spawn/despawn)与三快照读源 |
|
||||
| 7 | _status_effects | 留宿主 | B3 开域/闭域与三快照读源 |
|
||||
| 8 | _reward_economy | 留宿主 | B4 恰一次 roll/retire 编排+set_treasure_unlocked/query_reward_identity 两外部代理 |
|
||||
| 9 | treasure_inventory | **退役改址** | 唯一外部注入点 level_runner:520 改经 `reward_grant()` 出口直注(RewardGrant 在册成员);宿主与授予段读面改指 grant |
|
||||
| 10 | _damage | 留宿主 | 单据管线接线(fx_calls/inject)与 AC 基线注入时序锁定在受理段内 |
|
||||
| 11 | _fx_host | 留宿主 | 组件出口 `fx_host()`——定稿在册取件面 |
|
||||
| 12 | _reward_grant | 留宿主 | 组件出口 `reward_grant()`+库存持有者+escrow 读源 |
|
||||
| 13 | encounter | **BattleFacts** | 本战受理事实(打什么、带什么进来)——与过程事实同一记录口径 |
|
||||
| 14 | round_index | 留宿主 | 轮时钟;system_test 等四套件约 15 处 `settlement.round_index` 公有直读面,零改址 |
|
||||
| 15 | battle_result | 留宿主 | 状态机终局态;_fatal/_battle_over 唯一写点归属不变 |
|
||||
| 16 | _facts_reveals | **BattleFacts.reveals** | 轮 facts 缓冲 |
|
||||
| 17 | _facts_seals | **BattleFacts.seals** | 封印判定批缓冲 |
|
||||
| 18 | _facts_path | **BattleFacts.path** | 轮末路径事实 |
|
||||
| 19 | _settling | **RoundCycle._settling** | 结算重入门闸——与段序执行同一单元 |
|
||||
| 20 | _grant_seg | **RoundCycle** | 五段段件持有归驱动件(定稿「段序编排+接线」的代码承载) |
|
||||
| 21 | _aura_seg | **RoundCycle** | 同上 |
|
||||
| 22 | _combat_seg | **RoundCycle** | 同上 |
|
||||
| 23 | _decay_seg | **RoundCycle** | 同上 |
|
||||
| 24 | _verdict_seg | **RoundCycle** | 同上 |
|
||||
| 25 | _refresh_used_this_round | **BattleFacts.refresh_used** | 本轮刷新计数=过程事实(复位点=出口分发,语句随迁) |
|
||||
| 26 | _board_seq | **BattleFacts.board_seq** | 装板溯源事实 |
|
||||
| 27 | _board_from_midround_refresh | **BattleFacts.board_from_midround** | 装板 provenance(清图奖励守卫读源) |
|
||||
| 28 | _seal_consumed | **BattleFacts.seal_consumed** | 封印兑付资格账(install 重置) |
|
||||
| 29 | attunement | **BattleFacts.attunement** | 本战装配集快照=受理事实(enc.attunement 携带) |
|
||||
| 30 | _mines_hits | **RoundCycle.mines_hits** | 摇号条件账——转存语句本就在 `_roll_round_actions` 轮末,随摇号件走 |
|
||||
| 31 | _attune_safe_seen | **BattleFacts.attune_safe_seen** | 积点计数=过程事实 |
|
||||
| 32 | nest_preview_count | 留宿主 | 冻结外部直读面(main.gd×2+treasure_effects_test×1)零变化 |
|
||||
| 33 | _feat_first_dig_used | **BattleFacts.feat_first_dig_used** | 条件事实计数(魔矢每战首次) |
|
||||
| 34 | _seal_miss_seen | **BattleFacts.seal_miss_seen** | 标错去重账 |
|
||||
| 35 | _perfect_hit_true | **BattleFacts.perfect_hit_true** | 完美封印三账(契约 2 写口归件,见第 4 节) |
|
||||
| 36 | _perfect_hit_false | **BattleFacts.perfect_hit_false** | 同上 |
|
||||
| 37 | _perfect_forgiven | **BattleFacts.perfect_forgiven** | 同上 |
|
||||
| 38 | _hero_atk | **退役→派生读函数** | `_hero_atk()` 派生读(`encounter.get("hero_atk", 表值)`)——`_journal()`「读面即引用、无第二账」同款先例;E4 收口语义不变(encounter 受理后只读,派生值恒等) |
|
||||
|
||||
**宿主改后 15 项**:db、rng、minesweeper、action_economy、_enemy_system、_status_effects、_reward_economy、_damage、_fx_host、_reward_grant、round_index、battle_result、nest_preview_count、_rounds、_facts。
|
||||
|
||||
## 3. 新件一:RoundCycle(轮循环驱动件)
|
||||
|
||||
- **文件落点**:`game/core/settlement/round_cycle.gd`(与五段段件同目录——它是段件的序主人)。
|
||||
- **extends**:RefCounted(fx_host/reward_grant/段类同款;随编排器每战新建同灭)。
|
||||
- **职责语句**:每轮结算周期的唯一驱动——结算重入门闸(settling)、五段段序执行(段序骨架冻结于 SettlementTable.segment_order)、开轮摇号(共识点 B:技能选择前置到轮次开始,摇定即本拍结算的选技)、踩雷计数账(转存时点=摇号轮末)。
|
||||
- **单一变化原因**:轮结算周期的推进结构(段序、重入闸、摇号时序)。
|
||||
- **类变量(8 ≤ 15)**:`oc`(宿主,段类同款直调形态)、`_grant_seg`、`_aura_seg`、`_combat_seg`、`_decay_seg`、`_verdict_seg`、`_settling`、`mines_hits`({"total","last","round"} 三读数合一账)。
|
||||
- **公开方法(3 ≤ 20)**:`settle_if_due()`(=原 `_maybe_settle` 三闸+`_settle` 段序体合体)、`roll_round_actions()`(原函数逐字迁入)、`is_settling()`(diagnostic_snapshot 读投影)。
|
||||
- **行数估算**:约 120 行(头注+成员+四函数)。
|
||||
- **耦合边界**:
|
||||
- `_init(host, fx_host, reward_grant)`——3 参不触发 max-parameters,无需引用束;五段构造五行从宿主 `_init` 逐字搬入。
|
||||
- 段类对宿主的直调形态不变(定稿在册:「段类经宿主引用直调,现状形态」);驱动件经 `oc` 取 facts/协作件/行发射/出口分发,与段类同款。
|
||||
- **VerdictSegment 零改动**:`_exit_distribution` 留宿主(轮间转移=宿主生命周期域:换图编排、notify、轮始发射),判定段仍直调 `oc._exit_distribution()`——不产生段类对驱动件的新引用,不新增 RefCounted 引用环。
|
||||
- 随机只经 `oc.rng` 的 behavior_roll 封闭流(流名、开流时点、取号序逐字);零 await。
|
||||
- **宿主侧变化**:`_on_round_end` 末行改调 `_rounds.settle_if_due()`;`begin_battle` 与 `_exit_distribution` 的 `_roll_round_actions()` 改调 `_rounds.roll_round_actions()`;`_maybe_settle`/`_settle`/`_roll_round_actions` 三函数从宿主删除。
|
||||
|
||||
## 4. 新件二:BattleFacts(战斗事实件)
|
||||
|
||||
- **文件落点**:`game/core/battle_facts.gd`。
|
||||
- **extends**:RefCounted。
|
||||
- **职责语句**:战斗事实的唯一记录面——本战受理事实(encounter:打什么、带什么进来)、同调装配事实(attunement)、轮 facts 缓冲(reveals/seals/path)、封印判定账(去重两集+完美三账)、装板溯源(seq/provenance)、条件事实计数(refresh_used、feat_first_dig_used);自带轮复位与完美账写口。
|
||||
- **单一变化原因**:战斗事实的记录与查询口径——内容批新增触发条件事实/判定账只落此一处。实证:`_feat_first_dig_used`(魔能共鸣)、`_seal_miss_seen`(危险直觉)、`_mines_hits`(触发条件面)、enc 的 feats/tree_rules/voucher 携带键,全部由内容批按同一节奏累加。
|
||||
- **类变量(15 ≤ 15,贴顶)**:`encounter`、`reveals`、`seals`、`path`、`refresh_used`、`board_seq`、`board_from_midround`、`seal_consumed`、`seal_miss_seen`、`perfect_hit_true`、`perfect_hit_false`、`perfect_forgiven`、`feat_first_dig_used`、`attunement`、`attune_safe_seen`。
|
||||
- **公开方法(5 ≤ 20)**:`reset_round()`(原 `_reset_round_facts` 逐字——只清 reveals/seals/path 三项,**不碰 refresh_used**:_battle_over 后快照读到的 refresh_used 必须保持末轮值)、`mark_perfect_hit()`/`mark_perfect_miss()`/`mark_perfect_forgiven()`(契约 2 写口:`_perfect_hit_false` 纯净禁回退改写的执行点从段类纪律升级为账本单点)。其余一律公有成员直读写(段类/快照/宿主经 `oc._facts.X` 改指——fx_host._fx_bonus_delta 跨件直读写同款现状形态)。
|
||||
- **行数估算**:约 80 行。
|
||||
- **耦合边界**:**零注入引用、零信号、零协作对象调用**——纯数据+谓词+写口;缓冲写入点在宿主 A2 处理器(订阅面锁宿主),身份快照捕获(query_full_snapshot)留宿主 `_on_cell_revealed`(fact 件不持 B4 引用,防它变成第二编排面)。
|
||||
- **成员冻结义务**:15/15 贴顶——实现期禁增员,增员即停卡。预留扩容阀:下一张要加事实成员的卡,先把封印判定账五成员二次拆出(SealLedger,−5)再落新账,禁硬挤。
|
||||
|
||||
## 5. attune 族重新裁决(architecture「原位保留」句的废止建议)
|
||||
|
||||
**建议:部分改裁——状态两成员归 BattleFacts,行为函数留宿主。** 理由四条:
|
||||
|
||||
1. **原位裁的前提已消失**:该句是迭代 39/40 两批的防冲突临时裁,原文自认「本波残留债归尾波」;两批均已合回,本波即尾波,且用户已裁「不允许任何豁免」打开重裁通道。
|
||||
2. **状态是事实,行为是编排**:`attunement`=本战装配了什么(enc.attunement 受理携带的快照,受理后只读)、`attune_safe_seen`=本战安全开格积点——两者都是战斗事实,归账本件名正言顺。而参数合计(装配集行扫描)、积点自动兑付(何时 grant_ap=编排决策)、充能重置触发、呈现进度读数——这些是 B1 编排面的读数与触发,与 `_fx_host_fact` 同位的宿主读数形态,留在宿主不违职责语句。
|
||||
3. **外部面零改址**:`attune_has`(断点续玩测试×2+表结构守卫×2)、`attune_param_sum`(main.gd 授予段两处+treasure_effects_test)、`attune_convert_state`(treasure_interact_controller 取值回调)全部留宿主公有面——main.gd 与 treasure_interact_controller 本批零改动。若整体拆成 BattleAttune 新件,这三面约 10 处消费点全要改址(组件出口或转发壳),收益只是把 8 个读数函数换个文件——判据③(阈值动机)嫌疑大于内聚收益。
|
||||
4. **不并进 AttuneLoadout**:那是营地/冒险域的充能与装备集物化单源(迭代 39 已闭合契约);把战斗域读数插进去会重开已闭合边界。BattleFacts 持有的只是快照与计数,充能物化仍全归 AttuneLoadout(`_reseed_attune_charges`/`_hook_attune_consume` 经调用点传 loadout/treasure 委派,宿主侧单点不变)。
|
||||
|
||||
## 6. 已否决的方向(为什么不是别的切法)
|
||||
|
||||
1. **协作者引用束归袋**(任务提示①的直译形态):db/rng/units/statuses/reward_economy 等 11 个协作者句柄若收进一个「引用束」对象,宿主 150+ 处 `db.`/`oc._enemy_system.` 全部换名——零内聚收益的纯改名,命不出领域名字=凑计数袋(拆分判据②红)。引用束先例只用于新件 `_init` 防参(本批两新件参数均 ≤3,未触发)。
|
||||
2. **attune 整体拆件(BattleAttune)**:宿主 14 基数+3 句柄=16 不可达;且如第 5 节理由 3,外部三面 10 处改址换不来职责改善。
|
||||
3. **encounter 留宿主**:宿主 16 超阈。备选砍口只剩两处——nest_preview_count 解冻迁 facts(违背任务给定冻结面)或 _reward_economy 经 RewardGrant 中转(B4 mapping 生命周期与代理面挂到授予件名下=所有权失真)。encounter 归事实件是唯一不破冻结面、不失真的砍口;它也是本方案最弱的一格,见待裁点 1。
|
||||
4. **四件以上碎片化**:每多一件付一个宿主句柄;封印判定账、装板溯源单独成件都撑不起独立变化原因,且把宿主推向 16+。
|
||||
5. **_exit_distribution 迁入驱动件**:判定段须改持驱动件引用(RefCounted 环+段类构造变化),换图编排又是宿主生命周期语义——收益不抵风险,否。
|
||||
|
||||
## 7. 随迁键收敛义务
|
||||
|
||||
**基线实证**:`tools/gdstyle_baseline.txt` 中 battle_orchestrator.gd 现仅两条类级键(max-class-variables=38、max-file-length=1035),**零函数级键**——59 个函数全部在默认阈值内(长度≤50/分支≤8/局部≤10/返回≤6/参数≤5)。函数级指标是函数体内在属性,逐字迁移(仅引用改指)不产生新键。据此:
|
||||
|
||||
- **随迁键清单:预计零条**。义务改为「迁移函数逐字纪律」:`roll_round_actions`(45 行/分支≈8 贴线)、`settle_if_due`、`reset_round`、三个 mark 方法——迁移与改指**禁顺手增分支/局部**;确需增条件即停手核对 gdstyle,超线在卡内拆助手函数收敛(先例=迭代 40 卡①的 12 随迁键收敛)。
|
||||
- 新增小函数全部远在阈值内(最长 `roll_round_actions` 45 行;新件 `_init` 参≤3)。
|
||||
- 两新件与改址后的宿主、段类落地后跑 `python tools/gdstyle_gate.py` 预检一次再进批末闸。
|
||||
|
||||
## 8. 行为零变化风险点与对策
|
||||
|
||||
1. **RNG 取号序**:宿主三封闭流——encounter(`_begin_battle_dice`,留宿主)、gp_drop(`_roll_gp_drop`,留宿主)、behavior_roll(随 `roll_round_actions` 迁 RoundCycle——流名与开流时点逐字,只经 `oc.rng`)。fx_reveal(fx_host 内零触碰)、board_gen/variant_place(BoardInstaller 已定稿随件)。对策=同种子完整局对拍(见第 9 节 PARITY)。
|
||||
2. **信号契约**:五信号(step_row/battle_finished/round_started/board_changed/settlement_snapshot)全留宿主;发射语句零迁移——`round_started.emit` 在 begin_battle/`_exit_distribution` 内原位,仅 round_index 读源不变;A2 三 connect 逐字。发射时序零变化。
|
||||
3. **段类接线**:五段构造参数与持有形态不变(grant/combat 三引用、aura/decay/verdict 单引用);verdict 段零改动(`_exit_distribution` 留宿主)。段内约 25 处 `oc._X` 改指 `oc._facts.X`/`reward_grant.treasure_inventory`——调用点改指、禁转发壳(定稿同款纪律)。
|
||||
4. **_fatal 与 battle_result 唯一写点**:留宿主;BoardInstaller(已定稿 fatal Callable)、RoundCycle/段类(经 oc 直调)零改形。
|
||||
5. **结算时序**:`settle_if_due` 三闸顺序(settling→battle_result→phase)与「终局不回置 _settling、_battle_over 接管」早退语义逐字;判定段内 `_exit_distribution`→回置 `_settling` 的先后不变(出口留宿主保证);`reset_round` 不碰 refresh_used(_battle_over 后快照的 refresh_used 必须保持末轮值——这是本轮盘点抓出的一处险点)。
|
||||
6. **重入语义**:`_on_cell_revealed` 不设 settling 守卫(现状——flush_pending_reveals 的 fx_reveal 事件依赖 reveal_busy 旁路闸而非 settling),处理器体零改形;install 初始展开事件「先缓冲后清除」路径(begin/exit 两处 reset_round)保持。
|
||||
7. **快照逐字**:三快照字段名、嵌套结构、值口径逐字——读数改指投影后值恒等(round_index/attune_safe_seen/perfect 三账/hero_atk 派生读均受理后不变量)。
|
||||
8. **装板薄壳时序**:轴丙定稿五处清零→板序推进→board_changed 发射→叠加层退役的顺序逐字(成员改指 facts 不改序);BoardInstaller 闭合设计的 bundle 键「encounter」传 `_facts.encounter`——同一字典引用,零冲突。
|
||||
|
||||
## 9. 验收载体与判据
|
||||
|
||||
改动—验收对照表(卡内落六列)建议主行:
|
||||
|
||||
| 需求点 | 真实入口 | 载体 | 判据绑定面 |
|
||||
|---|---|---|---|
|
||||
| 行为零变化(本批总判据) | 真实局 begin_battle→挖掘→结算→终局 | **PARITY 同种子完整局对拍**(parity_anchor/parity_compare) | step_row/settlement_snapshot 逐位一致;**实跑须用户批准、禁重锚**(battle_orchestrator.gd 触 PARITY_TOUCH_FACES) |
|
||||
| 段序与重入门 | stop→WAITING→settle_if_due | round_flow_skill_pool_test、settle_segments_test(真实一轮走段序,零改址应绿) | 五段裁定行序、settling 闸、终局早退 |
|
||||
| 开轮摇号迁移 | begin_battle/出口分发→roll_round_actions | round_flow_skill_pool_test(技能池/保底/冷却)+trigger_cond_test(mines_hits 账——3 处读改指 _rounds) | 同种子摇定结果逐位、转存读数 |
|
||||
| 封印判定账迁移 | 封印动作→结算 | seal_polarity_test(4 处 perfect 直写改指)、feat_vouchers_test(8 处+_grant_seg 改指)、meta_progression_forge_test(契约 12 守侧) | 完美三账读数、去重闸、契约 2 计数纯净 |
|
||||
| 装板 shell/溯源 | begin/refresh/exit 装板 | variant_placement_test(零改址应绿)+seal_polarity_test provenance 守卫 | 刷新图不发清图奖励、board_seq |
|
||||
| attune 面零改址 | 装配起战→读数/兑付 | treasure_effects_test、breakpoint_resume_test、table_structure_guard_test(**应零改址全绿**——本批最硬的「外部面零变化」证) | attune_has/param_sum/convert_state/积点兑付 |
|
||||
| 受理事实迁移 | begin_battle(enc) | adventure_feats_test、meta_progression_forge_test(encounter 4 处改指) | enc 携带键贯通 |
|
||||
| 快照逐字 | presentation/diagnostic 出口 | system_test+对拍 | 载荷 schema 与值逐字 |
|
||||
| 库存注入改址 | level_runner 建战注入 | treasure_effects_test 秘宝使用链 | use_treasure 受理面 |
|
||||
|
||||
配套义务:①三件保险恒跑(冒烟/系统测试/静态扫描)+上表关联套件(02 关联档);②静态扫描随批增行——RoundCycle 进 S7 B1 域文件集与 S8 await 文件集(经 oc 调 B2/B3/B4 符号落在该文件),BattleFacts 零协作调用不入两清单;③新文件全类型标注(S9)、头注按 §1.4.1;④本批零数值改动,MC 零跑。
|
||||
|
||||
## 10. gdstyle 键账预期
|
||||
|
||||
| 文件 | 类变量 | 公开方法 | 长度 | 预期键 |
|
||||
|---|---|---|---|---|
|
||||
| battle_orchestrator.gd | **15**(38→15) | 14 | ~830 | **两条基线键全消失**(类变量/文件长双双回落阈值内),零新键 |
|
||||
| settlement/round_cycle.gd | 8 | 3 | ~120 | 零键 |
|
||||
| battle_facts.gd | 15(贴顶) | 5 | ~80 | 零键(15=阈值内合法,fx_host「14≤15」同口径) |
|
||||
| settlement/grant_segment.gd | 3(不变) | — | +~2 行改指 | 零键 |
|
||||
| 其余段类/fx_host/reward_grant | 不变 | 不变 | 不变 | 零键、零 diff |
|
||||
|
||||
基线处理:`--refresh` 人工重生成;全基线 16 条消失 2 条(−12.5%>10% 骤降守卫)→ 须 `--force` 显式确认,属正常还债缩基线。architecture S13 豁免登记第三条随批注销(反哺点,实现批禁写 design/)。
|
||||
|
||||
## 11. 改址盘点(触面清单)
|
||||
|
||||
- **产品码**:battle_orchestrator.gd(主改——成员改指+三函数迁出+hero_atk 派生化+头注指址改写);settlement/round_cycle.gd、battle_facts.gd(新建);grant_segment.gd(~25 处改指);combat_segment.gd(2 处);level_runner.gd(1 行——库存注入改经 `reward_grant()` 出口);aura/decay/verdict、battle_fx_host、reward_grant、damage_controller、main.gd、treasure_interact_controller、board_installer(**零改动**)。
|
||||
- **测试**:feat_vouchers_test(~13)、meta_progression_forge_test(~8)、seal_polarity_test(~8)、trigger_cond_test(3)、round_flow_skill_pool_test(1)、adventure_feats_test(1)、treasure_effects_test(1——`ob14.attunement` 改指);settle_segments_test、roll_multiplier_test、system_test、breakpoint_resume_test、table_structure_guard_test(零改址——attune 面与 round_index 面不动的直接受益者)。
|
||||
- **probes/sim**:零触碰(盘点无命中)。
|
||||
- **闸件数据**:gdstyle_baseline.txt(--refresh --force)。
|
||||
|
||||
## 12. 估时
|
||||
|
||||
**2–3 个工作日**:实现(两新件+宿主改址+段类改址+测试改址)1.5–2 日;验收(关联档回归+PARITY 批跑+对照表与审计配合)0.5–1 日。PARITY 实跑须用户在场批准(不占卡估时);基线 refresh 属批内闸步骤。
|
||||
|
||||
## 13. 待裁点清单
|
||||
|
||||
1. **encounter 归战斗事实件**(本方案最弱一格):受理参数与过程记录同件,变化理由按「战斗事实面扩展」归一(第 4 节实证),但确与事实缓冲不同复位节奏(encounter 随战、facts 随轮)。若否决:宿主 16,只剩两条砍路——nest_preview_count 冻结面解锁(外部读面 3 处改址)或 _reward_economy 经授予件中转(所有权失真),两者都更差,届时按判据④停卡呈报。
|
||||
2. **treasure_inventory 注入面改址**:唯一外部产品码触面(level_runner 一行改经组件出口直注),拆件定稿「外部赋值路径零改址」句随本批失效,需追认。
|
||||
3. **attune 重裁决幅度**:推荐「状态归 facts、行为留宿主」(第 5 节);备选「整体拆 BattleAttune」因宿主 16 不可达已被排除——即本条实际是确认推荐案或否决整个方向。
|
||||
4. **完美账写口升级**:grant_segment 三处直写改经 facts 三方法(契约 2 单点执行)——推荐采纳;若求最小 diff 可退直写(现状纪律同款),卡内裁量。
|
||||
5. **PARITY 对拍批准**:battle_orchestrator.gd 触 PARITY_TOUCH_FACES,实跑对拍须用户点头、不重锚。
|
||||
@@ -1,210 +0,0 @@
|
||||
# 设计——测速循环去 await(S13 `tune_sim_controller` await-in-loop 键真实消除)
|
||||
|
||||
状态行:设计讨论段过程稿 v1.0——待主会话汇总裁决(2026-10-29)。
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
用户 2026-10-29 裁定「不允许任何豁免」:S13 静态质量闸(gdstyle)的裸键 `game/presentation/tune_sim_controller.gd|quality/await-in-loop|'await' used inside a loop` 必须真实消除;architecture「测试与质量域」S13 测量面豁免登记(2026-10-27,理由=「循环内 await 是调参测量的 wall-clock 步进承载语义——重构即测量口径漂移」)随之注销(注销落文走反哺点通道,实现批禁直改 architecture)。
|
||||
|
||||
本设计回答一件事:**把「循环内 await 逐帧让出」换成信号驱动形态后,测量语义是否逐点等价**——每步恰占一帧、每步执行相位不变、终止与读数不变、输出逐字不变。结论先行:**可行,推荐 process_frame 信号连接+步进状态机形态**;等价性四判据三条可严格证明并可用双实现对拍执行化验证,一条(脚本错误中断路径)无法严格证明、列为已声明缺口。
|
||||
|
||||
## 2. 现状全解
|
||||
|
||||
### 2.1 测速循环逐句流程
|
||||
|
||||
现码 `run(n)`(`game/presentation/tune_sim_controller.gd:36-52`):
|
||||
|
||||
| 步 | 语句 | 做什么 |
|
||||
|---|---|---|
|
||||
| 1 | `_running = true` | 控制器运行态(组合根 `_start_debug_levels` 互查守卫的判据) |
|
||||
| 2 | `PlaytestLogger.new()`+`start_session(SEED_BASE)` | 开共享 JSONL 会话(一文件多局,`log_run` 行带种子切分局次) |
|
||||
| 3 | `panel.set_sim_running(true)` | 浮窗运行态(`DebugOverlay.st._sim_running`——模拟钮置灰+探针守卫环判据) |
|
||||
| 4 | `set_sim_progress("模拟中:0/n …")` | 进度串 |
|
||||
| 5 | 建 `stats` 六键束、取 autoplay 驱动 | 测量桶与策略驱动 |
|
||||
| 6 | 循环体:`_run_one_level(...)` | 单局全量模拟(`level_autoplay.run_level` 静态同步函数——自建 RngService、种子=SEED_BASE+i,逐局确定可回放)→ 四桶记账 |
|
||||
| 7 | `set_sim_progress("i+1/n")` | 进度串 |
|
||||
| 8 | `await panel.get_tree().process_frame` | 每局恰让出一帧(命中键的语句) |
|
||||
| 9 | 循环尽:`close_session()`+`set_sim_report(...)` | JSONL 收口+报告注入(文案归 `HudPresenter.tune_sim_report`,零触碰) |
|
||||
|
||||
读数本质:`stats` 六键与报告是 **(种子, atk_pct, hp_pct) 的纯函数**——帧时点不进测量值(`run_level` 不读 wall-clock)。豁免登记所保护的「测量语义」是运行姿态:每局之间恰隔一帧 process_frame 发射(进度可见、窗口不僵死),以及 run 全程的运行态语义。本设计保的就是这个姿态。
|
||||
|
||||
### 2.2 读数消费链
|
||||
|
||||
- 报告文案:`tune_sim_report(stats)` → 浮窗 RichTextLabel(`set_sim_report`);探针 ⑤ 断言「关卡完成率/关卡完成剩余 HP 均/败北节点/N=10」四串。
|
||||
- JSONL:`user://logs/playtest_*.jsonl`,由未触碰的 `level_autoplay` 逐行写;`close_session` 时点随收尾帧。
|
||||
- 运行态:`panel.set_sim_running` → 浮窗模拟钮置灰;`_running` → 组合根两层调试入口守卫。
|
||||
|
||||
### 2.3 断言面盘点与一处静态矛盾(潜伏红——本设计的关键发现)
|
||||
|
||||
两个在库断言面钉死了 run 生命周期的语义:
|
||||
|
||||
1. **单元套件 `standee_fx_sweep_test.gd`〔wd8〕**(`game/tests/unit/presentation/standee_fx_sweep_test.gd:126-134`):假驱动在**每一局** `run_level` 回调内读 `ctrl.is_running()`,断言 `drv.seen == [true, true]`(两局读数都真);收尾断言 `is_running()` 假+`panel.running` 假+报告非空;且用 `await ctrl.run(2)` 驱动——**run 必须保持可等待(协程),await 它须挂起到整批完成**。
|
||||
2. **探针 `ui_tune_probe.gd` ⑤**(`game/probe/ui_tune_probe.gd:67-83`):按下模拟钮后以 `while debug_overlay.is_running()` 守卫环逐帧等——**语义=浮窗运行态贯穿整批**,环退出后断言输出含报告四串。
|
||||
|
||||
静态推演现码:`_run_one_level` 尾部两行(`panel.set_sim_running(false)`/`_running = false`,:67-68)**每局执行一次**——首局完成即把两个运行态置假。后果:
|
||||
|
||||
- wd8 首断言实测必得 `[true, false]` → 红;
|
||||
- 探针 ⑤ 守卫环在按下返回后立即退出(首局在按下同一同步段内已跑完)→ 输出停在进度串 → 四条输出断言全红。
|
||||
|
||||
推断:这两行原本在循环**之后**(run 收尾单次执行),是「循环体提函数」(run() 局部变量 11→10 清偿批,2026-10-26 审计在案该键)搬运时被卷入提取体——wd8 写于 d8 批且当时必绿,可反证。两断言面均不在近期批次的关联档选测覆盖内(套件名与文件名无字面关联、probe_gate --full 非恒跑三保险),潜伏红未暴露。**T0 义务:实跑 standee_fx_sweep 单套件+probe_gate --full 复核现状**(本设计零测试执行,此判断待实跑确认)。
|
||||
|
||||
推论:本批若逐字保留现行为,wd8 与探针 ⑤ 必红、批不可绿。**本设计按「run 收尾单次置 false」的还原语义设计**(两断言面共同钉住的语义),该还原作为已申报行为改动进卡(待裁点 1)。
|
||||
|
||||
## 3. 方案形态评估
|
||||
|
||||
判定轴:帧相位(步进体在帧循环中的执行时点是否与 await 恢复点相同)、步进节律(相邻两步之间是否恰隔一次 process_frame 发射)、run 可等待性(wd8 契约)、键风险(S13 新键)。
|
||||
|
||||
Godot 4 帧循环 process 段的迭代序(engine-reference 口径):**① `emit process_frame`**(所有连接的 Callable 同步依次调用;`await process_frame` 的恢复点=此刻挂在信号上的临时连接被调用)→ **② 节点 `_process`**(Timer 节点在此段)→ **③ 帧末**(SceneTreeTimer 超时、延迟删除等)。官方文档:process_frame「Emitted immediately before Node._process is called on every node」。await 恢复点与显式 connect 回调**同处①、同一相位**——这是全部等价性论证的支点。
|
||||
|
||||
| 形态 | 帧相位 | 步进节律 | run 可等待 | 键风险 | 裁决 |
|
||||
|---|---|---|---|---|---|
|
||||
| **process_frame 信号连接+步进状态机** | 与 await 恢复点同相位(同一 emit 内) | 恒等(常驻连接,每发射恰走一步) | 保留(函数级单次 await 完成信号,见 §4) | 零新键 | **采纳** |
|
||||
| SceneTreeTimer 链 | timeout 在③帧末——相位不同 | `create_timer(0)` 同帧即燃→节律塌缩;加时长→漂移 | 须循环内 await→键不消 | await-in-loop 残留+每步分配 | 否 |
|
||||
| Timer 节点 | timeout 在②节点 process 段——相位不同 | wait_time 按秒计,一帧节律不精确 | 须 await timeout 链→键不消 | 键残留+须建 Node 入树(RefCounted 控制器破形、生命周期管理新增) | 否 |
|
||||
| 递归协程代循环 | 同相位(恢复点内即调下一步) | 恒等 | 天然(await 协程链) | 零键 | 备选否决——n 个并发函数状态链、错误中断语义更浑、可读性差 |
|
||||
| 线程 / WorkerThreadPool | 脱离主循环 | — | — | 测量确定性破坏+面板 setter 跨线程 | 否(一句话排除) |
|
||||
|
||||
godot-master 惯用法对齐:异步操作移出循环、改由信号触发的独立方法承载(其 NEVER-list 第 7 条同款);动态连接用毕即断(第 27 条);逻辑件保持 RefCounted 不引入 Node(When-NOT-to-use-Node);连接前 `is_connected` 守卫(迭代 39「恰好连接一次」先例)。
|
||||
|
||||
## 4. 推荐案:process_frame 信号步进状态机
|
||||
|
||||
### 4.1 代码结构草图(伪代码级)
|
||||
|
||||
```gdscript
|
||||
signal _batch_finished ## 批量模拟整批收尾完成(无参数;发射时点=报告注入与运行态复位之后;
|
||||
## 消费方=run() 自身收尾放行——外部 `await 控制器.run(n)` 经此放行)
|
||||
|
||||
# run 期活成员(批末失效,下次 run 重写——非无效成员)
|
||||
var _sim_n := 0
|
||||
var _sim_i := 0
|
||||
var _sim_stats := {}
|
||||
var _sim_autoplay = null
|
||||
var _sim_logger = null
|
||||
var _finished := false
|
||||
|
||||
func run(n: int) -> void:
|
||||
_running = true
|
||||
# …logger 建会话/set_sim_running(true)/进度 0/n/stats 六键束/_autoplay()——逐字保持现码…
|
||||
_sim_n = n; _sim_i = 0; _sim_stats = …; _sim_autoplay = …; _sim_logger = logger
|
||||
_finished = false
|
||||
if n > 0:
|
||||
var tree: SceneTree = panel.get_tree()
|
||||
if not tree.process_frame.is_connected(_step_frame):
|
||||
tree.process_frame.connect(_step_frame) # 恰连接一次守卫(迭代 39 先例)
|
||||
_step_frame() # 首步同步执行——与 await 形态「第 0 局在调用栈内跑完」对齐
|
||||
await _batch_finished # 函数级单次 await——不在任何循环体内(键消除的落点)
|
||||
else:
|
||||
_finish_batch() # n=0:与 await 形态一致——循环零进,同步收尾零帧
|
||||
|
||||
# 每帧恰执行一步(process_frame 发射点回调);步尽次帧收尾
|
||||
func _step_frame() -> void:
|
||||
if _sim_i < _sim_n:
|
||||
_run_one_level(_sim_autoplay, _sim_stats, _sim_i, panel, _sim_logger) # 逐字保持
|
||||
panel.set_sim_progress("模拟中:%d/%d …" % [_sim_i + 1, _sim_n]) # 逐字保持
|
||||
_sim_i += 1
|
||||
else:
|
||||
panel.get_tree().process_frame.disconnect(_step_frame) # 先断连(防再入)
|
||||
_finish_batch()
|
||||
_batch_finished.emit() # 放行 run() 的 await 与外部 await run(n) 的调用方
|
||||
|
||||
# 收尾单点(运行态复位还原为「run 收尾单次执行」——待裁点 1 的申报改动落点)
|
||||
func _finish_batch() -> void:
|
||||
_finished = true
|
||||
_sim_logger.close_session()
|
||||
panel.set_sim_running(false)
|
||||
_running = false
|
||||
panel.set_sim_report(HudPresenter.tune_sim_report(_sim_n, panel.atk_pct(), panel.hp_pct(), _sim_stats, _base_hp))
|
||||
```
|
||||
|
||||
要点:
|
||||
|
||||
- **await 只剩一处、在函数级**(`await _batch_finished`),文件内不再有任何 for/while——await-in-loop 键从文本形态上根除,且该文件此后对键**结构性免疫**(无循环即无循环内 await)。
|
||||
- **run 保持协程身份**:含 await 即仍是协程——`_on_tune_simulate` 不 await 调用(返回函数态、丢弃,与现行为逐字一致);wd8 的 `await ctrl.run(2)` 挂起到 `_batch_finished` 发射、恢复时整批已完成——**契约零变化、wd8 断言零改动**。
|
||||
- `_run_one_level` 除删去尾部两行(回归还原,见 §2.3)外逐字保持(含 5 参签名,参数≤5 临界不恶化)。
|
||||
- 头注按 code-conventions §2.1 增 `_batch_finished` 契约一行(现 4 行→5 行,S10 ≤8 行内)。
|
||||
- 收尾段内四语句的相对次序(close/两运行态复位/报告)对两个断言面均不可观测(wd8 在整批完成后检查、探针在帧边界检查)——按草图次序落码即可,实现期查 git 历史原序可进一步对齐。
|
||||
|
||||
### 4.2 帧相位等价性论证(逐步对齐表)
|
||||
|
||||
以 n=3 为例,旧(await)新(状态机)两形态逐帧对齐:
|
||||
|
||||
| 时点 | 旧形态 | 新形态 | 等价 |
|
||||
|---|---|---|---|
|
||||
| 调用点同步段(按钮信号链内) | setup→第 0 局→进度 1/n→await 挂起 | setup→connect→`_step_frame()` 跑第 0 局→进度 1/n→`await _batch_finished` 挂起 | 同一调用栈、同一同步段、语句同序 |
|
||||
| 第 1 帧 ①(emit process_frame) | 恢复→第 1 局→进度 2/n→再 await | `_step_frame` 回调→第 1 局→进度 2/n | **同一 emit、同一相位**(帧首、节点 _process 之前) |
|
||||
| 第 k 帧(1≤k≤n−1) | 第 k 局 | 第 k 局 | 步进体=同一函数 `_run_one_level`+同一进度语句 |
|
||||
| 第 n 帧 ① | 恢复(循环自然尽)→close→报告→返回 | `_step_frame` else 分支→断连→close→复位→报告→emit→run 返回 | 终止语句同帧同相位,恰多等的一帧来自旧形态末次 await——草图 else 分支精确复刻 |
|
||||
| n=0 | 循环零进,同步收尾,不挂起 | else 直调 `_finish_batch`,同步收尾,不挂起 | 一致(含 run 返回形态:均非挂起返回) |
|
||||
|
||||
连接次序论证(与同信号其他订阅者的相对序):产品码内 process_frame 订阅面仅两处——本件与 `settlement_fx_view.gd:94` 的一次性 await(等文本度量,战斗结算呈现期,与模拟批不并存;T0 实查复核)。探针 ⑤ 守卫环的 await 连接时点恒晚于本件(按下返回后才首轮 await)→ 每帧步进先于探针复查,两种形态一致。旧形态每次恢复后重新挂尾连接、新形态常驻连接——对「连接时点早于 run()」的订阅者,两形态中本件都排其后;差异仅在「run 途中新增订阅者」的假想场景,现库为零(已列风险 3)。
|
||||
|
||||
## 5. 等价性证明清单(四判据)
|
||||
|
||||
| 判据 | 结论 | 依据 |
|
||||
|---|---|---|
|
||||
| ① 步数与帧数一一对应不变 | **严格成立** | §4.2 对齐表:第 i 局恒在(调用点 i=0/第 i 帧发射点 i≥1),收尾恒在第 n 帧发射点,n=0 退化路径一致 |
|
||||
| ② 每步工作量与执行时点不变(同相位) | **严格成立** | 步进体逐字同一函数;执行点同为 emit process_frame(①段,帧首)——await 恢复点与信号回调在引擎内同处一列连接、同一 emit 内被同步调用 |
|
||||
| ③ 终止条件与终止时读数不变 | **严格成立** | 终止=i 走满 n(else 分支↔循环自然尽);终止时语句(close/复位/报告)同帧执行 |
|
||||
| ④ 输出逐字不变 | **成立+执行化验证** | 报告=未触碰的 `tune_sim_report(stats)`;stats 为种子纯函数(帧时点不进值);JSONL 由未触碰的 autoplay 写、close 时点同帧——逐位一致由双实现对拍执行证明(见下) |
|
||||
|
||||
执行化验证=**双实现对拍**(test-conventions §5.3「重放:改前改后配对」词汇,非变异类):新增配对套件——`game/tests/` 面置**遗留形态夹具**(现 run() 的 await 形态逐字副本,尾部两行按还原语义置收尾;tests/ 不在 S13/S8 扫描面,夹具内循环 await 合法在册);同一假面板+确定性假驱动分别驱动两形态,断言五行全等:每局调用时记录的**帧索引序列**(直接证明「每步恰一帧、相位同点」——把 §4.2 的论证变成当轮真实执行证据)、驱动读到的运行态序列、进度串序列、stats 六键逐位、报告全文逐字。
|
||||
|
||||
**已声明缺口(不能严格证明的点)**:
|
||||
|
||||
1. **脚本错误中断路径**:GDScript 无错误陷阱 API。旧形态:步进体内脚本错误→协程死亡→静默停摆(运行态永真、报告永不落)。新形态:错误中断 `_step_frame`→计数未推进→次帧重试同一步(确定性错误→逐帧重试,探针 1800 帧守卫可抓;生产态=持续重试的可见坏,与旧「静默卡死」同级不同形)。此差异不可消除,接受并文档化(待裁点 3);测量批遇错本就整批作废,两形态都不产出可用读数。
|
||||
2. **微观连接序对未来订阅者**:若未来有人在 run 途中向 process_frame 新增连接,常驻连接与挂尾连接的相对序会分叉——现库零此场景,登记为实现期 T0 实查项+代码评审注记。
|
||||
|
||||
## 6. gdstyle 键账预期(逐规则核对)
|
||||
|
||||
| 规则 | 预期 | 依据 |
|
||||
|---|---|---|
|
||||
| quality/await-in-loop(裸键,本案标的) | **消除** | 全文件零 for/while,await 仅函数级一处 |
|
||||
| quality/allocation-in-loop | 不命中 | 文件零循环;`PlaytestLogger.new()` 在 run 顶层(现状即如此,非循环内) |
|
||||
| max-function-length ≤50 | 达标 | run 约 22 行、`_step_frame` 约 12 行、`_run_one_level` 删两行后约 10 行 |
|
||||
| max-branches ≤8 | 达标 | `_step_frame` 一个 if/else;run 一个 if/else |
|
||||
| max-local-variables ≤10 | 达标 | run 局部 3(logger/stats/autoplay——余者转成员);`_step_frame` 局部 1 |
|
||||
| max-returns ≤6 | 达标 | 全 void |
|
||||
| max-parameters ≤5 | 达标(临界持平) | `_run_one_level` 5 参逐字保持;新函数 0 参 |
|
||||
| max-class-variables ≤15 | 达标 | 现 5+新增 6 成员=11(`_batch_finished` 信号若计入则 12)——成员皆 run 期活承载,非凑数袋 |
|
||||
|
||||
键账流程:键消失后闸判定即绿(消失键不参与红判定);基线死键由批末用户人工 `--refresh` 自然清去(16→15,降幅 <10%,不需 `--force`)。
|
||||
|
||||
## 7. 行为零变化风险点
|
||||
|
||||
1. **测量读数分布**:stats/JSONL/报告是 (种子, atk, hp) 纯函数、帧时点不进值——结构上零漂移;执行证据=双实现对拍逐位+探针 ⑤ 输出四串断言。
|
||||
2. **探针断言面**:⑤ 守卫环语义依赖浮窗运行态贯穿整批——本设计还原该语义(§2.3)→ 探针由「静态推演红」转绿;探针其余段(①–④、⑥–⑩)零触碰。
|
||||
3. **发布态零影响**:浮窗角标 `_debug_entry` 门控(`main.gd:200`,发布态恒隐、浮窗无 UI 开启口——系统测试与冒烟既有断言面在役);tune_sim 全链路发布态不可达,本改动不触任何发布路径。
|
||||
4. **生命周期**:控制器由 `main._tune_sim` 应用期持有(RefCounted 不因帧回调悬挂);`is_connected` 守卫防信号绕过 disabled 的二次 run 造成双连接双步进;收尾先断连防再入;`_batch_finished` 发射时 run 自身的 await 连接恒在位(不存在零听众发射——n=0 路径不经 emit)。
|
||||
5. **并发暴露面**:`_on_tune_simulate` 无 is_running 早退(现状即无,本设计不新增——守卫=按钮置灰〔还原后贯穿整批〕+两层调试入口 is_running 互查);与还原前相比,运行态中途置假的再入洞被顺手封死(还原语义的附带收益,申报面见待裁点 1)。
|
||||
|
||||
## 8. 验收载体
|
||||
|
||||
| # | 载体 | 判什么 | 入闸 |
|
||||
|---|---|---|---|
|
||||
| 1 | T0 实跑复核:standee_fx_sweep 单套件+probe_gate --full | 确认 §2.3 潜伏红现状(改动前读数) | 开工首步 |
|
||||
| 2 | wd8 三断言〔wd8〕(既有,零改动) | 每局运行态真/收尾运行态假+报告注入/run 可等待——**卡内须显式申报该套件**(套件名与涉案文件无字面关联,diff 推导可能漏选) | run_all 关联档 |
|
||||
| 3 | 双实现对拍配对套件(新增,§5) | 帧索引序列/运行态序列/进度串/stats 逐位/报告逐字——五面对拍 | run_all 关联档 |
|
||||
| 4 | ui_tune_probe ⑤(既有,零改动) | 真实 UI 全链路 N=10:守卫环完成+报告四串+运行期钮禁用 | probe_gate --full |
|
||||
| 5 | 批末 `run_all_gates.sh --code` | 所选域全绿;static_scan S13 对账确认 await 键消失、无新键 | 批末 |
|
||||
|
||||
## 9. 估时
|
||||
|
||||
| 项 | 估时 |
|
||||
|---|---|
|
||||
| T0 现状复核(两断言面实跑) | 0.25 工作日 |
|
||||
| 控制器重构(§4.1 草图落码+头注契约行) | 0.25–0.5 工作日 |
|
||||
| 双实现对拍(夹具+配对套件) | 0.25–0.5 工作日 |
|
||||
| 孤立验证+批末代码域闸+键账对账 | 0.25 工作日 |
|
||||
| **合计** | **1–1.5 工作日** |
|
||||
|
||||
## 10. 待裁点清单
|
||||
|
||||
1. **潜伏红处置(必裁)**:现码 `_run_one_level` 尾部两行与 wd8/探针 ⑤ 静态矛盾(§2.3)。推荐:随批还原「run 收尾单次置 false」,作为已申报行为改动进卡(T0 实跑确认现状后施工);该还原同时封死运行中途的模拟再入洞。若用户掌握「每局置 false 系有意行为」的背景,请指出——但该选择下 wd8 与探针 ⑤ 必红、批不可绿,需另行裁决断言面处置。
|
||||
2. **双实现对拍是否入批**:推荐入(把帧相位等价从纸面论证变成当轮执行证据;tests/ 面不入 S13 扫描面、夹具内循环 await 合法)。备选:仅靠 wd8+探针 ⑤(省一测试件,相位等价无执行化证据)。
|
||||
3. **错误路径差异接受度**:脚本错误下「逐帧重试」对「静默停摆」的差异(§5 缺口 1)不可消除。推荐:接受并文档化。备选:`_on_tune_simulate` 加 is_running 早退守卫兜底——+1 行为面、system_test〔wd7〕前置断言随之需复核,代价大于收益。
|
||||
|
||||
## 11. 关联文档同步面(随批义务备查,经反哺点通道落文)
|
||||
|
||||
- `design/engineering/architecture/architecture.md`「测试与质量域」:S13 测量面豁免登记首条(2026-10-27 tune_sim await)**注销**;同段其余条目(battle_orchestrator 第三条等)不在本案范围。
|
||||
- `tools/gdstyle_baseline.txt`:await 裸键随批末人工 `--refresh` 消失(禁实现批中途 refresh)。
|
||||
- `game/tests/README.md` 能力清单:配对套件入表归写卡段(实现批禁写该文件)。
|
||||
@@ -1,171 +0,0 @@
|
||||
# 设计——站桩状态件拆分(S13 max-class-variables 键清偿)
|
||||
|
||||
设计讨论段过程稿 v1.0——待主会话汇总裁决。
|
||||
|
||||
## 0. 一句话结论
|
||||
|
||||
把 `_StandeeState` 沿「身份命值 / 资产演出」职责缝拆成两个独立文件类(12 + 11 成员),三个演出探针计数器移到宿主;宿主类变量 19 → 10,两新文件各自 ≤15,站桩外部契约与呈现时序零变化。
|
||||
|
||||
**先纠一个前提**:主会话实测的「_StandeeState 成员 13 个、独立成文件即 13≤15 合规」不成立。实测(gdstyle v0.4.0 二进制逐案验证):该文件 `_StandeeState` 真实成员是 **25 个**;基线键账 19 是 gdstyle 一个解析缺陷造出的截断读数——内嵌类里**带行尾注释的属性声明**(`var _intent_scale := 1.0: # 注释`)会把该内嵌类的成员计数截断,其后的成员全部漏记进宿主。把 `_StandeeState` 原样拆成独立文件,键账是 25 不是 13,照样红。
|
||||
|
||||
## 1. 机检事实(gdstyle v0.4.0 计数语义,实测五案)
|
||||
|
||||
| 案 | 内容 | gdstyle 读数 | 结论 |
|
||||
|---|---|---|---|
|
||||
| 1 | standee_body.gd 原文件 | 外层类 19(1:1),内嵌类零命中 | 19 = 顶层 6 + 漏记内嵌 13 |
|
||||
| 2 | 内嵌 25 成员抽成独立文件 | 该类 25 | **拆出即 25 > 15,方案①不成立** |
|
||||
| 3 | 内嵌类全普通 var(无属性) | 内嵌类单独报 25,宿主 6 不报 | 无属性时内嵌类独立计数,正常 |
|
||||
| 4 | 内嵌类 12 普通 var + 带行尾注释属性 + 12 普通 var + 宿主 6 | 宿主 18(6+12 漏记) | 属性行尾注释 = 截断点 |
|
||||
| 5 | board_cell_unit.gd(旁证) | 基线 30 = 顶层 6 + 漏记 24 | 同一规则,账目吻合 |
|
||||
|
||||
有效规则:**类各自计数;内嵌类遇到「属性声明 + 行尾注释」即成员计到该属性为止,其后成员漏进宿主**。standee_body.gd 的截断点 = `_intent_scale`(37 行),其后 13 个成员(`_glyph_rot` 起到 `_flash_count`)漏进宿主:6 + 13 = 19。board_cell_unit.gd 截断点 = `edge`(30 行),6 + 24 = 30,同款吻合。
|
||||
|
||||
含义:不动内嵌形态,把三行属性声明移到内嵌类末尾(或删其行尾注释)就能让账变回「宿主 6 / 内嵌 25」——但内嵌 25 仍超阈。**真正的债是状态件 25 个成员本身**,任何合规解都必须把它拆成 ≥2 个类或砍到 ≤15。
|
||||
|
||||
## 2. 现状成员全列(31 个:宿主 6 + 状态件 25)
|
||||
|
||||
### 2.1 宿主顶层(6 个——全部有外部冻结契约)
|
||||
|
||||
| 成员 | 类型 | 写入方 | 读取方 |
|
||||
|---|---|---|---|
|
||||
| `st` | _StandeeState | 成员初始化器;`_init` 灌 _owner/_hero_state/_kind | 宿主全部内部函数经 `st.X` 读写;**外部零直访**(全仓 grep 证实) |
|
||||
| `box` | Vector2(150,176) | battle_stage_view `_sync_layout`(198/208 行);fx_probe 三处 | `_place_portrait`/`_portrait_rect`/`_pedestal_rect`/`content_rect`/`_draw_*` 五域;battle_stage_view 两个 center 出口读 |
|
||||
| `font` | Font | battle_stage_view `set_world_font`(232/235 行) | `_efont` |
|
||||
| `slot_row` | StatusSlotRow | battle_stage_view(140/265 行) | `set_effects`/`set_effects_cleared_feedback`/`mark_dead`/`_revive`;battle_stage_view `_sync_companions`;ui_probe/ui_click_probe |
|
||||
| `_intent_charge` | bool | `set_pending`(源码锚行 194)、`mark_dead` | `_play_intent_motion`;standee_fx_sweep_test 直读(103 行) |
|
||||
| `has_world_hp_bar` | true 常量 | 无(声明即终值) | ui_probe 141 行 |
|
||||
|
||||
### 2.2 _StandeeState(25 个)
|
||||
|
||||
| # | 成员 | 类型 | 写入方 | 读取方 |
|
||||
|---|---|---|---|---|
|
||||
| 1 | `_owner` | Node2D | `_init` | 三个属性 setter(queue_redraw) |
|
||||
| 2 | `_kind` | String | `_init` | `set_hero_state`/`_revive`/`_portrait_glyph`/`_draw`/`_draw_hp_bar`/`_portrait_color` |
|
||||
| 3 | `_portrait_sprite` | Sprite2D | `set_portrait_texture`/`_place_portrait` | 同函数 + `_draw_portrait`/`set_hero_state`/`_settle_hero_idle`/`portrait_probe` |
|
||||
| 4 | `_portrait_tex` | Texture2D | `set_portrait_texture` | 仅 `_place_portrait` 判空(与 sprite.texture 冗余) |
|
||||
| 5 | `_hero_tex` | Dictionary | `register_hero_state` | `set_hero_state`/`_settle_hero_idle`/`hero_state_probe` |
|
||||
| 6 | `_hero_state` | int | `_init`/`set_hero_state`/`_settle_hero_idle`/`_revive` | `set_hero_state`/`hero_state_probe` |
|
||||
| 7 | `_state_revert_tw` | Tween | `set_hero_state` | 同函数(重启先杀) |
|
||||
| 8 | `_order` | int | `_set_order` | `_draw_hp_bar`(顺位徽标) |
|
||||
| 9 | `_intent_glyph` | String | `set_pending` | `intent_probe`/`_draw_intent_badge` |
|
||||
| 10 | `_intent_col` | Color | `set_pending` | `_draw_intent_badge` |
|
||||
| 11 | `_intent_visible` | bool | `set_pending`×3/`mark_dead` | `intent_probe`/`_draw_intent_badge` |
|
||||
| 12 | `_intent_scale` | float(属性→重绘) | `_play_intent_motion` 的 tween | `_draw_intent_badge` |
|
||||
| 13 | `_glyph_rot` | float(属性→重绘) | `_play_intent_motion` 的 tween | `_draw_portrait` |
|
||||
| 14 | `_display_name` | String | `set_data` | `display_name`/`name_line_probe`/`_draw_armor_name_line` |
|
||||
| 15 | `_enemy_id` | String | `set_data` | `enemy_id`(d12 解析主键) |
|
||||
| 16 | `_armor` | String | `set_data` | `name_line_probe`/`_draw_armor_name_line` |
|
||||
| 17 | `_dead` | bool | `mark_dead`/`_revive` | `set_data`/`set_hero`/`is_dead`/`flash_hit`/`_portrait_glyph`/`set_pending`/`mark_dead` |
|
||||
| 18 | `_hp_max` | float | `set_data`/`set_hero` | `_set_hp`/`_draw_hp_bar` |
|
||||
| 19 | `_hp_cur` | int | `_set_hp` | `_draw_hp_bar`(数字即时值) |
|
||||
| 20 | `hp_value` | float(属性→重绘+clamp) | `_set_hp` 的 tween | `_draw_hp_bar`(条宽) |
|
||||
| 21 | `_hp_tween` | Tween | `_set_hp` | 同函数(重启先杀) |
|
||||
| 22 | `_hp_flash_tw` | Tween | `flash_hit` | 同函数(重启先杀;回色读 `_dead`) |
|
||||
| 23 | `_death_shards` | int | `_spawn_death_shards` | `fx_probe` |
|
||||
| 24 | `_hit_sparks` | int | `_spawn_hit_spark` | `fx_probe` |
|
||||
| 25 | `_flash_count` | int | `flash_hit` | `fx_probe` |
|
||||
|
||||
### 2.3 外部触面(拆分边界 = 全部保持)
|
||||
|
||||
写状态的外部方只有 battle_stage_view(box/font/slot_row 三 var + 全部经方法)与 fx_probe(box 三处);读面 = 两个 center 出口、六个 probe 出口、`_intent_charge` 测试直读、theme_projection_test 三条源码锚断言(679–683 行:`GOLD_BRIGHT` 顺位墨、`HERO_BLUE_BRIGHT`/`GOLD_BRIGHT` 护甲墨、`_intent_charge = pid in CHARGE_SKILL_IDS`)——三条锚所在函数(`_draw_hp_bar`/`_draw_armor_name_line`/`set_pending`)**全部留在宿主且锚行逐字不动**。
|
||||
|
||||
## 3. 方案形态评估
|
||||
|
||||
### 方案 A(主会话原①):_StandeeState 升格独立文件
|
||||
|
||||
**淘汰。** 实测拆出即 25 > 15(机检事实案 2),不削成员不合规;而削到 15 需砍 10 个,全是承重成员(见方案 B 的砍不动论证),等于把 A 逼成 B+拆分。
|
||||
|
||||
### 方案 B(主会话原②):原地真实削减 4 个(19→15)
|
||||
|
||||
**淘汰。** 被计入 19 的是宿主 6(全部外部冻结:box/font/slot_row/has_world_hp_bar 探针契约面、_intent_charge 源码锚成员、st 本体)+ 漏记的 13(`_glyph_rot`/身份三元组/`_armor`/`_dead`/`_hp_max`/`_hp_cur`/`hp_value`/两条 tween 槽/三个探针计数)。逐个过堂:身份三元组合一个字典 = 丢类型的凑计数袋(违反 code-conventions §1.1①⑤);三个探针计数合一个字典同理且键变字符串;`_hp_cur` 与 `hp_value` 一个是即时目标一个是 tween 滞后值,不可互推;两条 tween 槽的重启语义各自独立;`_glyph_rot` 是 tween 目标属性。**诚实削减余额 ≈ 0(顶多 `_portrait_tex` 一个冗余成员)**,−4 凑不出来。
|
||||
|
||||
### 方案 C(推荐):沿职责缝拆两个独立文件类 + 三个演出探针计数器移宿主
|
||||
|
||||
25 个成员按领域分三堆,各自命得出名字:
|
||||
|
||||
**新件一 `game/presentation/views/standee_vitals.gd`「站桩身份与命值态」(12 成员)**
|
||||
- 成员:`_owner`、`_kind`、`_display_name`、`_enemy_id`、`_armor`、`_order`、`_dead`、`_hp_max`、`_hp_cur`、`hp_value`(属性→重绘+clamp)、`_hp_tween`、`_hp_flash_tw`。
|
||||
- 职责语句:站桩是谁、活没活、血量几何的唯一账面——身份五元组(种类/名/id/护甲/顺位)+ 存活位 + 血量账与两条血量系 tween 槽。
|
||||
- 单一变化原因:战斗结算快照投影的字段形态(set_data/set_hero 投影什么它记什么)。
|
||||
- 迁入行为(防纯数据袋):`apply_hp(hp)`=原 `_set_hp` 整体搬移(clamp、重启 `_hp_tween`、tween 写 `hp_value`);`hp_value` 属性 setter 逐字。`_hp_flash_tw` 归此件:`flash_hit` 的回色分支读 `_dead`,与存活位同域。
|
||||
- extends **RefCounted**(godot-master 判据:瞬态逻辑数据包、随宿主生灭、零序列化零 Inspector——Resource 的共享/.tres 语义此处零收益)。
|
||||
|
||||
**新件二 `game/presentation/views/standee_motion.gd`「站桩资产与演出态」(11 成员)**
|
||||
- 成员:`_owner`、`_portrait_sprite`、`_portrait_tex`、`_hero_tex`、`_hero_state`、`_state_revert_tw`、`_intent_glyph`、`_intent_col`、`_intent_visible`、`_intent_scale`(属性→重绘)、`_glyph_rot`(属性→重绘)。
|
||||
- 职责语句:站桩的资产挂点与一次性演出——立绘精灵落位与换装、主角三态注册与 0.35s 短驻回归、意图徽标弹入动画。
|
||||
- 单一变化原因:美术素材落位规则与演出编排设计(立绘 48px 档、三态帧档、§4.6.4 三档运动签名)。
|
||||
- 迁入行为:`set_portrait_texture(tex, flip, box)`(原函数整体搬移,box 由宿主传入——box 是宿主冻结 var);`register_hero_state`;`apply_hero_state(state, is_hero)`(原 `set_hero_state`,唯一改形 = `st._kind != "hero"` 早退改参判 `is_hero`——早退序逐字);`reset_state()`(原 `_revive` 内「`_hero_state = RESET` 强制绕同态早退」两拍的 encapsulation);`play_intent_motion(charge)`(原 `_play_intent_motion`,`_intent_charge` 改参传入);`state_probe()`。
|
||||
|
||||
**宿主 standee_body.gd 保留(类变量 10)**
|
||||
- 五个冻结 var 原位 + `st`(vitals 实例,**名字保留**——约 40 处引用与 tween 路径串 `"st.hp_value"` 零改)+ `mo`(motion 实例,命名待裁)+ 三个演出探针计数器 `_death_shards`/`_hit_sparks`/`_flash_count`。
|
||||
- 计数器归宿主的内聚依据:唯一写入方 = 宿主演出函数(`_spawn_death_shards`/`_spawn_hit_spark`/`flash_hit`),唯一读取方 = 宿主 `fx_probe()` 出口——仪器跟着驱动它的函数走;同时给 vitals 让出余量(15 满额 → 12)。
|
||||
- 保留函数:`_init`、`set_data`/`set_hero`(跨两域编排)、`set_effects`/`set_effects_cleared_feedback`(slot_row 域)、`set_pending`(分档计算 + 源码锚行,字段写改指 mo)、`mark_dead`/`flash_hit`/`play_hit_impact`/`_spawn_*`/`_revive`(跨域演出编排)、`_draw` 全族与几何函数(绘制是宿主 CanvasItem 职责)、六个 probe/display_name/enemy_id/is_dead 出口(外形零变,体内前缀改指)。
|
||||
|
||||
接线形态:**保持 `_owner: Node2D` 直回引,不改 Callable 注入、不改信号**。依据:①现状形态,setter 体逐字(`_owner.queue_redraw()`)即重绘时序零漂移——tween 每帧写属性 → setter 同步触发,正是「弹入动画逐帧重绘」的承载;②Node 非 RefCounted,state→宿主回引无环引用泄漏(与 BattleFxHost 场景不同——那边是两 RefCounted 互持才禁双向);③queue_redraw 是 CanvasItem 公开 API,不属「件回调宿主私有族」禁令射程。
|
||||
|
||||
淘汰的变形:**两内类同居主文件**(diff 更小)——依赖成员排序躲解析缺陷(属性须排各类末尾),未来任何人往类中部加一个带注释属性就静默漏账(基线恶化闸要到 19→29 才红,9→15 区间六格漂移无感知);两新件独立文件则完全脱离该缺陷的作用面。**改属性行注释形态躲缺陷**同理淘汰——赌解析器怪癖不如离开怪癖作用面。
|
||||
|
||||
## 4. 写入路径对账(外部写入方零改动清单)
|
||||
|
||||
| 外部触点 | 现状 | 改后 |
|
||||
|---|---|---|
|
||||
| battle_stage_view 140/265 行 `slot_row =` | 宿主 var 直写 | 不变(var 原位) |
|
||||
| battle_stage_view 198/208 行 `box =` | 宿主 var 直写 | 不变;box 仍是无 setter 普通 var,**不触发重绘是现状语义**(重排后的呈现由后续 set_data/字体注入等 queue_redraw 承载),设计不补挂不拆挂 |
|
||||
| battle_stage_view 232/235 行 `font =` + `queue_redraw` | var 直写 | 不变 |
|
||||
| battle_stage_view 132–138/267 行 set_portrait_texture/register_hero_state | 宿主方法 | 同名宿主方法保留(1–2 行转调 mo,box 作参),battle_stage_view 一行不改 |
|
||||
| battle_stage_view 313/316/388 行 set_hero_state | 宿主方法 | 同名保留,转调 `mo.apply_hero_state(state, st._kind == "hero")` |
|
||||
| battle_stage_view 333–335 行 play_hit_impact/flash_hit/mark_dead | 宿主方法 | 不变(宿主保留) |
|
||||
| hud_presenter 77/78/137/162/163 行 set_hero/set_effects | 宿主方法 | 不变 |
|
||||
| fx_probe/ui_probe/ui_struct_probe/ui_click_probe 全部读数 | 六 probe 出口 + box/has_world_hp_bar/slot_row | 出口外形零变(fx_probe 改读宿主计数器、intent_probe/portrait_probe 前缀改指 mo) |
|
||||
| standee_fx_sweep_test 103 行 `s1._intent_charge` | 宿主 var 直读 | 不变(成员原位) |
|
||||
| 内部 tween 路径串 | `"st.hp_value"`(vitals 成员名保留 → 零改);`"st._intent_scale"`/`"st._glyph_rot"` | 改 `"mo._intent_scale"`/`"mo._glyph_rot"`(搬进 mo 的同一函数体内) |
|
||||
|
||||
重绘/重排时序零变化论证:三个属性 setter 体逐字(`_owner.queue_redraw()`);tween 目标路径只换持有者前缀、写序不变;box/font/slot_row 写入面与现状同拍同序(battle_stage_view 一行不改 = 接线时序恒等)。
|
||||
|
||||
## 5. gdstyle 键账预期(逐文件 ≤15)
|
||||
|
||||
| 文件 | 类变量实数 | 基线对账 |
|
||||
|---|---|---|
|
||||
| standee_body.gd | **10**(5 冻结 + st + mo + 3 计数器) | 基线登记 19,实数 10 < 19 = 改小不红 |
|
||||
| standee_vitals.gd | **12** | 无基线键,12 ≤ 15 = 零命中 |
|
||||
| standee_motion.gd | **11** | 无基线键,11 ≤ 15 = 零命中 |
|
||||
|
||||
函数级键:**零函数迁入新键**——六个搬移函数逐字搬运(仅前缀与两处改参),长度/分支/局部/返回/参数全在原值内(最大者 `apply_hero_state` 4 参数 4 分支);宿主新增转调壳 1–2 行零键。基线不随批刷新(改小即绿;收账归后续全清批人工 `--refresh`,须用户批准——与 battle_orchestrator 50→38 先例同口径)。
|
||||
|
||||
## 6. 行为零变化风险点
|
||||
|
||||
1. **tween 属性路径串**:`"st.hp_value"`/`"mo._intent_scale"`/`"mo._glyph_rot"` 拼错 = 运行时属性找不到、动画静默失效。兜底:fx_probe 段的意图弹入断言、hero_state_probe 三态断言、fx_shot_probe 帧取证都在闸内。
|
||||
2. **hero 三态机改形两处**(`is_hero` 参数化、`reset_state` 封装):早退序与 RESET 哨兵语义必须逐拍对齐——`set_hero_state` 的三连早退(非主角/同态/未注册)条件序不变;`_revive` 强制回 idle 两拍改两调用、顺序不变。
|
||||
3. **`_hp_flash_tw` 回色读 `_dead`**:flash_hit 留宿主、跨读 `st._dead`,与现状同一拍。
|
||||
4. **源码锚三条**(theme_projection 679–683):锚行所在函数留宿主且锚行逐字,改造只动同函数其他行的 `st.` 前缀。
|
||||
5. **成员初始化时序**:st/mo 于成员初始化器构造、`_init` 灰 `_owner`/`_kind`——与现状同形,构造期零属性写早于 `_owner` 赋值。
|
||||
6. **counters 迁移**:三个计数器无 setter 无重绘语义,纯读写易位;`fx_probe()` 返回键名逐字。
|
||||
|
||||
## 7. 验收载体建议(真实入口)
|
||||
|
||||
| 载体 | 断言面 | 绑定 |
|
||||
|---|---|---|
|
||||
| static_scan S13(gdstyle_gate 回执) | 「基线外新违规 0、恶化 0」+ standee_body 键账 10 | 被测改动本身的直接判据(键清偿),grep 回执可定位 |
|
||||
| run_all 关联套件 | standee_fx_sweep_test(_intent_charge 直读、fx_probe().flash_count、enemy_id 解析);theme_projection_test(三条源码锚) | 拆分后宿主成员与源码锚零变 |
|
||||
| probe_gate --full | fx_probe 段(碎裂 5/火花 6/闪白计数/三态切换/死亡残位 idle);ui_probe(intent_probe 三档、name_line_probe、portrait_probe、has_world_hp_bar、slot_row);ui_struct_probe ⑥standee 出框断言;ui_click_probe slot_row tooltip | 外部契约面逐一可达 |
|
||||
| render_gate | fx_shot_probe 取证 + 战斗舞台 golden | 站桩呈现像素级零变化 |
|
||||
| run_smoke / run_system_test | 恒跑保险 | 活性 |
|
||||
|
||||
对照表口径:本批为非行为改动(结构重组)逐行申报 + 既有断言面全绿作呈现零变化证明;S13 键账数字即键清偿判据,无需新增断言。
|
||||
|
||||
## 8. 估时
|
||||
|
||||
写卡段不计。实现批(worktree):宿主改造与函数搬移 ≈2h;两新件与头注(≤8 行、无反向链接)≈0.5h;闸跑(S13 + run_all 关联 + probe_gate --full + render_gate + 冒烟/系统)与取证 ≈1.5h;对照表与实现报告 ≈0.5h——**合计 ≈0.5 工作日**。
|
||||
|
||||
## 9. 反哺点(预登记)
|
||||
|
||||
1. architecture.md「模块归属·呈现层」表登记两新件(standee_vitals/standee_motion,各一句职责)。
|
||||
2. 相邻发现(不属本批):board_cell_unit.gd 内嵌类 `_CellPaintState` 27 成员受同一 gdstyle 解析缺陷截断(基线 30 = 6 + 24 漏记),属 gdstyle 存量债同族,是否立卡清偿待裁。
|
||||
3. `_portrait_tex` 与 `_portrait_sprite.texture` 冗余(单一事实源可归一)——本批不动(零变化优先),留债册。
|
||||
|
||||
## 10. 待裁点
|
||||
|
||||
1. **方案形态确认**:推荐案 C(两独立文件 + 计数器归宿主)vs 淘汰案 B(原地 −4,凑不出)与两内类变形(赌解析缺陷)。前提修正:原①「拆出即合规」实测不成立。
|
||||
2. **探针计数器落点**:宿主(推荐——写入方/读取方同在宿主,vitals 让出余量)vs vitals 内(15 满额零余量,快照投影类加一个字段即红)。
|
||||
3. **motion 实例成员命名**:`mo`(推荐,短、域对)vs 其他;vitals 实例沿用 `st`(引用面与 `"st.hp_value"` 路径串零改)。
|
||||
4. **基线收账时点**:本批不刷新(改小即绿,先例口径)vs 随批人工 `--refresh`(须用户批准)。
|
||||
@@ -1,236 +0,0 @@
|
||||
# 设计——组合根注册面(S13 真修复:main.gd 类变量归 15)
|
||||
|
||||
状态行:设计讨论段过程稿 v1.0——待主会话汇总裁决(2026-10-29)
|
||||
|
||||
## 0. 背景与判据来源
|
||||
|
||||
用户 2026-10-29 裁「不允许任何豁免」:main.gd 的 S13 键(`game/presentation/main.gd|quality/max-class-variables = 49`,阈值 15)必须真实修复,architecture 在册的 S13 豁免登记(「组合根类变量面即探针契约面」)随批注销。主会话已点头的主方向:把屏壳+覆盖层一级句柄收进一个「注册面/接口层门面」件,探针从 `main.X` 改走注册面地址。
|
||||
|
||||
本设计的判据来源:
|
||||
|
||||
- code-conventions §1.1 拆分边界纪律五条(职责轴拆分、集体身份、过阈值只作发现信号、拆不出即停卡、禁无效成员别名)与 §1.3 依赖单向(组合根=main.gd+其构造注入的组合根拆件)。
|
||||
- architecture「呈现层装配与会话生命周期」「模块归属·呈现层」「测试与质量域」三节。
|
||||
- godot-master 的 Node 取舍判据("Use RefCounted for logic objects and data containers. Reserve Node for things that must exist in the scene tree")与信号卫生条款;本仓既有先例:ConfigDB 迭代 41 用「三张域容器」解决同构的成员数超标问题,ModalFlow/各交互控制器均为持引用的 RefCounted。
|
||||
- 源码实查:main.gd 915 行 49 var(实数复核);探针+system_test 的 `main.X` 成员引用 867 处(机械统计,扣除 main.tscn/get_node/get_viewport 等非成员形态);四个流程承接件 `root.X` 引用约 350 处。
|
||||
|
||||
## 1. 注册件形态
|
||||
|
||||
### 1.1 推荐形态:一个门面+三个域容器(四文件,全 RefCounted,不挂树)
|
||||
|
||||
| 新件 | 文件 | extends | 类变量数 | 职责一句话 |
|
||||
|---|---|---|---|---|
|
||||
| **界面注册面** | `game/presentation/ui_registry.gd` | RefCounted | **3** | 呈现层界面元素清单:持有三域容器、LAYER_CONTRACT 合同表、`node(key)` 合同寻址、`apply_layer_contract(root)` 唯一落位口 |
|
||||
| **屏壳与全屏容器域** | `game/presentation/ui_screens.gd` | RefCounted | **9** | 三屏壳、屏内一级子层、全屏态、浮层角标、排播泵节点的句柄册 |
|
||||
| **战区视图域** | `game/presentation/ui_battle.gd` | RefCounted | **5** | 战斗屏 A–D 区视图与结算演出句柄册 |
|
||||
| **模态层域** | `game/presentation/ui_modals.gd` | RefCounted | **14** | 十三个模态覆盖层句柄+ModalFlow 栈编排(登记、开合、锁谓词) |
|
||||
|
||||
main.gd 新增一个成员 `ui`(类型 UiRegistry),探针与流程件的新地址形如 `main.ui.modals.level_screen`、`main.ui.battle.board_zone`、`main.ui.screens.menu_screen`。
|
||||
|
||||
**为什么是三容器而不是一件**: gdstyle 阈值 15 是按文件的,句柄 27 个+flow/row_pacer 共 29 个进一个文件必然超阈、又要开新基线键=留债,违用户裁决出口。 分组轴不是拍脑袋切的——它就是 LAYER_CONTRACT 的 kind 轴(modal/shell/state/float/node)加上 battle.md 的战区轴,三组身份先于本批存在(详见 §2),是「按既有领域轴收拢」,不是「为凑 15 而切」。
|
||||
|
||||
**为什么是 RefCounted 不是 Node**: 注册面是纯句柄容器+合同数据,零 `_process`、零绘制、零树位需求——按 godot-master 判据「Node 只留给必须在场景树里存在的东西」应取 RefCounted。 它持有的节点(屏壳/覆盖层/视图)都是 `_build_ui` 一次装配、随 main 同生死的常驻件,不含任何会话期 `queue_free` 对象(局态在 run_scope,留 main),RefCounted 持 Node 引用无悬挂风险;本仓先例充分:ModalFlow、TreasureInteractController、CampShopPresenter、DebugSession、SettingsStore 全是持引用 RefCounted。 若做成 Node 挂树,反而要回答「它占哪个树位」「进不进 LAYER_CONTRACT」「冒烟 V1d 怎么看它」三个新问题,纯增噪声。
|
||||
|
||||
**class_name**: 四件均给 class_name(UiRegistry/UiScreens/UiBattle/UiModals),main 里 `var ui: UiRegistry` 类型化;随批跑一次编辑器扫描刷新全局类缓存+同步 .uid(code-conventions 语言纪律 5)。
|
||||
|
||||
### 1.2 逐成员去向对账表(main.gd 现有 49 var,三档:进注册面/留 main/消灭)
|
||||
|
||||
**进注册面(28)**——成员名在容器内去下划线(变为公共地址面,与 LAYER_CONTRACT 键名对齐):
|
||||
|
||||
| # | 现 main 成员 | 去向 | 依据 |
|
||||
|---|---|---|---|
|
||||
| 1 | `_menu_screen` | `ui.screens.menu_screen` | 屏壳(kind=shell) |
|
||||
| 2 | `_camp_screen` | `ui.screens.camp_screen` | 屏壳 |
|
||||
| 3 | `_adventure_screen` | `ui.screens.adventure_screen` | 屏壳 |
|
||||
| 4 | `_start_overlay` | `ui.screens.start_overlay` | 菜单屏内一级子层 |
|
||||
| 5 | `_battle_root` | `ui.screens.battle_root` | 冒险屏内一级子层 |
|
||||
| 6 | `_inter_overlay` | `ui.screens.inter_overlay` | 全屏态(kind=state) |
|
||||
| 7 | `_inter_label` | `ui.screens.inter_label` | 过场层附随标签 |
|
||||
| 8 | `debug_badge` | `ui.screens.debug_badge` | 全局浮层(kind=float) |
|
||||
| 9 | `_row_pacer` | `ui.screens.row_pacer` | LAYER_CONTRACT kind=node 注册层(节点本体仍 add_child 到 main,注册面只持引用,树位零变化) |
|
||||
| 10 | `stage` | `ui.battle.stage` | 战斗屏 B 区 |
|
||||
| 11 | `log_view` | `ui.battle.log_view` | B 区明细带 |
|
||||
| 12 | `info_panel` | `ui.battle.info_panel` | C 区 |
|
||||
| 13 | `board_zone` | `ui.battle.board_zone` | D 区(含 toast/fx/board_view/ap_bar) |
|
||||
| 14 | `settlement_fx` | `ui.battle.settlement_fx` | 结算演出覆盖层 |
|
||||
| 15 | `legend_overlay` | `ui.modals.legend_overlay` | 模态层(kind=modal,13 件全集) |
|
||||
| 16 | `node_overlay` | `ui.modals.node_overlay` | 模态层 |
|
||||
| 17 | `level_screen` | `ui.modals.level_screen` | 模态层(host=adventure_screen,TAG_SCREEN_STATE) |
|
||||
| 18 | `curio_overlay` | `ui.modals.curio_overlay` | 模态层 |
|
||||
| 19 | `_end_overlay` | `ui.modals.end_overlay` | 模态层 |
|
||||
| 20 | `shop_overlay` | `ui.modals.shop_overlay` | 模态层 |
|
||||
| 21 | `camp_overlay` | `ui.modals.camp_overlay` | 模态层(shell=camp_screen) |
|
||||
| 22 | `settings_overlay` | `ui.modals.settings_overlay` | 模态层 |
|
||||
| 23 | `status_panel` | `ui.modals.status_panel` | 模态层 |
|
||||
| 24 | `career_overlay` | `ui.modals.career_overlay` | 模态层 |
|
||||
| 25 | `save_select_overlay` | `ui.modals.save_select_overlay` | 模态层 |
|
||||
| 26 | `confirm_dialog` | `ui.modals.confirm_dialog` | 模态层 |
|
||||
| 27 | `debug_overlay` | `ui.modals.debug_overlay` | 模态层(TAG_NON_LOCKING) |
|
||||
| 28 | `_modal_flow` | `ui.modals.flow` | 模态编排与模态层同域(登记/开合/锁谓词的宿主) |
|
||||
|
||||
**留 main(14)+新增(1)=改后 15**:
|
||||
|
||||
| # | 成员 | 保留理由 |
|
||||
|---|---|---|
|
||||
| 1 | `db` | 核心配置读视图——组合根唯一加载单点读取入口(`_ready` 装配) |
|
||||
| 2 | `run_scope` | 会话承载节点——架构在册「局态一律住 RunScope,组合根经 run_scope.X 读写」;173 处探针引用零迁移 |
|
||||
| 3 | `save_manager` | autoload 读视图——architecture 在册「main.save_manager 语义零迁移」 |
|
||||
| 4 | `meta` | autoload 读视图(同上) |
|
||||
| 5 | `settings_store` | 系统级设置存储——非界面元素(无视觉面),`_ready` 装配、`_quit_game` 落盘、SettingsOverlay 构造注入 |
|
||||
| 6 | `logger` | 试玩日志器——组合根埋点面(非界面元素) |
|
||||
| 7 | `_debug_entry` | 调试会话门控(组合根启动态布尔) |
|
||||
| 8 | `_confirm_consumer` | 确认弹窗分派状态量(组合根自身状态) |
|
||||
| 9 | `_confirm_consumer_slot` | 分派附随槽号(与 8 同一关注点成对读写) |
|
||||
| 10 | `_debug` | DebugSession——调试会话状态机持有(逻辑件非界面件) |
|
||||
| 11 | `_treasure_ui` | TreasureInteractController——组合根拆件(核心写调用代执行) |
|
||||
| 12 | `_bonus` | CurioInteractController——组合根拆件 |
|
||||
| 13 | `_camp_pres` | CampShopPresenter——组合根拆件 |
|
||||
| 14 | `_tune_sim` | TuneSimController——调参测量控制器(逻辑件) |
|
||||
| 15 | `ui`(新增) | 界面注册面——本设计的唯一新成员 |
|
||||
|
||||
这 14+1 全部是「组合根自身状态+拆件引用+autoload 读视图」,正是 §1.1 拆分纪律下组合根该留的最小内聚面;没有一件是因为「计数不够了才留下」的。
|
||||
|
||||
**消灭(7)**——全部是别名或一行转发,属拆分纪律⑤明令禁止保留的无效成员:
|
||||
|
||||
| # | 成员 | 本体 | 消灭后地址 |
|
||||
|---|---|---|---|
|
||||
| 1 | `board_view` | = board_zone.board_view | `ui.battle.board_zone.board_view`(探针惯用 `var bv = ...` 局部承接,每文件 1–2 处) |
|
||||
| 2 | `ap_bar` | = board_zone.ap_bar | `ui.battle.board_zone.ap_bar` |
|
||||
| 3 | `_modals` | = _modal_flow.stack | `ui.modals.flow.stack`(ui_struct 登记序断言) |
|
||||
| 4 | `_row_queue` | 委托属性 = _row_pacer.pending_rows() | `ui.screens.row_pacer.pending_rows()`(main 自身 3 处+pacing_queue_test 1 处;同一 Array 引用,语义不变) |
|
||||
| 5 | `_seed_edit` | = debug_overlay.seed_edit | `ui.modals.debug_overlay.seed_edit.text`(仅 main._seed_value 内部消费,探针零引用) |
|
||||
| 6 | `_settlement_stop_pending` | 委托属性(读=timer.is_armed(),写=arm()/disarm()) | `run_scope.settlement_stop_timer` 直呼(ui_click_probe 2 处读+main_adventure_flow 3 处写) |
|
||||
| 7 | `_deferred_modal` | 委托属性 = _modal_flow._deferred | `ui.modals.flow._deferred`(t17_defer_probe 1 处) |
|
||||
|
||||
对账:14(留)+28(进注册面)+7(消灭)=49 ✓;main 改后 = 14+1(ui)=**15,恰在阈值内**。
|
||||
|
||||
### 1.3 main.gd 改后类变量实数
|
||||
|
||||
**15**(14 留+ui)。gdstyle 的 max-class-variables 语义是「超过 15 才红」,15=绿。此后 main 每想加成员就是过阈红——这正是拆分纪律③的合规用法:过阈值作发现信号,新句柄该进注册面、新职责该拆新件。
|
||||
|
||||
## 2. 职责语句+单一变化原因
|
||||
|
||||
| 件 | 职责语句 | 单一变化原因 | 集体身份判据 |
|
||||
|---|---|---|---|
|
||||
| ui_registry | 「呈现层界面元素清单的唯一事实源——哪些层、什么序、地址在哪」 | 界面元素集合或层序变化(加屏/加覆盖层/改层序) | 它就是今天散在 main 的 LAYER_CONTRACT+_layer_node+一级句柄三样东西的合体;合同键、登记序、句柄址本是同一份清单的三个投影 |
|
||||
| ui_screens | 「不进模态栈的树位层册——三屏壳与其一级子层、全屏态、浮层角标、排播泵节点」 | 屏壳/全屏态/浮层集合变化 | 集体身份=LAYER_CONTRACT 里 kind≠modal 的项(shell/state/float/node)+屏内一级子层句柄 |
|
||||
| ui_battle | 「战斗屏四区(A 状态/B 明细/C 数据/D 棋盘)视图与结算演出句柄册」 | 战斗区视图构成变化(battle.md 三区面) | battle.md 三区+演出,是架构文档反复引用的既有概念,非本批发明 |
|
||||
| ui_modals | 「模态层域——十三个模态覆盖层句柄+模态栈编排(登记/开合/输入锁谓词)」 | 模态层集合或模态编排语义变化 | 集体身份=「被 ModalStack 登记的层」——遮挡互斥、开合同步、锁谓词是这 13 件共享的行为面 |
|
||||
|
||||
**禁凑计数袋自检(拆分判据①–⑤逐条)**:
|
||||
|
||||
1. 拆分沿职责轴:三容器的轴=LAYER_CONTRACT kind 轴+战区轴,两者都是本批之前就存在的领域轴;过阈值(49→15)只是**发现信号**,不是切分依据。
|
||||
2. 集体身份:每件命得出名字、说得清「共同表达什么」(见上表),没有一个容器是「剩下的成员」。
|
||||
3. 过阈值只作动机=违规:本设计若只把 30 个句柄原样搬进一件,那才是凑计数;按领域轴分三域+把合同机器(今天在 main 里同样占职责面的 LAYER_CONTRACT/_layer_node)一并归位,是职责收拢。
|
||||
4. 拆不出内聚单元须停卡:本设计拆得出(见上),不停卡。
|
||||
5. 禁无效成员/别名:本批**净消灭 7 个别名/转发成员**(§1.2 第三表)+退役 main 侧六个纯转发方法(§4.2),方向是减不是留。
|
||||
|
||||
依赖方向自检(§1.3):注册面只持视图引用、零核心写调用、零信号连接——它不是新的写调用出口,组合根单点装配不变;视图仍经信号到 main(或 main 拆件)再到 core,依赖单向零触碰。
|
||||
|
||||
## 3. 探针契约迁移
|
||||
|
||||
### 3.1 新地址形态
|
||||
|
||||
**推荐**:`main.ui.<域>.<句柄>`(例:`main.ui.modals.level_screen`、`main.ui.battle.board_zone`、`main.ui.screens.menu_screen`)。三段式地址每段都有领域含义(组合根→注册面→域→元素),与 ConfigDB 的 `db.<域容器>.<成员>` 两段式同构——本仓已验证的容器寻址形态。
|
||||
|
||||
**备选一(双容器直挂,`main.modals.X` 两段式)**:少一跳,但 main 要放 3 个容器成员,改后 main=16 过阈,只能再靠合并 `_confirm_consumer_slot` 之类凑减员——凑计数味,淘汰。
|
||||
**备选二(单件+字典存储+方法访问器 `main.ui.layer("legend_overlay")`)**:丢了类型化字段,且约 30 个访问器方法有撞 max-public-methods 默认阈值的风险(board_view 现值 27 已在基线,默认阈值必然更低)=新基线键=留债,淘汰。
|
||||
|
||||
### 3.2 改址策略(约 867 处探针/系统测试引用+约 200 处流程件 root.X 引用+main 自身)
|
||||
|
||||
**机械映射表**(实现批以脚本生成+对账,人工复核语义位):映射表条目形如 `旧路径 → 新路径`,来源即 §1.2 对账表。三类引用分别处理:
|
||||
|
||||
1. **属性读/写(约 750 处)**:`main.<名>` → `main.ui.<域>.<名′>`(`名′`=去下划线后的名)。前缀链式读写在 GDScript 天然支持(`main.ui.modals.debug_overlay.seed_edit.text = "42"` 与现形态同构);探针里 `var bv = main.board_view` 的局部承接习惯使别名消灭的实际改动收敛到每文件 1–2 处。
|
||||
2. **方法调用(约 110 处,其中绝大多数零迁移)**:组合根流程方法(`_start_adventure_from_menu` 16、`_open_save_select` 7、`_on_save_select_closed` 9、`_on_camp_closed` 6、`_on_battle_end_continue` 4、`_show_debug_overlay` 4、`_resume_from_menu` 3、`_flush_row_queue` 3、`_seed_value` 3 等)**留 main,零迁移**——它们是模式流转与流程入口,本就是组合根职责。真正改址的方法引用只有四条:`main._input_locked()`(18 处)→ `main.ui.modals.flow.locks_input()`;`main._layer_node(key)`(3 处,system_test)→ `main.ui.node(key)`;`main._open_modal/_close_modal`(探针各 1 处+流程件 root. 共约 23 处)→ `main.ui.modals.flow.open/close`;`root._open_modal_after_playback`(2 处)→ `root.ui.modals.flow.open_after_playback`。
|
||||
3. **字符串键取值(smoke_boot 的 `main.get("<名>")` 6 处)**:`main.get("run_scope")`/`main.get("settings_store")` 零迁移(留 main);其余改 `main.get("ui").<域>.<名′>`(get 只解析一层,后续走公共字段)。
|
||||
|
||||
**流程承接件随批同规改址**:main_ui_build 的赋值目标改 `root.ui.<域>.<名′> = ...`;main_adventure_flow/main_overlay_flow/main_debug_flow 的 `root.<名>` 同表映射。构造注入的 context 束(CurioFlowContext/CampFlowContext 的 overlay/toast/start_overlay 等键值)改址取值,注入时点与值不变。
|
||||
|
||||
**源码级断言随批重锚(易漏项,实查全量在案)**:
|
||||
|
||||
- `source_guard_test.gd` V1d「层序落位单口」:现扫描 main.gd 源码中 `_apply_layer_contract` 之外零 `move_child(`。合同机器迁入 ui_registry 后,重锚为「扫全 `game/presentation/*.gd`:`move_child(` 只允许出现在 ui_registry.gd 的 `apply_layer_contract` 函数体内」(判据同步强化:从扫单文件变扫全目录,比原判据更严)。
|
||||
- `theme_projection_test.gd` V6:`main_src.contains("debug_overlay.diagnose_requested.connect(_on_diagnose_pressed)")` 字符串断言 → 改为 ui.modals.debug_overlay 新串。
|
||||
- 其余 main.gd 源码断言(V8 GP 影子账残留检查)为「禁止出现」型,不受影响;`meta_progression_forge_test` 经 `load("res://presentation/main.gd")` 直呼 static `build_adventure_params`——留 main,零迁移。
|
||||
|
||||
**改址完整性自检**(验收辅证):映射表驱动的全仓 grep——`game/` 下(探针/tests/flow 四件/main 自身)旧一级路径 `main.<旧名>`/`root.<旧名>`/`self.<旧名>` 残留必须为 0(按 49 名逐名 grep,报告留档)。
|
||||
|
||||
### 3.3 architecture 登记句改写建议
|
||||
|
||||
「呈现层装配与会话生命周期 §三屏壳与组合根句柄面」现句(含 S13 豁免登记)整句退役,建议改写为:
|
||||
|
||||
> 屏成员与覆盖层句柄经**界面注册面**(main.ui,`ui_registry.gd`+三域容器 ui_screens/ui_battle/ui_modals,全 RefCounted)统一暴露;探针挂载假设=`main.ui.<域>.<句柄>` 路径(2026-10-29 用户裁「不允许任何豁免」——原「组合根 main.gd 一级句柄(main.X 路径零迁移)」挂载假设与 S13 豁免登记同批注销,探针面全量改址,行为零变化由 probe_gate/render_gate/冒烟/系统测试四闸主证)。组合根 main.gd 成员面收口为组合根自身状态+拆件引用+autoload 读视图(类变量 15,阈内)。层序唯一事实源=`ui_registry.LAYER_CONTRACT`+`ui.apply_layer_contract()`;模态登记/开合/锁谓词单口=`ui.modals`(ModalFlow 语义零变化)。
|
||||
|
||||
「模块归属·呈现层」表同步增四行(四新件),main_ui_build 行的「层序逻辑不在此件——唯一事实源仍是 main.LAYER_CONTRACT」句改指 ui_registry。
|
||||
|
||||
## 4. main.gd 改后形态
|
||||
|
||||
### 4.1 剩余成员清单
|
||||
|
||||
见 §1.2 第二表(14 留+ui,逐个理由在表内,不重复)。文件头注同步改写:组合根职责语句追加一句「界面句柄与层清单在 ui 注册面(ui_registry.gd)」。
|
||||
|
||||
### 4.2 接线流程变化
|
||||
|
||||
1. **装配入口**:`_ready` 在 `_build_ui()` 之前 `ui = UiRegistry.new()`(容器随门面构造);`MainUiBuild.build(self)` 八步内部赋值目标全部改 `root.ui.<域>.<名′>`,八步顺序、add_child 顺序、连接语句逐条不变。
|
||||
2. **MainUiBuild 交付物改型**:build 签名不变(仍 `build(root)`),改的是写入目标——从「给 root 造 30 个一级成员」变「往 root.ui 三容器登记」。装配序与 z 序零改动(合同落位仍最后一步)。
|
||||
3. **合同机器搬家**:`LAYER_CONTRACT` 常量(内容逐字不动)、`_apply_layer_contract()`(root 作参传入)、`_layer_node(key)`(改为 ui_registry.`node(key)` 的 19 键 match)、`_register_modal`(改入 ui_modals 为 `register_layer(m, tags)`,anchors preset+flow.register 语义逐字)四样整体迁入注册面;main 侧不留转发壳。
|
||||
4. **模态口收口**:main 的六个纯转发方法退役——`_open_modal`/`_close_modal`/`_on_modal_closed`/`_input_locked`/`_open_modal_after_playback`/`_on_pump_ended`。调用方(三个流程件、context 注入束、row_pacer.pump_ended 注入点、信号 connect 的 bind 目标、探针)一律改指 `ui.modals.flow` 真方法;`_replay_locked_click` **留 main**(读 run_scope.locked_click+调 _on_board_action,是组合根行为,作为回调注入 flow 不变)。
|
||||
5. **`_seed_value()`**:种子框读取改 `ui.modals.debug_overlay.seed_edit.text`(全工程唯一种子框读取处纪律不变)。
|
||||
|
||||
### 4.3 LAYER_CONTRACT 与 _apply_layer_contract
|
||||
|
||||
合同表条目、顺序、tags、host/shell 标注**逐字零变化**,只换宿主文件;落位算法逐字搬运(move_child 单口语义不变,冒烟 V1d 判据按 §3.2 重锚后仍覆盖「全 presentation 无第二落位点」)。改层序仍只改合同表。
|
||||
|
||||
### 4.4 RunScope 生命周期零变化声明
|
||||
|
||||
`_begin_session`/闲时会话/整节点 `queue_free` 机制**一字不动**;run_scope 留 main,注册面与三容器**零会话期引用**(不持 adventure/runner/settlement,控制器仍走现值回调),会话更替对注册面完全透明。存活性矩阵第五引用面的四持句柄件+_row_pacer 逐面同源比对断言(system_test V3a–V3i)逻辑零变化,仅 `_modal_flow`→`main.ui.modals.flow`、`_row_pacer`→`main.ui.screens.row_pacer` 两处取址随批改。
|
||||
|
||||
## 5. 行为零变化风险点
|
||||
|
||||
1. **装配与接线时序**:容器在 `_ready` 建闲时会话之前创建并装配完毕,八步 build 顺序、`_apply_layer_contract` 末位调用点、信号连接顺序逐条不变。风险形态=漏改一处地址→运行期 null 实例 SCRIPT ERROR→被冒烟闸③与探针 error_scan 抓住(不静默)。
|
||||
2. **模态开合**:ModalFlow 的八个查询/钩子 Callable(start_visible_get/inter_visible_get/settlement_get/rows_empty_get/flush_rows/on_open_sync/on_close_sync/replay_click)注入值不变,仅 `root._start_overlay.visible` 这类 lambda 体内取址改 `root.ui.screens.start_overlay.visible`;开合编排、挂起兜底、点击重放语义零触碰。
|
||||
3. **会话更替**:注册面零局态引用(§4.4),queue_free 不触及;row_pacer 节点本体仍 add_child 到 main、树位由合同落位,注册面只持引用——第五引用面断言改址后逐面同源比对仍成立。
|
||||
4. **别名消灭的断言等价性**:board_view/ap_bar/_modals/_row_queue 四件消灭后,探针断言经多一跳取到**同一对象引用**(属性链与别名同指),断言语义逐条等价;system_test V1 的句柄等价断言(`main.board_view == main._adventure_screen.board_view` 型)改址为 `ui.battle.board_zone.board_view == ui.screens.adventure_screen.board_view` 后仍是有效的装配结构断言。
|
||||
5. **接缝属性消灭的读/写映射**:`_settlement_stop_pending` 读=armed→`is_armed()`、写=arm/disarm→同名方法直呼,映射一一对应且 run_scope 在探针用时点恒非空(_ready 即建,永非 null 契约);`_deferred_modal`→`flow._deferred` 同字段直读。
|
||||
6. **演出链**:settlement_fx/row_pacer 的 play/enqueue 调用点改址不改序——结算行排播、轮横幅、锁期点击重放的时序敏感面(T17)零触碰;t17_defer_probe 挂起态断言改读 `flow._deferred`,判据不变。
|
||||
7. **源码级断言漏改**:V1d/V6 两处实查在案(§3.2),随批重锚;若存在未登记的字符串匹配型断言,run_all 关联档跑批暴露——本设计已全量 grep `presentation/main.gd` 引用面确认只有上列两件。
|
||||
|
||||
RNG 消费序零触碰(本批不涉任何随机面);PARITY 触面(battle_orchestrator.gd)不在 diff;呈现层订阅禁令、核心写调用唯一出口纪律零触碰。
|
||||
|
||||
## 6. 验收载体建议
|
||||
|
||||
| 闸 | 载体与判据 |
|
||||
|---|---|
|
||||
| probe_gate | **默认段+`--click`+`--full` 全跑**——探针是本批改址的第一消费方(ui_click_probe 1079 行是最大户),只跑默认段会漏最深的改址面;判据=全段退出码 0 |
|
||||
| render_gate | golden 零差异(shot_probe 七屏+菜单 golden+棋盘 golden)——视觉零变化的主证 |
|
||||
| run_smoke | V1 装配句柄在位(get() 键改址后)+V2 启动态六条——boot 侧证明注册面装配完整 |
|
||||
| run_system_test | V1–V9 全绿:LAYER_CONTRACT 寻址(改 ui.LAYER_CONTRACT/ui.node)、句柄等价、存活性矩阵、模态互斥、两连局+续玩 |
|
||||
| run_all(关联档) | 申报套件:source_guard_test(V1d 重锚)、theme_projection_test(V6 字符串)、pacing_queue_test(_row_queue 改址)、meta_progression_forge_test(static 入口零变化);main.gd 是否按横切面回落全量套件见 §8 待裁点 |
|
||||
| static_scan | S9 过(四新文件全类型标注);S13 键账:main.gd 键从基线消失、四新文件零新键(§7) |
|
||||
| 改址完整性自检 | §3.2 的 49 名逐名 grep 残留=0,报告留档(实现报告对照表挂行) |
|
||||
|
||||
验收闭合口径(test-conventions §8):判据绑定面=「探针经新地址取到同一节点并驱动真实输入路径」——probe_gate 全绿+系统测试全绿+golden 零差异三件齐,即「改址不改变行为」的真实入口主证;grep 自检只作完整性辅证,不作行为判据。
|
||||
|
||||
## 7. gdstyle 键账预期
|
||||
|
||||
| 文件 | 改后类变量 | 键账 |
|
||||
|---|---|---|
|
||||
| main.gd | **15**(14+ui) | 基线键 `main.gd|quality/max-class-variables = 49` 消失——还债方向下降,注销合法 |
|
||||
| ui_registry.gd | 3 | 零新键 |
|
||||
| ui_screens.gd | 9 | 零新键 |
|
||||
| ui_battle.gd | 5 | 零新键 |
|
||||
| ui_modals.gd | 14 | 零新键(阈内,余量 1) |
|
||||
|
||||
基线 refresh 人工跑(`--refresh`):净减 1 键(约 15 键的 6.7%),低于 10% 骤降守卫,无需 `--force`。四新文件其余质量键(max-public-methods/max-file-length 等)预期零命中——容器纯字段无长函数,match 键数(19)在 max-branches 默认内,若实现批实测出新键按基线外 NEW 红处理、不得开豁免(用户裁决口径统一适用)。
|
||||
|
||||
§3.3 的登记句改写即豁免注销文案;「S13 豁免登记第二/三条」(tune_sim_controller、battle_orchestrator)不在本批范围、原文不动。
|
||||
|
||||
## 8. 估时与待裁点
|
||||
|
||||
**估时:3–4 个工作日**。构成:映射表脚本生成+四文件建件+main/流程件改址 1–1.5 天;探针/系统测试/冒烟改址+源码级断言重锚 1 天;闸循环(probe_gate --click --full/render golden/smoke/system_test/run_all 关联档/static_scan)修复余量 0.5–1 天;architecture 登记句+模块归属表+卡片改动—验收对照表 0.5 天。低于迭代冻结线(5 工作日),可编批。
|
||||
|
||||
**待裁点(呈用户裁决)**:
|
||||
|
||||
1. **注册面拓扑**:推荐「一门面+三域容器」(§1.1,main=15);备选「双容器直挂」因 main 会过阈 16、需再凑减员而淘汰。是否照推荐案执行。
|
||||
2. **合同机器是否随批迁入注册面**:推荐迁(LAYER_CONTRACT+_apply_layer_contract+_layer_node+_register_modal → ui_registry/ui_modals,职责闭合);不迁则注册面只管址不管序,main 留合同——两案都可达 15,迁是内聚更优解但多动 V1d/system_test 约 8 处。
|
||||
3. **消灭与改名清单**:七个别名/转发成员消灭+六个 main 纯转发模态方法退役+容器内成员去下划线(对齐合同键名)——涉及探针断言面写法(`main._input_locked()`→`ui.modals.flow.locks_input()` 等),请整体确认或逐项裁。
|
||||
4. **run_all 关联档口径**:main.gd 是全探针宿主,保守口径=按横切面回落全量套件;精确口径=只跑 §6 申报四件。请裁跑批档位。
|
||||
5. **编批**:估时 3–4 天在冻结线内,编入哪个迭代由迭代编排段定。
|
||||
@@ -34,9 +34,9 @@
|
||||
| 2 | `board_view.gd\|quality/max-branches\|_paint_cell = 24` | 24/8 | 同上 |
|
||||
| 3 | `board_view.gd\|quality/max-local-variables\|_paint_cell = 22` | 22/10 | 同上 |
|
||||
| 4 | `board_view.gd\|quality/allocation-in-loop`(裸键) | 命中 | `board_view.gd:249`——rebuild() 建格循环内 `_CELL_UNIT.new()` |
|
||||
| 5 | `board_view.gd\|quality/max-class-variables = 32` | 32/15 | `board_view.gd:49-85`(var 成员 31 + `cell_size` 只读属性 1,以闸实测为准) |
|
||||
| 5 | `board_view.gd\|quality/max-class-variables = 32` | 32/15 | `board_view.gd:49-85`(var 成员 31)+:93(`cell_size` 只读属性;计数以闸实测为准) |
|
||||
| 6 | `board_view.gd\|quality/max-public-methods = 27` | 27/20 | 全文件:11 setter+6 探针出口+4 几何契约出口+3 入站事件+2 生命周期(rebuild/refresh)+1 访问器(board()) |
|
||||
| 7 | `level_runner.gd\|quality/max-public-methods = 50` | 50/20 | `game/core/level_runner.gd`——其中商店同签名委托 17 个公开方法(751-829 行)+3 个私有转发(`_bind_shop`:728、`_spend_discounted`:772、`_shop_draw_shelf`:783)+`_shop` 成员(:44) |
|
||||
| 7 | `level_runner.gd\|quality/max-public-methods = 50` | 50/20 | `game/core/level_runner.gd`——其中商店同签名委托 17 个公开方法(751-828 行)+3 个私有转发(`_bind_shop`:728、`_spend_discounted`:772、`_shop_draw_shelf`:783)+`_shop` 成员(:44) |
|
||||
| 8 | `level_runner.gd\|quality/max-class-variables = 30` | 30/15 | `level_runner.gd` 类成员区(含 `hero_hp`/`gp` 两属性) |
|
||||
| 9 | `level_runner.gd\|quality/max-returns\|_enter_node = 7` | 7/6 | `level_runner.gd:486-513`——shop 分支 pool/legacy 双 return(:509、:511) |
|
||||
| 10 | `battle_orchestrator.gd\|quality/max-file-length = 1035` | 1035/1000 | `game/core/battle_orchestrator.gd`——装板与变异布置域六函数合计约 140 行(:414-549) |
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
- board_view 公开方法 27 个全是契约面:setter 是组合根注入面(依赖单向纪律),探针出口(cells_probe/diggable_probe/hover_probe/fog_params_probe/type_glow_probe/cell_rect_probe)是探针断言面,几何出口与入站事件是演出与输入契约。可降空间极小。
|
||||
- battle_orchestrator 装板域六函数全仓零外部调用,仅本文件三处调用(:271 begin_battle、:801 _exit_distribution、:835 player_request_refresh)——拆件不触任何外部调用面。
|
||||
- 六函数现行均无超标键(基线无其函数级键);`_install_new_board` 体内 442-451 行为宿主态复位块(五处计数清零+板序推进+board_changed 发射+秘宝叠加层退役)——按第 6 节 D1 裁决留宿主薄壳。
|
||||
- 六函数现行均无超标键(基线无其函数级键);`_install_new_board` 体内 443-452 行为宿主态复位块(五处计数清零+板序推进+board_changed 发射+秘宝叠加层退役)——按第 6 节 D1 裁决留宿主薄壳。
|
||||
- `_board_generator` 全文件仅四处使用(:42 声明、:233 创建、:239 fatal 接线、:416 装板消费)——装板族独占,随件迁移后宿主成员退役(38→37)。
|
||||
- level_runner 商店委托面被呈现层 5 文件(camp_shop_presenter/main_adventure_flow/main_overlay_flow/main_ui_build/shop_overlay_view)、`game/sim/level_autoplay.gd`、测试 4 套件(level_shop_economy/pool_case_d/tree_rules_v11/hero_ledger)引用——shop_overlay_view 三处命中均为注释投影引用(:15/:88/:152 实查),代码调用面在 presenter/组合根拆件/sim 侧。
|
||||
- `tools/run_all_gates.sh` PARITY_TOUCH_FACES 含 `game/core/battle_orchestrator.gd`——本批必触面。
|
||||
@@ -122,6 +122,7 @@
|
||||
| game/core/battle_orchestrator.gd | 战斗结算编排中枢 | 修改(非行为改动——装板域六函数迁出、宿主薄壳承接复位块、`_board_generator` 成员退役、三调用点改址;验收=对照表行 V4) |
|
||||
| game/core/board_installer.gd | 棋盘安装与变异布置域件(新增,architecture v1.24 功能层在册) | 新增(非行为改动;验收=对照表行 V4) |
|
||||
| game/tests/unit/core/level_shop_economy_test.gd | 关卡图与商店宿主套件 | 修改(仅新增断言 _test_shop_node_entered_payload〔尾波 V1〕;委托面调用点改址归并排卡) |
|
||||
| game/tests/unit/core/run_time_fatal_test.gd | 运行期违约通道负面套件 | 修改(wr5 棋盘生成半边改指 BoardInstaller 新组装点——T0 复核补查项:卡面 §3 漏查的该测试白盒取数点 `_board_generator` 随成员退役断链,wr5 断言目标违约→封印传导不变) |
|
||||
| game/tests/static_scan.sh | 静态扫描域承载 | 修改(S7 B1 域文件集与 S8 await 文件集增行 board_installer——工程随动,architecture 拆件定稿节 S7/S8 随动条在册) |
|
||||
|
||||
新增件「为什么不能复用」理由与唯一落点核查见第 10 节;对不上即卡片不成立。
|
||||
@@ -163,7 +164,7 @@
|
||||
|
||||
**T3 battle_orchestrator 装板域拆件——键 10 归绿(1–1.5 工作日)**(前置:architecture v1.24 轴丙在册)
|
||||
|
||||
- [ ] 建 `game/core/board_installer.gd`(引用束注入,第 10 节落位预检),装板逻辑六函数迁件;`_install_new_board` 拆件体=生成→决议→装板→摇号→布置(415-441 行段),宿主薄壳 `_install_and_reset` 承载复位块(442-451 行段:五处计数清零+板序推进+board_changed 发射+秘宝叠加层退役),时序逐字
|
||||
- [ ] 建 `game/core/board_installer.gd`(引用束注入,第 10 节落位预检),装板逻辑六函数迁件;`_install_new_board` 拆件体=生成→决议→装板→摇号→布置(415-441 行段),宿主薄壳 `_install_and_reset` 承载复位块(443-452 行段:五处计数清零+板序推进+board_changed 发射+秘宝叠加层退役),时序逐字
|
||||
- [ ] 宿主三调用点(:271/:801/:835)改调薄壳;删宿主 `_board_generator` 成员(38→37,禁无效成员)
|
||||
- [ ] static_scan.sh S7 B1 域文件集与 S8 await 文件集增行
|
||||
- [ ] 孤立验证:`-- --only=variant_placement,round_flow,seal_polarity` 全绿+`python tools/run_smoke.py`
|
||||
|
||||
@@ -21,14 +21,14 @@
|
||||
跳过设计线的证据指认(需求性工程条目,第〇步核验放行 2026-10-29):
|
||||
|
||||
- 待办清单条目实况:委托壳=迭代 37 卡④ ShopSession 拆分时立的「冻结公开面」契约过渡件;架构登记=`design/engineering/architecture/architecture.md:109`「外部调用面由 LevelRunner 同签名委托承载(外部零变化)」。
|
||||
- 拆除形态权威=`architecture.md:152`「调用直连:不留中间人委托壳(纯转传=Middle Man 反模式,2026-10-26 用户裁定)」。
|
||||
- 拆除形态权威=`architecture.md:154`「调用直连:不留中间人委托壳(纯转传=Middle Man 反模式,2026-10-26 用户裁定)」。
|
||||
- 2026-10-29 写卡会话裁决:改址定式四条(公开成员取件/零调用死壳删/测试直连私有面/契约注释随壳消失)+ spend_gp 归属确认非问题(共享冒险钱包的校验扣款原语,宿主 ShopSession 语义自洽、不迁移)。
|
||||
|
||||
## 3. 现状事实(代码级,开工自行复核)
|
||||
|
||||
委托壳块:
|
||||
|
||||
1. level_runner.gd:722–724 区块注释(「本类保留同签名委托」句)+:725(「白盒入口——外部调用面与断点取数面零变化」)+:751–828 共 19 个同签名转传方法:shop_products:751/current_price:755/purchased_tier:759/buy_product:763/player_request_refresh:767/_spend_discounted:772/set_shop_pool:778/_shop_draw_shelf:783/pool_stock:787/pool_price:791/shop_shelf:795/shop_refresh_free_left:799/shop_refresh_cost:803/shop_refresh:807/spend_gp:811/buy_pool_item:815/is_shop_pool:819/shop_bp_shelf:823/shop_bp_visit_buys:827。
|
||||
1. level_runner.gd:723–725 区块注释(:723「商店房兑付」节头保留;:724「本类保留同签名委托」句+:725「白盒入口——外部调用面与断点取数面零变化」两句随壳删除)+:751–828 共 19 个同签名转传方法:shop_products:751/current_price:755/purchased_tier:759/buy_product:763/player_request_refresh:767/_spend_discounted:772/set_shop_pool:778/_shop_draw_shelf:783/pool_stock:787/pool_price:791/shop_shelf:795/shop_refresh_free_left:799/shop_refresh_cost:803/shop_refresh:807/spend_gp:811/buy_pool_item:815/is_shop_pool:819/shop_bp_shelf:823/shop_bp_visit_buys:827。
|
||||
2. 零外部调用方死壳 2 枚:`_spend_discounted`(全库仅 tree_rules_v11_test.gd:6 注释提及)、`pool_stock`(外部同名调用全为 CurioDeck.pool_stock,如 adventure_feats_test.gd:545——同名不同件)。
|
||||
|
||||
外部调用面(产品码与 sim):
|
||||
@@ -48,7 +48,7 @@
|
||||
|
||||
登记与账面:
|
||||
|
||||
9. 架构:architecture.md:109(委托承载句+公开面格)/:152(直连原则);`design/` 全目录仅此一处委托登记(grep 考证 2026-10-29)。
|
||||
9. 架构:architecture.md:109(委托承载句+公开面格)/:154(直连原则);`design/` 全目录仅此一处委托登记(grep 考证 2026-10-29)。
|
||||
10. gdstyle 基线:tools/gdstyle_baseline.txt:11–13——level_runner 三键 max-class-variables=30/max-public-methods=50/max-returns|_enter_node=7。
|
||||
11. 能力清单:game/tests/README.md 旅程段四「GP 钱包/escrow/商店收口/共享池」行真实入口列引用委托名——已随本卡写作更新为直连形态(写卡段义务,实现批禁写该文件)。
|
||||
12. shop_session.gd:4 头注「公开面由 LevelRunner 同签名委托承载」句随拆除失效(商店件唯一注释级 diff,见契约 3)。
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
## 5. 范围边界
|
||||
|
||||
做:壳块与死壳删除;`_shop`→`shop` 公开化(含内部引用点);产品码/sim/测试调用点改址;注释同步六处(shop_session.gd:4、level_runner.gd:722–724 区块句、level_autoplay.gd:335、shop_overlay_view.gd:88/152、tree_rules_v11_test.gd:6);level_runner 头注涉委托表述随批核查同步。
|
||||
做:壳块与死壳删除;`_shop`→`shop` 公开化(含内部引用点);产品码/sim/测试调用点改址;注释同步六处(shop_session.gd:4、level_runner.gd:723–725 区块涉委托两句〔删 :724–725、留 :723 节头〕、level_autoplay.gd:335、shop_overlay_view.gd:88/152、tree_rules_v11_test.gd:6);level_runner 头注涉委托表述随批核查同步。
|
||||
|
||||
不做(去向):
|
||||
|
||||
@@ -136,7 +136,7 @@ game/tests/unit/core/tree_rules_v11_test.gd 头注同步 1 处【非行
|
||||
|
||||
- 取用:T0 全调用点直连形态在位。
|
||||
- 产出:终态 level_runner(壳归零);T2 的闸与审计对象。
|
||||
- [ ] 删除 level_runner.gd:722–724 区块注释涉委托句+:725 契约注释(保留「商店房兑付」节头与件注入说明)+:751–828 十九个委托全量(含死壳 `_spend_discounted`:772/`pool_stock`:787)
|
||||
- [ ] 删除 level_runner.gd:723–725 区块注释中涉委托与白盒两句(:724–725;保留 :723「商店房兑付」节头与 :727 件注入说明)+:751–828 十九个委托全量(含死壳 `_spend_discounted`:772/`pool_stock`:787)
|
||||
- [ ] shop_session.gd:4 头注委托承载句更新(「外部调用面=调用方经宿主公开成员 `shop` 直连」表述)
|
||||
- [ ] 验证:`python tools/run_smoke.py` 绿+全单元套件绿(壳删后绿=T0 改址无遗漏的编译级证明)
|
||||
- [ ] 残留扫描:grep 19 个方法名于 `game/`(排除 shop_session.gd 本体定义、level_runner.gd 内部 `shop.` 使用点、跨类同名方法——BattleOrchestrator.player_request_refresh 与 CurioDeck.pool_stock 按现状事实 5 清单判接收方类归属)——产品码与测试面零命中,输出留实现报告
|
||||
@@ -160,7 +160,7 @@ game/tests/unit/core/tree_rules_v11_test.gd 头注同步 1 处【非行
|
||||
| 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点) | 层级 | 真实入口 | 判据绑定面 | 能力行 |
|
||||
|---|---|---|---|---|---|---|
|
||||
| R1 调用面直连改址(非行为改动——调用目标/实参/返回/副作用逐项同前,仅取件路径文本变化) | §9 结构图产品码 6 件+sim 1 件+测试 7 件全部调用点 | 既有套件回归两轮全绿:T0 中间态轮+T1 壳删后轮(level_shop_economy/hero_ledger/adventure_feats/pool_case_d/treasure_effects/curio_refresh_paid/meta_progression_forge 全套+冒烟) | 单元+接口 | 各套件既有真实入口(直构 LevelRunner/AdventureRunner 链) | 既有断言逐位不变(行为零改动正向证据)+壳删后编译通过(改址无遗漏) | 既有:GP 钱包/escrow/商店收口/共享池;既有:奖励三选一候选/刷新付费/呈现 |
|
||||
| R2 壳块拆除(非行为改动——纯转传方法与契约注释删除,行为承载在 ShopSession 不变) | level_runner.gd:722–724 句+:725+:751–828(含死壳 `_spend_discounted`:772/`pool_stock`:787) | 残留扫描零命中(T1 静态步)+T1 套件绿 | 静态+单元 | grep 全仓(19 方法名清单固定)+套件真实入口 | 扫描面>0 前置(grep 命令对 19 名单非空可执行)+壳删后零引用可编译;命中行按接收方类归属判别(现状事实 5 跨类同名清单) | 既有:GP 钱包/escrow/商店收口/共享池 |
|
||||
| R2 壳块拆除(非行为改动——纯转传方法与契约注释删除,行为承载在 ShopSession 不变) | level_runner.gd:723–725 区块涉委托两句(:724–725)+:751–828(含死壳 `_spend_discounted`:772/`pool_stock`:787) | 残留扫描零命中(T1 静态步)+T1 套件绿 | 静态+单元 | grep 全仓(19 方法名清单固定)+套件真实入口 | 扫描面>0 前置(grep 命令对 19 名单非空可执行)+壳删后零引用可编译;命中行按接收方类归属判别(现状事实 5 跨类同名清单) | 既有:GP 钱包/escrow/商店收口/共享池 |
|
||||
| R3 宿主成员公开化(非行为改动——私有 `_shop` 更名公开 `shop`,装配与读写路径不变) | level_runner.gd:44+内部引用 :99/:102/:104/:305–306/:506–507/:704/:729 | 随 R1 两轮套件绿 | 单元 | 套件真实入口 | 同 R1(内部使用点行为不变) | 既有:GP 钱包/escrow/商店收口/共享池 |
|
||||
| R4 注释同步六处(非行为改动——注释文本,无运行时可观测面) | shop_session.gd:4/level_runner.gd:722–724/level_autoplay.gd:335/shop_overlay_view.gd:88/152/tree_rules_v11_test.gd:6 | 随批代码域闸绿(静态扫描覆盖文件头纪律面) | 静态 | —(静态判据) | 观测面局限申报:注释无运行时提交面,判据=静态扫描+评审注记 | 既有:GP 钱包/escrow/商店收口/共享池 |
|
||||
|
||||
|
||||
Reference in new issue
Block a user