Skip to content

feat(MAA): 从模拟器层面接管明日方舟游戏更新 - #418

Open
1w1w11w1 wants to merge 1 commit into
AUTO-MAS-Project:devfrom
1w1w11w1:feat/maa-game-update
Open

feat(MAA): 从模拟器层面接管明日方舟游戏更新#418
1w1w11w1 wants to merge 1 commit into
AUTO-MAS-Project:devfrom
1w1w11w1:feat/maa-game-update

Conversation

@1w1w11w1

@1w1w11w1 1w1w11w1 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

摘要

  • MAA 自带开始唤醒任务会原地轮询等待游戏内资源热更新(GameStartUpdateOCR / GameStartCheckResourceOCR 自循环),但对客户端 APK 版本落后导致的强制更新门没有任何任务,只会一直卡到超时并按重试次数反复失败。本 PR 只补 MAA 缺失的这一层,不重复实现热更新。
  • 启动 MAA 前比对服务端与模拟器内的客户端版本:官服可自动下载安装包并经 adb 安装,安装后复检版本;其余服务器无可靠安装包来源,改为快速失败并推送可执行提示,避免静默卡到超时。
  • 用服务端 resVersion 识别待下载的资源热更新,仅在该次运行把超时放宽到「游戏更新超时限制」,代理成功后记录版本供下次比对,避免把正常大版本热更误判成卡死。
  • 新增 3 个脚本级配置项(默认全部关闭,不改变现有用户行为):启动前检查游戏更新、自动安装游戏安装包(仅官服)、游戏更新超时限制。

实现要点

  • DeviceBase.get_adb_path() 为非抽象方法、默认返回 None(回退系统 adb),MuMu 与雷电各自覆写返回自带 adb.exe,不破坏现有实现。
  • 版本接口 ak-conf.hypergryph.com/config/prod/{official,b}/Android/version 实测可用;外服与台服未找到稳定公开接口,不在映射表中的服务器直接跳过检查。
  • 服务器是每用户字段,包名与版本按用户运行时解析,不按脚本一次性解析。
  • 检查自身异常、读不到已安装版本、取不到 adb 地址三种情况一律不阻断代理,交回 MAA 原有流程判定。
  • 安装包约 2 GB:下载前校验磁盘余量,落盘走 .downloading 临时文件,体积明显偏小判定为未取到真实安装包,无论成败都清理不长期占用磁盘。

测试

  • python -m pytest tests/ -q:206 passed / 7 failed。7 项失败在未改动的 origin/dev 上完全一致(199 passed / 同样 7 failed),与本 PR 无关;新增 7 项测试全部通过。
  • 新增 tests/task/test_maa_game_update.py 覆盖版本比较(含段数不等、无法解析时不下判断)与编排层各分支判定。

待办与已知限制

  • 后端 schema 有变更,需在后端运行时执行 yarn openapi 重新生成前端 API 代码frontend/src/api/models/MaaConfig_Run.tsMaaUserConfig_Data.ts)。按规范未手改生成文件;updateScript 入参为 any,不阻塞当前功能。
  • 仅官服支持自动安装,B 服与外服无可验证的安装包直链,当前明确提示手动更新。
  • APK 下载与 adb 安装链路未做端到端实测 —— 手上没有版本落后的客户端环境,无法构造真实的强制更新门。版本比对、编排分支判定、跳过与快速失败路径已由单测覆盖。
  • 资源热更新期间 MAA 是否输出内容变化的日志行未实测(LogMonitor.update_latest_timestamp 仅在日志行内容变化时推进 latest_time),放宽超时是保守兜底而非依赖该行为。

Sourcery 摘要

接管明日方舟客户端版本检查与官服自动更新,并为资源热更新放宽本次 MAA 代理超时。

新功能:

  • 添加可选的明日方舟客户端版本检查功能,支持下载官服 APK 并通过 ADB 安装。
  • 添加可配置的游戏更新超时处理,以及针对长时间游戏内更新的资源版本跟踪。
  • 在 MAA 脚本配置界面中提供游戏更新检查、APK 自动安装和超时设置。

错误修复:

  • 防止客户端版本过旧时,MAA 在强制更新界面反复卡住。
  • 避免将预期的资源热更新延迟误判为 MAA 任务超时。

改进:

  • 支持使用模拟器专用的 ADB 可执行文件,并在必要时回退到系统 ADB。
  • 针对不受支持的服务器或自动更新失败的情况,提供用户通知和可执行的手动更新指引。

