Skip to content

Fix: 战后基质错误essence#1554

Merged
MistEO merged 19 commits intov2from
fix/afterBattleEssence
Mar 23, 2026
Merged

Fix: 战后基质错误essence#1554
MistEO merged 19 commits intov2from
fix/afterBattleEssence

Conversation

@Joe-Bao
Copy link
Copy Markdown
Contributor

@Joe-Bao Joe-Bao commented Mar 23, 2026

#1543
1.更加稳定的roi方式
2.介入全球化
3.重构集成减少代码
4.干掉了不必要的log
5.修复了不选弃置就会自动退出的bug
6.还没想起来反正肯定还有
7.修复了interface相关没写全球化i18的问题

Summary by Sourcery

重构 EssenceFilter 引擎初始化和决策流程,以复用共享逻辑、集中化 UI 报告,并改进本地化和数据目录处理。

New Features:

  • 添加统一的 EssenceFilter 集成层,用于构建视图模型、报告 UI 消息,并在不同流水线中驱动决策流程。
  • 引入共享的技能决策例程,在背包内和战后精华评估中复用。
  • 提供 matchapi.FormatMessage 辅助方法和内嵌目录,用于独立于引擎实例的本地化焦点消息。

Bug Fixes:

  • 修复战后精华决策处理,使锁定/跳过/丢弃行为与主 EssenceFilter 逻辑保持一致,并避免在未选择丢弃时出现意外退出。
  • 改进在匹配选项或引擎加载失败时的错误报告,使问题能呈现到焦点 UI,而不是静默失败。
  • 确保能够检测并报告无效或不完整的 EssenceFilter 数据目录,而不是在不经意间使用它们。

Enhancements:

  • 复用共享的 EnsureMatchEngine 辅助方法,以集中化 EssenceFilter 的匹配引擎创建、选项加载和状态接线。
  • 通过构建专用视图模型并将 HTML/表格生成移入可复用的报告辅助方法,简化 EssenceFilter 初始化。
  • 使用本地化的焦点消息改进库存数量、数据版本和进度报告,包括行遍历过程和最终汇总。
  • 减少低价值日志,例如不再需要的详细技能池转储和过滤技能统计。
  • 更新默认的 EssenceFilter 数据目录解析为使用 data/EssenceFilter,并在无法找到路径时提供更清晰的错误信息。
Original summary in English

Summary by Sourcery

Refactor EssenceFilter engine initialization and decision flows to reuse shared logic, centralize UI reporting, and improve localization and data directory handling.

New Features:

  • Add a unified EssenceFilter integration layer to build view models, report UI messages, and drive decision flows across different pipelines.
  • Introduce a shared skill decision routine that is reused for both in-inventory and after-battle essence evaluation.
  • Provide a matchapi.FormatMessage helper and embedded catalog for localized focus messages independent of an engine instance.

Bug Fixes:

  • Fix after-battle essence decision handling so that lock/skip/discard behavior is consistent with main EssenceFilter logic and avoids unintended exits when discard is not selected.
  • Improve error reporting when match options or engines fail to load so issues are surfaced to the focus UI instead of silently failing.
  • Ensure invalid or incomplete EssenceFilter data directories are detected and reported instead of being used inadvertently.

Enhancements:

  • Reuse a shared EnsureMatchEngine helper to centralize match engine creation, option loading, and state wiring for EssenceFilter.
  • Simplify EssenceFilter initialization by building a dedicated view model and moving HTML/table generation into reusable reporting helpers.
  • Improve inventory count, data version, and progress reporting with localized focus messages for row traversal and final summaries.
  • Reduce low-signal logging such as detailed skill pool dumps and filtered skill stats that are no longer needed.
  • Update default EssenceFilter data directory resolution to use data/EssenceFilter and clarify error messages when the path cannot be found.

Summary by Sourcery

重构 EssenceFilter 的初始化和决策处理逻辑,在共享背包和战后流程中的引擎设置与 UI 逻辑的同时,改进本地化能力和数据目录解析。

New Features:

  • 引入共享的 EssenceFilter 集成层,用于集中管理匹配引擎创建、决策路由以及 UI 上报。
  • 通过内嵌的 i18n 目录和格式化辅助工具,为焦点提示消息添加与引擎无关的本地化支持。

Bug Fixes:

  • 将战后精华锁定/跳过/丢弃决策与主 EssenceFilter 逻辑对齐,防止在未选择丢弃时发生非预期退出。
  • 将缺失的运行状态、匹配引擎以及匹配失败情况上报到焦点 UI,而不是静默失败。
  • 校验 EssenceFilter 数据目录和环境重写配置,在必需文件缺失时给出清晰的错误提示。

Enhancements:

  • 通过构建专用视图模型和可复用的武器与技能列表上报辅助工具,简化 EssenceFilter 初始化。
  • 使用本地化的焦点提示消息改进背包数量、数据版本以及行遍历进度的上报。
  • 通过移除详细技能池与过滤后技能统计输出,减少低价值日志。
  • 更新默认的 EssenceFilter 数据目录发现策略,改为使用 data/EssenceFilter 布局,并在解析失败时提供更清晰的错误信息。
Original summary in English

Summary by Sourcery

Refactor EssenceFilter initialization and decision handling to share engine setup and UI logic across inventory and after-battle flows while improving localization and data directory resolution.

New Features:

  • Introduce a shared EssenceFilter integration layer to centralize match engine creation, decision routing, and UI reporting.
  • Add engine-independent localization support for focus messages via an embedded i18n catalog and formatting helper.

Bug Fixes:

  • Align after-battle essence lock/skip/discard decisions with the main EssenceFilter logic to prevent unintended exits when discard is not selected.
  • Report missing run state or match engine and match failures to the focus UI instead of failing silently.
  • Validate EssenceFilter data directories and environment overrides, surfacing clear errors when required files are missing.

Enhancements:

  • Simplify EssenceFilter init by building a dedicated view model and reusable helpers for weapon and skill list reporting.
  • Improve inventory count, data version, and row traversal progress reporting using localized focus messages.
  • Reduce low-value logging by removing detailed skill pool and filtered skill statistics output.
  • Update default EssenceFilter data directory discovery to use a data/EssenceFilter layout and provide clearer error messages when resolution fails.

@Joe-Bao Joe-Bao marked this pull request as ready for review March 23, 2026 16:14
Copilot AI review requested due to automatic review settings March 23, 2026 16:14
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了两个问题,并给出了一些整体性的反馈:

  • buildInitViewModel 中,在执行 st == nil 判断之前就访问了 st.TargetSkillCombinations,如果函数在 RunState 为 nil 的情况下被调用,就会触发 panic;请把 nil 检查移动到函数最上方,在任何字段访问之前进行。
  • runUnifiedSkillDecision 假定 engine 一定非 nil,并且无条件调用 engine.MatchOCR;建议要么显式声明这个前置条件(例如在不满足时提前返回并上报一个 focus 错误),要么在这里对 nil engine 做保护,以避免未来在新的调用点中以 nil engine 调用该函数时出现潜在的 panic。
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `buildInitViewModel`, `st.TargetSkillCombinations` is accessed before the `st == nil` guard, which will panic if the function is called with a nil `RunState`; move the nil check to the very top before any field access.
- `runUnifiedSkillDecision` assumes `engine` is non-nil and calls `engine.MatchOCR` unconditionally; consider either asserting this precondition explicitly (e.g., early return with a focus error) or guarding against a nil engine to avoid potential panics if it is ever invoked with a nil engine in new call sites.

## Individual Comments

### Comment 1
<location path="agent/go-service/essencefilter/integration.go" line_range="104-105" />
<code_context>
+	SlotSkills      [3][]string
+}
+
+func buildInitViewModel(st *RunState) InitViewModel {
+	vm := InitViewModel{
+		FilteredWeapons: make([]matchapi.WeaponData, 0, len(st.TargetSkillCombinations)),
+	}
</code_context>
<issue_to_address>
**issue (bug_risk):** Potential nil pointer dereference when `st` is nil in `buildInitViewModel`

`len(st.TargetSkillCombinations)` is evaluated before checking `st == nil`, so this will panic if `buildInitViewModel` is ever called with a nil `RunState`. Please guard `st == nil` first and only use `st.TargetSkillCombinations` when `st` is confirmed non-nil.
</issue_to_address>

### Comment 2
<location path="agent/go-service/essencefilter/actionsAfterBattle.go" line_range="27" />
<code_context>
 	}