测试:

  • 增加对客户端版本比较和游戏更新编排分支的测试覆盖。
Original summary in English

Summary by Sourcery

接管明日方舟客户端版本检查与官服自动更新,并为资源热更新放宽本次 MAA 代理超时。

New Features:

  • Add optional pre-launch Arknights client version checks with official-server APK download and ADB installation support.
  • Add configurable game-update timeout handling and resource-version tracking for prolonged in-game updates.
  • Expose game-update checking, automatic APK installation, and timeout settings in the MAA script configuration UI.

Bug Fixes:

  • Prevent outdated client versions from repeatedly stalling MAA at the forced-update screen.
  • Avoid treating expected resource hot-update delays as MAA task timeouts.

Enhancements:

  • Support emulator-specific ADB executables with fallback to the system ADB.
  • Provide user notifications and actionable manual-update failures for unsupported servers or unsuccessful automatic updates.

Tests:

  • Add coverage for client-version comparison and game-update orchestration branches.

MAA 自带的开始唤醒任务会原地轮询等待游戏内资源热更新,但对客户端 APK 版本
落后导致的强制更新门没有任何任务,只会一直卡到超时并按重试次数反复失败,
无人值守场景下这段时间是纯浪费。

补足 MAA 缺失的这一层:启动 MAA 前比对服务端与模拟器内的客户端版本,官服
可自动下载安装包并经 adb 安装;其余服务器无可靠安装包来源,改为快速失败并
给出可执行提示。同时用服务端 resVersion 识别待下载的资源热更新,在那一次
运行放宽超时,避免把正常更新误判成卡死。
@sourcery-ai

sourcery-ai Bot commented Aug 25, 2026

Copy link
Copy Markdown

审查者指南

本 PR 在不重复实现 MAA 内置资源热更新的前提下,在启动前增加可选的客户端版本检查和官服 APK 自动更新链路,并通过 resVersion 记录识别资源热更新、动态放宽单次代理超时;同时补充模拟器 adb 路径适配、脚本配置、前端设置项和分支测试。

启动前游戏版本检查与更新时序图

sequenceDiagram
    participant AutoProxy
    participant GameUpdate as ensure_game_updated
    participant VersionAPI
    participant Emulator
    participant APK as OfficialAPK
    participant ADB
    participant User

    AutoProxy->>GameUpdate: ensure_game_updated()
    GameUpdate->>VersionAPI: fetch_game_version()
    VersionAPI-->>GameUpdate: clientVersion, resVersion
    GameUpdate->>Emulator: get_installed_client_version()
    Emulator->>ADB: dumpsys package
    ADB-->>Emulator: installed version
    Emulator-->>GameUpdate: installed version
    alt client version is current
        GameUpdate-->>AutoProxy: UpToDate
    else Official and auto install enabled
        GameUpdate->>APK: download_official_apk()
        APK-->>GameUpdate: APK file
        GameUpdate->>ADB: install_apk()
        ADB-->>GameUpdate: Success
        GameUpdate->>Emulator: get_installed_client_version()
        Emulator-->>GameUpdate: updated version
        GameUpdate-->>AutoProxy: Updated
    else unsupported server or manual update required
        GameUpdate-->>AutoProxy: NeedManualUpdate
        AutoProxy->>User: push notification and stop retry
    end
Loading

资源热更新超时处理流程图

flowchart TD
    A[Start MAA run] --> B[ensure_game_updated]
    B --> C{resVersion differs from LastResVersion?}
    C -- No --> D[Use normal task timeout]
    C -- Yes --> E[Mark resource hot update pending]
    E --> F[Use max task timeout and GameUpdateTimeLimit]
    F --> G[MAA performs its built-in resource hot update]
    G --> H{Proxy succeeds?}
    H -- Yes --> I[Save pending resVersion as LastResVersion]
    H -- No --> J[Keep previous LastResVersion]
    D --> K[Run normal MAA flow]
    I --> K
    J --> K
Loading

文件级变更

变更 详情 文件
新增游戏客户端版本检查、官服 APK 自动下载、安装及安装后复检流程。
  • 通过服务端版本接口获取客户端与资源版本,并与模拟器内的应用包版本进行比较。
  • 针对官服且启用自动安装的场景下载 APK、校验磁盘空间和文件体积,通过模拟器专用或系统 adb 安装,并在失败或非官服时推送手动更新提示。
  • 检查异常、adb/已安装版本不可读或服务器无版本接口时跳过检查,交回 MAA 原有启动流程。
app/task/MAA/tools/game_update.py
app/task/MAA/AutoProxy.py
app/utils/constants.py
将资源热更新状态接入 MAA 代理编排和超时控制。
  • 按用户记录上次成功代理时的 resVersion,并在检测到变化时仅放宽本次运行的超时限制。
  • 客户端需要手动更新时终止当前模式重试,关闭模拟器,并通过 WebSocket、桌面通知和用户日志进行提示。
  • 代理成功后保存待处理的资源版本,避免下次重复放宽超时。
app/task/MAA/AutoProxy.py
app/models/config.py
app/models/schema.py
补充模拟器 adb 路径抽象及 MuMu、雷电实现。
  • 在基础设备接口中提供默认回退至系统 adb 的方法。
  • MuMu 与雷电优先返回各自安装目录中的 adb.exe。
app/models/emulator.py
app/utils/emulator/mumu.py
app/utils/emulator/ldplayer.py
增加脚本配置、前端编辑项和默认值。
  • 新增启动前检查、官服自动安装和游戏更新超时三个配置项,默认关闭或默认为 60 分钟。
  • 在 MAA 脚本编辑页面增加开关、超时输入,以及仅在启用检查时可用的联动控件。
  • 扩展前端脚本配置类型与后端 schema。
app/models/config.py
app/models/schema.py
frontend/src/types/script.ts
frontend/src/views/EditView/Script/MAAScriptEdit.vue
增加版本解析、更新编排分支及资源版本场景的单元测试。
  • 覆盖不同版本段数、版本无法解析、非官服、关闭自动安装、无法读取版本、缺少 adb 以及无版本接口等路径。
tests/task/test_maa_game_update.py

可能关联的 issue

  • #未提供:PR 实现了该 issue 中“自动更新游戏本体”需求的具体子范围:MAA 明日方舟客户端检查、下载、ADB 安装及热更新处理。
  • #:PR 直接实现了 issue 建议的版本检测、更新包自动下载、ADB 安装和更新后复检功能。

提示与命令

与 Sourcery 交互

  • 触发新的审查: 在 pull request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审查评论。
  • 从审查评论生成 GitHub issue: 回复审查评论,请 Sourcery 根据该评论创建 issue。你也可以回复 @sourcery-ai issue,从该评论创建 issue。
  • 生成 pull request 标题: 在 pull request 标题的任意位置写入 @sourcery-ai,即可随时生成标题。你也可以在 pull request 中评论 @sourcery-ai title,以随时生成或重新生成标题。
  • 生成 pull request 摘要: 在 pull request 正文中任意位置写入 @sourcery-ai summary,即可在指定位置随时生成 PR 摘要。你也可以在 pull request 中评论 @sourcery-ai summary,以随时生成或重新生成摘要。
  • 生成审查者指南: 在 pull request 中评论 @sourcery-ai guide,即可随时生成或重新生成审查者指南。
  • 解决所有 Sourcery 评论: 在 pull request 中评论 @sourcery-ai resolve,即可解决所有 Sourcery 评论。如果你已经处理完所有评论且不想再看到它们,这项功能会很有用。
  • 忽略所有 Sourcery 审查: 在 pull request 中评论 @sourcery-ai dismiss,即可忽略所有现有的 Sourcery 审查。如果你想从新的审查开始,这项功能尤其有用——别忘了评论 @sourcery-ai review 来触发新的审查!

自定义使用体验

访问你的控制面板以:

  • 启用或禁用审查功能,例如 Sourcery 生成的 pull request 摘要、审查者指南等。
  • 更改审查语言。
  • 添加、删除或编辑自定义审查说明。
  • 调整其他审查设置。

获取帮助

Original review guide in English

Reviewer's Guide

本 PR 在不重复实现 MAA 内置资源热更新的前提下,在启动前增加可选的客户端版本检查和官服 APK 自动更新链路,并通过 resVersion 记录识别资源热更新、动态放宽单次代理超时;同时补充模拟器 adb 路径适配、脚本配置、前端设置项和分支测试。

Sequence diagram for pre-launch game version check and update

sequenceDiagram
    participant AutoProxy
    participant GameUpdate as ensure_game_updated
    participant VersionAPI
    participant Emulator
    participant APK as OfficialAPK
    participant ADB
    participant User

    AutoProxy->>GameUpdate: ensure_game_updated()
    GameUpdate->>VersionAPI: fetch_game_version()
    VersionAPI-->>GameUpdate: clientVersion, resVersion
    GameUpdate->>Emulator: get_installed_client_version()
    Emulator->>ADB: dumpsys package
    ADB-->>Emulator: installed version
    Emulator-->>GameUpdate: installed version
    alt client version is current
        GameUpdate-->>AutoProxy: UpToDate
    else Official and auto install enabled
        GameUpdate->>APK: download_official_apk()
        APK-->>GameUpdate: APK file
        GameUpdate->>ADB: install_apk()
        ADB-->>GameUpdate: Success
        GameUpdate->>Emulator: get_installed_client_version()
        Emulator-->>GameUpdate: updated version
        GameUpdate-->>AutoProxy: Updated
    else unsupported server or manual update required
        GameUpdate-->>AutoProxy: NeedManualUpdate
        AutoProxy->>User: push notification and stop retry
    end
Loading

Flow diagram for resource hot-update timeout handling

flowchart TD
    A[Start MAA run] --> B[ensure_game_updated]
    B --> C{resVersion differs from LastResVersion?}
    C -- No --> D[Use normal task timeout]
    C -- Yes --> E[Mark resource hot update pending]
    E --> F[Use max task timeout and GameUpdateTimeLimit]
    F --> G[MAA performs its built-in resource hot update]
    G --> H{Proxy succeeds?}
    H -- Yes --> I[Save pending resVersion as LastResVersion]
    H -- No --> J[Keep previous LastResVersion]
    D --> K[Run normal MAA flow]
    I --> K
    J --> K
Loading

File-Level Changes

Change Details Files
新增游戏客户端版本检查、官服 APK 自动下载安装及安装后复检流程。
  • 通过服务端版本接口获取客户端与资源版本,并与模拟器内包版本比较。
  • 对官服且启用自动安装的场景下载 APK、校验磁盘空间和文件体积、通过模拟器专用或系统 adb 安装,并在失败或非官服时推送手动更新提示。
  • 检查异常、adb/已安装版本不可读或服务器无接口时跳过检查,交回 MAA 原有启动流程。
app/task/MAA/tools/game_update.py
app/task/MAA/AutoProxy.py
app/utils/constants.py
将资源热更新状态接入 MAA 代理编排和超时控制。
  • 按用户记录上次成功代理时的 resVersion,并在检测到变化时仅放宽本次运行的超时限制。
  • 客户端需要手动更新时终止当前模式重试,关闭模拟器并通过 WebSocket、桌面通知和用户日志提示。
  • 代理成功后保存待处理资源版本,避免下次重复放宽超时。
app/task/MAA/AutoProxy.py
app/models/config.py
app/models/schema.py
补充模拟器 adb 路径抽象及 MuMu、雷电实现。
  • 在基础设备接口提供默认回退系统 adb 的方法。
  • MuMu 与雷电优先返回各自安装目录中的 adb.exe。
app/models/emulator.py
app/utils/emulator/mumu.py
app/utils/emulator/ldplayer.py
增加脚本配置、前端编辑项和默认值。
  • 新增启动前检查、官服自动安装和游戏更新超时三个默认关闭/默认 60 分钟的配置。
  • 在 MAA 脚本编辑页面增加开关、超时输入及仅在启用检查时可用的联动控件。
  • 扩展前端脚本配置类型与后端 schema。
app/models/config.py
app/models/schema.py
frontend/src/types/script.ts
frontend/src/views/EditView/Script/MAAScriptEdit.vue
增加版本解析、更新编排分支及资源版本场景的单元测试。
  • 覆盖不同版本段数、无法解析版本、非官服、关闭自动安装、无法读取版本、缺少 adb 和无版本接口等路径。
tests/task/test_maa_game_update.py

Possibly linked issues

  • #未提供: PR实现了该 issue 自动更新游戏本体需求的具体子范围:MAA 明日方舟客户端检查、下载、ADB安装及热更新处理。
  • #: PR直接实现了issue建议的版本检测、更新包自动下载、ADB安装和更新后复检功能。

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

嘿——我发现了 1 个问题

给 AI 代理的提示
请处理此次代码审查中的评论:

## 个别评论

### 评论 1
<location path="app/task/MAA/tools/game_update.py" line_range="221-225" />
<code_context>
+        async def report(text: str) -> None:
+            self.script_info.log = text
+
+        try:
+            result = await ensure_game_updated(
+                adb_path=self.emulator_manager.get_adb_path(),
</code_context>
<issue_to_address>
**issue (bug_risk):** 配置的 `time_limit` 从未应用于 APK 下载:`download_official_apk` 使用固定的 60 秒 HTTP 超时,而调用方调用它时没有设置任何截止时间。一个持续产生下载进度的 2 GB 下载可能无限期运行,因此 `GameUpdateTimeLimit` 并未像其配置和文档字符串所声称的那样限制下载时间。

**触发条件:** CDN 下载速度缓慢或停滞,但产生数据的频率仍高于 HTTP 非活动超时时间。

**建议修复:** 将配置的截止时间传入 `download_official_apk`,并在完整下载过程外层强制执行该截止时间,例如使用总体的 `asyncio.timeout(time_limit * 60)`,或采用等效的总时间限制。
</issue_to_address>

Sourcery 评估

需要人工审查。 首先需要处理 1 个发现的问题;此外,启用该功能后,它会从外部端点下载 APK,并通过 ADB 安装该 APK。因此,错误的版本响应、重定向或软件包可能会永久修改模拟器,而仅回滚此 PR 并不能撤销该安装。其他方面,存储的资源版本和超时变更均处于受控范围内,并且可以在后续运行中修正。

阻塞性发现:app/task/MAA/tools/game_update.py:225


Sourcery 对开源项目免费——如果您喜欢我们的审查,请考虑分享给他人 ✨
请帮助我变得更有用!请在每条评论上点击 👍 或 👎,我会利用这些反馈来改进审查结果。
Original comment in English

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="app/task/MAA/tools/game_update.py" line_range="221-225" />
<code_context>
+        async def report(text: str) -> None:
+            self.script_info.log = text
+
+        try:
+            result = await ensure_game_updated(
+                adb_path=self.emulator_manager.get_adb_path(),
</code_context>
<issue_to_address>
**issue (bug_risk):** The configured `time_limit` is never applied to APK downloading: `download_official_apk` uses a fixed 60-second HTTP timeout, and the caller invokes it without any deadline. A 2 GB download that continues making progress can run indefinitely, so `GameUpdateTimeLimit` does not limit the download as its configuration and docstring claim.

**Triggers:** When the CDN download is slow or stalls while still producing data more frequently than the HTTP inactivity timeout.

**Suggested fix:** Pass the configured deadline into `download_official_apk` and enforce it around the complete download, for example with an overall `asyncio.timeout(time_limit * 60)` or an equivalent total-time limit.
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 1 finding to address first, and when enabled, the feature downloads an APK from an external endpoint and installs it through ADB, so a bad version response, redirect, or package can alter the emulator persistently and reverting the PR will not undo that installation. The stored resource version and timeout change are otherwise bounded and can be corrected on a later run.

Blocking findings: app/task/MAA/tools/game_update.py:225


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 +221 to +225
try:
async with httpx.AsyncClient(follow_redirects=True) as client:
async with client.stream(
"GET", ARKNIGHTS_OFFICIAL_APK_URL, timeout=60.0
) as response:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): 配置的 time_limit 从未应用于 APK 下载:download_official_apk 使用固定的 60 秒 HTTP 超时,而调用方调用它时没有设置任何截止时间。一个持续产生下载进度的 2 GB 下载可能无限期运行,因此 GameUpdateTimeLimit 并未像其配置和文档字符串所声称的那样限制下载时间。

触发条件: CDN 下载速度缓慢或停滞,但产生数据的频率仍高于 HTTP 非活动超时时间。

建议修复: 将配置的截止时间传入 download_official_apk,并在完整下载过程外层强制执行该截止时间,例如使用总体的 asyncio.timeout(time_limit * 60),或采用等效的总时间限制。

Original comment in English

issue (bug_risk): The configured time_limit is never applied to APK downloading: download_official_apk uses a fixed 60-second HTTP timeout, and the caller invokes it without any deadline. A 2 GB download that continues making progress can run indefinitely, so GameUpdateTimeLimit does not limit the download as its configuration and docstring claim.

Triggers: When the CDN download is slow or stalls while still producing data more frequently than the HTTP inactivity timeout.

Suggested fix: Pass the configured deadline into download_official_apk and enforce it around the complete download, for example with an overall asyncio.timeout(time_limit * 60) or an equivalent total-time limit.

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.

1 participant