-	skills := []string{ocr.Skills[0], ocr.Skills[1], ocr.Skills[2]}

 	if st.MatchEngine == nil {
+		reportFocusByKey(ctx, st, "focus.error.no_match_engine")
 		return false
</code_context>
<issue_to_address>
**question:** After-battle decision now hard-depends on `st.MatchEngine` and no longer falls back to defaults

This now errors when `st.MatchEngine` is nil and assumes `PipelineOpts` was set up earlier, instead of reconstructing options or falling back to `defaultEssenceFilterOptions()`. That tightens the pipeline contract: any flow calling `EssenceFilterAfterBattleSkillDecisionAction` without a prior init that sets `st.MatchEngine` will fail instead of using defaults. If that behavior is desired, please verify all after-battle pipeline JSONs always run the init step first; otherwise consider calling `EnsureMatchEngine` here or restoring a minimal fallback for missing state.
</issue_to_address>

Sourcery 对开源项目免费——如果你觉得我们的评审有帮助,欢迎分享 ✨
帮我变得更有用!请对每条评论点 👍 或 👎,我会根据这些反馈改进后续的评审。
Original comment in English

Hey - I've found 2 issues, and left some high level feedback:

  • In buildInitViewModel, st.TargetSkillCombinations is accessed before the st == nil guard, which will panic if the function is called with a nil RunState; move the nil check to the very top before any field access.
  • runUnifiedSkillDecision assumes engine is non-nil and calls engine.MatchOCR unconditionally; consider either asserting this precondition explicitly (e.g., early return with a focus error) or guarding against a nil engine to avoid potential panics if it is ever invoked with a nil engine in new call sites.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `buildInitViewModel`, `st.TargetSkillCombinations` is accessed before the `st == nil` guard, which will panic if the function is called with a nil `RunState`; move the nil check to the very top before any field access.
- `runUnifiedSkillDecision` assumes `engine` is non-nil and calls `engine.MatchOCR` unconditionally; consider either asserting this precondition explicitly (e.g., early return with a focus error) or guarding against a nil engine to avoid potential panics if it is ever invoked with a nil engine in new call sites.

## Individual Comments

### Comment 1
<location path="agent/go-service/essencefilter/integration.go" line_range="104-105" />
<code_context>
+	SlotSkills      [3][]string
+}
+
+func buildInitViewModel(st *RunState) InitViewModel {
+	vm := InitViewModel{
+		FilteredWeapons: make([]matchapi.WeaponData, 0, len(st.TargetSkillCombinations)),
+	}
</code_context>
<issue_to_address>
**issue (bug_risk):** Potential nil pointer dereference when `st` is nil in `buildInitViewModel`

`len(st.TargetSkillCombinations)` is evaluated before checking `st == nil`, so this will panic if `buildInitViewModel` is ever called with a nil `RunState`. Please guard `st == nil` first and only use `st.TargetSkillCombinations` when `st` is confirmed non-nil.
</issue_to_address>

### Comment 2
<location path="agent/go-service/essencefilter/actionsAfterBattle.go" line_range="27" />
<code_context>
 	}
-	skills := []string{ocr.Skills[0], ocr.Skills[1], ocr.Skills[2]}

 	if st.MatchEngine == nil {
+		reportFocusByKey(ctx, st, "focus.error.no_match_engine")
 		return false
</code_context>
<issue_to_address>
**question:** After-battle decision now hard-depends on `st.MatchEngine` and no longer falls back to defaults

This now errors when `st.MatchEngine` is nil and assumes `PipelineOpts` was set up earlier, instead of reconstructing options or falling back to `defaultEssenceFilterOptions()`. That tightens the pipeline contract: any flow calling `EssenceFilterAfterBattleSkillDecisionAction` without a prior init that sets `st.MatchEngine` will fail instead of using defaults. If that behavior is desired, please verify all after-battle pipeline JSONs always run the init step first; otherwise consider calling `EnsureMatchEngine` here or restoring a minimal fallback for missing state.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +104 to +105
func buildInitViewModel(st *RunState) InitViewModel {
vm := InitViewModel{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk):buildInitViewModel 中的 st 为 nil 时可能发生空指针解引用

len(st.TargetSkillCombinations) 会在检查 st == nil 之前被求值,因此如果在 RunState 为 nil 的情况下调用 buildInitViewModel,这里会触发 panic。请先对 st == nil 做保护,只在确定 st 非 nil 时再访问 st.TargetSkillCombinations

Original comment in English

issue (bug_risk): Potential nil pointer dereference when st is nil in buildInitViewModel

len(st.TargetSkillCombinations) is evaluated before checking st == nil, so this will panic if buildInitViewModel is ever called with a nil RunState. Please guard st == nil first and only use st.TargetSkillCombinations when st is confirmed non-nil.

ctx.OverrideNext(arg.CurrentTaskName, []maa.NextItem{{Name: "EssenceFilterAfterBattleDiscardItemLog"}})
} else {
ctx.OverrideNext(arg.CurrentTaskName, []maa.NextItem{{Name: "EssenceFilterAfterBattleCloseDetail"}})
if st.MatchEngine == nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: 战后决策现在对 st.MatchEngine 形成硬依赖,不再回退到默认值

当前实现会在 st.MatchEngine 为 nil 时直接报错,并假设 PipelineOpts 之前已经被正确设置,而不是在这里重建选项或回退到 defaultEssenceFilterOptions()。这会收紧整个 pipeline 的约束:任何在未经过设置 st.MatchEngine 的初始化步骤就调用 EssenceFilterAfterBattleSkillDecisionAction 的流程都会失败,而不会使用默认配置。如果这是预期行为,请确认所有战后 pipeline 的 JSON 都会先执行 init 步骤;否则建议在此调用 EnsureMatchEngine,或者为缺失状态恢复一个最小的兜底逻辑。

Original comment in English

question: After-battle decision now hard-depends on st.MatchEngine and no longer falls back to defaults

This now errors when st.MatchEngine is nil and assumes PipelineOpts was set up earlier, instead of reconstructing options or falling back to defaultEssenceFilterOptions(). That tightens the pipeline contract: any flow calling EssenceFilterAfterBattleSkillDecisionAction without a prior init that sets st.MatchEngine will fail instead of using defaults. If that behavior is desired, please verify all after-battle pipeline JSONs always run the init step first; otherwise consider calling EnsureMatchEngine here or restoring a minimal fallback for missing state.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 围绕 Issue #1543 的“战后基质筛选卡住/无法停止任务”问题,对战后基质筛选的 pipeline 与 go-service EssenceFilter 逻辑进行了稳定性改造、i18n 接入与流程重构,以统一战利品/背包两条链路的决策与 UI 汇报方式,并减少噪声日志。

Changes:

  • 调整战后筛选 pipeline:新增基于颜色定位黄点的级联 ROI、拆分 CloseDetail 的 Skip/JumBack 路径,并引入 wait_freezes 等待机制。
  • go-service EssenceFilter 重构:新增统一集成层(integration.go),复用初始化/决策/汇报逻辑,移除部分统计/技能池日志与状态字段。
  • i18n 完善:AutoEssence 焦点文案改为 key,并补齐多语言 locale;matchapi 增补多条聚焦/错误/进度文案与 FormatMessage 辅助。

Reviewed changes

Copilot reviewed 18 out of 19 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
assets/resource/pipeline/EssenceFilter/EssenceFilterAfterBattleLockDiscard.json 调整战后锁定/弃置/关闭详情分支,并引入 wait_freezes、JumpBack 专用节点
assets/resource/pipeline/EssenceFilter/EssenceFilterAfterBattleCheckItem.json 新增颜色匹配黄点定位的级联节点,重设 OCR ROI 以提高稳定性
assets/resource/pipeline/AutoEssence/EssenceFilterAfterBattle.json 焦点文案改为 i18n key,并更新部分等待参数
assets/resource/image/EssenceFilter/EssenceTabChoose.png 新增/更新图像资源
assets/misc/locales/{zh_cn,zh_tw,en_us,ja_jp,ko_kr}.json 新增 AutoEssence 战后筛选相关焦点文案翻译
agent/go-service/essencefilter/ui.go 移除低价值日志输出函数
agent/go-service/essencefilter/state.go 删除与日志统计相关的 RunState 字段与 Reset 逻辑
agent/go-service/essencefilter/recognitionAfterBattle.go 调整战后 nth 识别逻辑的日志/注释
agent/go-service/essencefilter/matchapi/loader.go 修改默认数据目录解析逻辑与错误信息
agent/go-service/essencefilter/matchapi/i18n_messages.json 大幅补充聚焦/错误/进度类 i18n 文案
agent/go-service/essencefilter/matchapi/i18n.go 新增 FormatMessage,使用嵌入式 i18n catalog
agent/go-service/essencefilter/matchapi/engine.go 更新 NewDefaultEngine 注释以匹配新的默认数据路径描述
agent/go-service/essencefilter/integration.go 新增统一集成层:汇报、初始化视图模型、统一技能决策、EnsureMatchEngine

Comment on lines +104 to +110
func buildInitViewModel(st *RunState) InitViewModel {
vm := InitViewModel{
FilteredWeapons: make([]matchapi.WeaponData, 0, len(st.TargetSkillCombinations)),
}
if st == nil {
return vm
}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buildInitViewModel 在判断 st == nil 之前就执行了 len(st.TargetSkillCombinations) 来初始化 slice 容量;如果未来有调用方传入 nil(函数签名也允许),这里会直接 panic。建议先做 nil 判断,再决定容量(例如 cap=0 或基于 len 的分支)。

Copilot uses AI. Check for mistakes.
@MistEO MistEO merged commit 1ac3601 into v2 Mar 23, 2026
11 checks passed
@MistEO MistEO deleted the fix/afterBattleEssence branch March 23, 2026 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants