ok-ef 開發指南
本文以當前原始碼、src/config.py、測試目錄和 workflow 為準,說明專案結構和貢獻流程。具體專案自有介面見 API 參考。
1. 執行架構
ok-ef 是基於 ok-script 的 Windows 遊戲自動化應用。倉庫負責業務任務、專案級識別/互動封裝、資源和自定義 GUI;截圖、基礎 OCR/Feature API、任務排程和主 GUI 由 ok-script 提供。
flowchart TD
A[main.py / main_debug.py] --> B[src.config.config]
A --> C[install_startup_patches]
C --> D[ok.OK config]
B --> D
D --> E[onetime_tasks]
D --> F[trigger_tasks]
D --> G[custom_tabs]
E --> H[业务 Mixin / BaseEfTask]
F --> H
H --> I[src/core/base_mixin]
I --> J[ok.BaseTask]
H --> K[Feature / OCR / YOLO / Win32 interaction]
當前關鍵技術配置:
| 領域 | 當前實現 |
|---|---|
| Python | CI 和 China 打包使用 3.12 |
| 平臺 | Windows;遊戲程序 Endfield.exe、視窗類 UnityWndClass |
| 捕獲 | 優先 WGC,後備 BitBlt_RenderFull |
| OCR | onnxocr,啟用 OpenVINO 和 NPU 引數 |
| Feature | COCO 標註區域 + OpenCV 模板匹配 |
| YOLO | ONNX/OpenVINO,多模型註冊和按目標路由 |
| UI | ok-script GUI + qfluentwidgets 自定義頁 |
| 打包 | PyAppify;China/Global profile |
2. 基類與組合
2.1 BaseEfTask
基礎設施 Mixin 已從任務目錄移動到 src/core/base_mixin/:
BaseEfTask(
WindowArrowDrawingMixin,
AccountOverrideMixin,
GameFlowMixin,
RuntimeMixin,
ok.BaseTask,
ProcessManager,
)
職責:
| 類 | 檔案 | 職責 |
|---|---|---|
WindowArrowDrawingMixin |
src/core/base_mixin/window_arrow_drawing_mixin.py |
導航箭頭視窗繪製 |
AccountOverrideMixin |
src/core/base_mixin/account_override_mixin.py |
按穩定賬號 ID 覆蓋任務配置 |
GameFlowMixin |
src/core/base_mixin/game_flow_mixin.py |
主介面、地圖、登入截圖、彈窗和場景流程 |
RuntimeMixin |
src/core/base_mixin/runtime_mixin.py |
Feature、點選、按鍵、移動、UI 穩定、YOLO |
ProcessManager |
src/core/base_mixin/process_manager.py |
遊戲程序終止能力 |
不要再引用舊的 src/tasks/mixin/runtime_mixin.py、game_flow_mixin.py、process_manager.py 或 window_arrow_drawing_mixin.py 路徑。
2.2 業務 Mixin
src/tasks/mixin/ 保留跨任務業務能力:
BaseEfTask
├── Common
├── MapMixin
├── BattleMixin
├── MouseScanMixin
├── NavigationMixin
│ ├── LiaisonMixin
│ └── ZipLineMixin
└── LoginMixin
└── AccountMixin
EndCommandMixin、WsPositionMixin 是無 BaseEfTask 基類的協作 Mixin,通過最終任務組合獲得任務能力。
2.3 實際任務 MRO
主要組合以類宣告順序為準:
DailyTask(
Common, MapMixin, ZipLineMixin, BattleMixin, LiaisonMixin,
EndCommandMixin, AccountMixin, MouseScanMixin
)
BattleTask(Common, MapMixin, ZipLineMixin, BattleMixin)
DeliveryTask(AccountMixin, ZipLineMixin, MapMixin)
AutoCombatTask(BattleMixin, TriggerTask)
ItemNavigatorTask(WsPositionMixin, BaseEfTask, TriggerTask)
DailyTask 的日常子功能不再全部作為 Python 基類混入。它在 __init__ 中組合 DailyBuyFeature、DailyBattleFeature、DailyTradeFeature、DailyShopFeature、DailyRoutineFeature、DailyLiaisonFeature、DailyDemoFeature 物件,並由 DailyTaskRunner 執行 build_task_plan()。
所有協作式 __init__ 都應呼叫 super()。配置字典使用 update 增量合併,避免破壞 MRO 前序類註冊的資料。
3. 註冊清單
src/config.py 是 GUI 註冊的唯一權威來源。
一次性任務
| 順序 | 類 | 模組 |
|---|---|---|
| 1 | DailyTask |
src.tasks.onetime.DailyTask |
| 2 | TakeDeliveryTask |
src.tasks.onetime.TakeDeliveryTask |
| 3 | WarehouseTransferTask |
src.tasks.onetime.WarehouseTransferTask |
| 4 | DeliveryTask |
src.tasks.onetime.DeliveryTask |
| 5 | BattleTask |
src.tasks.onetime.BattleTask |
| 6 | DemoDrawTask |
src.tasks.onetime.DemoDrawTask |
| 7 | YingTuoTask |
src.tasks.onetime.YingTuoTask |
| 8 | TestStartGame |
src.tasks.onetime.TestStartGame |
| 9 | TestBattleToEnd |
src.tasks.test.TestBattleToEnd |
| 10 | TestArrowAngle |
src.tasks.test.TestArrowAngle |
| 11 | TestDragScan |
src.tasks.test.TestDragScan |
| 12 | TestPauseTiming |
src.tasks.test.TestPauseTiming |
| 13 | TestBlueDotAlign |
src.tasks.test.TestBlueDotAlign |
| 14 | TestLevelRead |
src.tasks.test.TestLevelRead |
| 15 | TestDemoGraphic |
src.tasks.test.TestDemoGraphic |
| 16 | RealtimeDetectTask |
src.tasks.test.RealtimeDetectTask |
| 17 | DiagnosisTask |
src.tasks.test.DiagnosisTask |
| 18 | TestBattleSlotDetect |
src.tasks.test.TestBattleSlotDetect |
| 19 | TestCombatTemplateMatch |
src.tasks.test.TestCombatTemplateMatch |
| 20 | MouseRotationCalibration |
src.tasks.test.MouseRotationCalibration |
一次性任務按「業務任務(src.tasks.onetime.*)→ 除錯/測試任務(src.tasks.test.*)」分組排列。
PeriodicScreenshotTask.py 存在但未註冊。TakeDeliveryTask 的類宣告還包含 TriggerTask,但它當前只註冊在一次性任務列表中。
觸發式任務
| 順序 | 類 | 模組 |
|---|---|---|
| 1 | AutoCombatTask |
src.tasks.trigger.AutoCombatTask |
| 2 | AutoInteractionTask |
src.tasks.trigger.AutoInteractionTask |
| 3 | AutoPickTask |
src.tasks.trigger.AutoPickTask |
| 4 | ItemNavigatorTask |
src.tasks.trigger.ItemNavigatorTask |
當前沒有 AutoLoginTask.py 或觸發式自動登入註冊。登入切換能力由 LoginMixin/AccountMixin 供多賬號任務呼叫。
自定義頁
GlobalConfigTab:全域性戰鬥、鍵位和基礎配置。AccountConfigTab:賬號資料及按任務覆蓋配置。
4. 當前目錄
以下只列開發時需要理解和維護的檔案,不包含執行快取、日誌、截圖、IDE 後設資料和生成的檔案、目錄。
ok-end-field/
├── main.py / main_debug.py # 正式/调试入口,均安装启动补丁
├── pyproject.toml # 项目 Python 依赖声明
├── requirements.txt # 由 uv 针对平台生成,供发布流水线 pip 使用
├── run_tests.ps1 # 逐个运行 tests/*.py(经 uv run)
├── pyappify.yml # China/Global 打包 profile
├── deploy.txt # tag 构建时同步到更新仓库的清单
├── auto_release.py/.ps1/.sh # tag 辅助脚本
├── src/
│ ├── config.py # ok-script 应用配置、任务和 tab 注册
│ ├── globals.py # 应用级共享对象
│ ├── icons.py # 图标定义
│ ├── core/
│ │ ├── BaseEfTask.py
│ │ ├── BattleConfig.py
│ │ ├── config_migration.py
│ │ ├── global_config_store.py
│ │ ├── sequence_parser.py
│ │ └── base_mixin/
│ │ ├── account_override_mixin.py
│ │ ├── game_flow_mixin.py
│ │ ├── process_manager.py
│ │ ├── runtime_mixin.py
│ │ └── window_arrow_drawing_mixin.py
│ ├── tasks/
│ │ ├── onetime/ # 一次性任务和 AutoCombatLogic
│ │ ├── trigger/ # 四个已注册后台任务
│ │ ├── mixin/ # 业务能力 Mixin
│ │ ├── account/ # 账号解析、稳定 ID 和覆盖存储
│ │ └── daily/ # Feature 组合、runner、汇总和 misc 子功能
│ ├── data/
│ │ ├── FeatureList.py # 模板名称字符串枚举
│ │ ├── characters*.py
│ │ ├── delivery_area*.py
│ │ ├── item_map_query.py
│ │ ├── world_map*.py
│ │ ├── zh_en.py
│ │ └── lang/__init__.py # 统一 JSON 语言访问器
│ ├── interaction/ # Win32 输入、键位、鼠标、屏幕区域
│ ├── image/ # HSV、登录截图、旋转模板
│ ├── yolo/ # 模型定义、注册、加载和 OpenVINO 检测
│ ├── essence/ # 装备词条 OCR 纯算法轮子
│ ├── patches/ # 启动 monkey patches
│ └── gui/ # 全局/账号配置页、WebView 对话框
├── assets/
│ ├── coco_annotations.json
│ ├── images/ # Feature 图片
│ ├── items/ # 物品和地图数据
│ ├── lang/*.json # 每模块一个统一多 locale JSON
│ ├── models/yolo/ # ONNX 模型
│ └── ocr_fix/ocr_text_fix.json
├── i18n/<locale>/LC_MESSAGES/ # gettext ok.po/ok.mo
├── configs/ # 任务、全局、账号作用域配置
├── tests/ # unittest 测试
├── tools/ # 辅助工具;部分语言工具仍针对旧 schema
├── scripts/ # 下载统计、迁移等脚本
├── ok_tasks/ # 用户自定义任务
├── ok_templates/ # 模板标注子模块
└── .github/workflows/ # 构建、统计、地图数据和维护 workflow
5. 開發環境
git clone --recurse-submodules https://github.com/AliceJump/ok-end-field.git
Set-Location ok-end-field
uv sync
uv run python main_debug.py
約束:
- 使用 Python 3.12 與當前 CI/打包環境保持一致。
- 依賴通過 uv 管理:
uv sync依照uv.lock建立.venv;uv run python ...在該環境中執行 Python。requirements.txt是面向釋出流水線的派生產物,不要手動編輯。 - Windows 互動需要程序許可權不低於遊戲,開發時通常以管理員許可權啟動 IDE/終端。
- 從倉庫根目錄執行,資源和配置路徑大量以當前工作目錄解析。
- 遊戲視窗配置要求 16:9,最低
1920x1080(1080P)。 - WGC 常規截圖不適合登入介面;登入 Mixin 使用 Win32 螢幕捕獲,通常需要視窗可見並可啟用。
6. 開發流程
6.1 新增任務
一次性任務通常直接繼承 BaseEfTask 或業務 Mixin:
from src.core.BaseEfTask import BaseEfTask
class MyTask(BaseEfTask):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.name = "我的任务"
self.description = "任务说明"
self.default_config.update({"选项 A": True})
self.config_description.update({"选项 A": "控制该步骤。"})
def run(self):
self.ensure_main()
註冊格式:
["src.tasks.onetime.MyTask", "MyTask"],
觸發式任務還需在最終 MRO 中包含 ok.TriggerTask,並註冊到 trigger_tasks。完整最小示例見 QUICKSTART。
6.2 新增業務 Mixin
- 跨任務業務能力放
src/tasks/mixin/。 - 基礎執行時能力才放
src/core/base_mixin/。 - Mixin 不定義最終任務的
name、description或run()。 - 若繼承
BaseEfTask,使用協作式super()。 - 如果 Mixin 只是依賴最終任務提供能力,可像
EndCommandMixin一樣不繼承BaseEfTask,但必須明確它的依賴。 - 增加基類前用 Python 的
Class.__mro__檢查 C3 線性化,避免重複基類順序衝突。
6.3 任務配置
框架任務配置使用:
self.default_config.update({...})
self.config_description.update({...})
self.config_type[key] = {...}
self.default_config_group.update({...})
BaseEfTask.register_config_groups(groups) 可建立一個帶 sub_configs 的分組下拉框。配置舊鍵遷移通過類屬性 config_key_migrations 宣告,BaseEfTask.load_config() 會沿 MRO 合併後呼叫 migrate_config_file_keys。
全域性配置定義在 src/core/global_config_store.py:
Game Hotkey ConfigBattle ConfigEnsure Main Once Action SleepZip Line Config
戰鬥任務通過 BattleMixin.get_battle_config() 讀取。任務可選擇全域性或獨立戰鬥配置;繫結賬號上下文後,賬號任務覆蓋優先順序最高。不要在多個任務中複製全域性戰鬥預設值。
6.4 Feature 資源
src/config.py 的 template_tab 會生成 src/data/FeatureList 標籤列舉,Feature 影像和標註以 assets/images/、assets/coco_annotations.json 及 ok_templates/ 資料為準。
from src.data.FeatureList import FeatureList as fL
box = self.find_one(fL.transfer_go)
boxes = self.find_feature([fL.monthly_card, fL.monthly_card2])
解析度名稱約定為無後綴、_2k、_4k。RuntimeMixin.get_feature_by_resolution() 只會選擇 FeatureList 中實際存在的名稱,缺失時拋 AttributeError。
6.5 OCR 與語言
OCR 業務文本儲存在單檔案 assets/lang/<module>.json,不是 locale 子目錄:
self.wait_ocr(match=self.lang.login_mixin.k_20275ef2, time_out=5)
當前活動 OCR locale 是 zh_CN、zh_TW。全域性混淆補丁只擴充套件 match,不改寫 OCR 輸出。新增資源和糾錯前閱讀 i18n 與 OCR 配置流程。
6.6 鍵位
可改鍵操作不得直接傳送預設字面值:
self.press_key("f") # common
self.press_industry_key("y") # industry
self.press_combat_key("e") # combat
KeyConfigManager 只有 resolve_key(key, key_type)。方向移動、固定角色數字鍵、固定滑索鍵和 alt 等系統修飾鍵可按明確的不改鍵語義使用底層介面。若遊戲設定允許改鍵,對應 UI 圖示也不應做成固定按鍵字樣模板。
6.7 登入和多賬號
LoginMixin.login_flow(username, password=None) 通過登入介面的“最近賬號”列表選擇賬號,不輸入密碼。舊賬號行中的逗號後密碼欄位會被忽略且不儲存。
多賬號任務應使用 iter_multi_account_context() 或現有 AccountMixin 流程,並在讀取賬號覆蓋配置前設定 current_account_id。賬號覆蓋優先穩定 ID,使用者名稱僅作為後備。
7. 測試清單
當前 tests/ 有 37 個測試模組:
| 檔案 | 主要覆蓋 |
|---|---|
TestAccountBattleConfig.py |
賬號配置可見性、快照合併、戰鬥配置優先順序 |
TestAccountConfigBlacklist.py |
任務賬號配置黑名單 |
TestAccountOverrideMixin.py |
賬號覆蓋 Mixin:僅任務執行時啟用覆蓋、其餘回退預設 |
TestAutoCombat.py |
戰鬥圖片識別、技能條、等級和排軸解析 |
TestAutoPick.py |
自動拾取規則(可生產植物預設跳過與開關) |
TestCheckLang.py |
原始碼語言 key 與統一 JSON 的 zh_CN/zh_TW 引用 |
TestConditionalRotation.py |
排軸條件旋轉 AST 歸一化 |
TestConditionalRotationCombat.py |
條件旋轉戰鬥執行(if/else 分支) |
TestConditionalRotationGui.py |
條件旋轉 GUI 動作/條件格式化 |
TestDailyBattleToEnd.py |
日常刷本到結束:YOLO 命中停用中鍵點選、獎勵等待 |
TestDailyBoatState.py |
日常聯運狀態共享範圍 |
TestDailyConfigMigration.py |
日常地區布林鍵合併遷移 |
TestDailyRegionalRunner.py |
日常地區執行器(僅購買/回撥/重試) |
TestDailyRewardWaits.py |
日常獎勵領取等待邏輯 |
TestDailyTaskFinallyFile.py |
日常彙總檔案生成和清理 |
TestDeliveryAreaConfig.py |
送貨地區、搜尋區域、目標和券種配置 |
TestDeliveryRewardsClaim.py |
送貨獎勵領取狀態處理 |
TestEfInteraction.py |
視窗啟用與後臺訊息互動 |
TestEssenceImageFeatures.py |
裝備詞條 Feature 資產存在性 |
TestEssenceRecognizer.py |
裝備詞條 OCR 純解析和等級附加 |
TestGameWindow.py |
遊戲視窗查詢(類名與執行檔匹配) |
TestGuiI18n.py |
GUI 翻譯呼叫和執行時採集汙染 |
TestItemMapQuery.py |
物品地圖查詢和篩選 |
TestLogZipDedup.py |
日誌打包圖片去重 |
TestMouseRotationCalibration.py |
滑鼠視角旋轉系數標定角度差純函式與任務註冊 |
TestOutpostExchange.py |
據點兌換優先順序與排除邏輯 |
TestPoLocaleConsistency.py |
gettext catalog 完整性和一致性 |
TestPressEsc.py |
press_esc 走任務鍵盤控制器 |
TestRuntimeMixinFeatureClick.py |
普通/Alt Feature 點選路徑 |
TestScreenshotSidecar.py |
截圖側邊資料序列化 |
TestSequenceParser.py |
中英文逗號序列和整數序列解析 |
TestStateDrivenWaits.py |
狀態驅動的等待(ensure_main/ensure_map/safe_back 等) |
TestTakeDeliveryFunctions.py |
運送委託 OCR 樣本處理 |
TestWarehouseSwitchOCR.py |
倉庫狀態 OCR 樣本 |
TestYoloDetect.py |
檢測注入、ROI/overlay 和引數驗證 |
TestYoloModelRegistry.py |
模型配置合併及目標路由 |
TestZipLineConfig.py |
滑索全域性配置分組與舊配置遷移 |
推薦從倉庫根目錄執行:
uv run python -m unittest discover -s tests -p "Test*.py"
或使用倉庫指令碼:
.\run_tests.ps1
run_tests.ps1 通過 uv run python 在專案 .venv 中執行,無需手動啟用虛擬環境。
測試並非全是無資源的純演算法測試。部分依賴 assets 圖片、OCR 樣本、OpenCV、ok-script 的 TaskTestCase 或 Windows 相關匯入。它們通常不要求正在運行遊戲,但視窗互動流程仍必須實機驗證。
8. CI、釋出與工具
.github/workflows/build.yml 只在推送 v* tag 時觸發:
checkout(LFS)
-> Python 3.12
-> pip install -r requirements.txt(requirements.txt 由 uv 从 pyproject.toml 生成)
-> inline ok-script requirements
-> 逐个运行 tests/*.py
-> 按 deploy.txt 同步更新仓库
-> PyAppify 打包
-> GitHub Release
-> 触发 MirrorChyan workflow
其它當前 workflow:
download_stats.yml:每日/手動生成並提交assets/downloads.svg。mirrorchyan_uploading.yml、mirrorchyan_release_note.yml:MirrorChyan 釋出流程。update-endfield-map-data.yml:地圖資料更新。stale.yml:issue/PR 維護。
auto_release.py、auto_release.ps1、auto_release.sh 是 tag 輔助指令碼。釋出行為以指令碼和 workflow 當前實現為準,不要假定測試在“打 tag 前”自動執行;CI 是 tag 已推送後啟動。
語言工具狀態:tools/lang_batch_translate.py 仍掃描舊的 locale 子目錄 schema,不適用於當前統一 assets/lang/*.json;scripts/migrate_lang.py 是遷移指令碼。日常語言維護不要執行它們,詳見 i18n 文件。
9. 維護檢查
程式碼變更後按影響面檢查:
- 任務註冊變化:同步
src/config.py對應使用者/開發文件。 - Mixin 或基礎設施移動:同步匯入示例和 MRO 圖,搜尋舊路徑。
- API 引數或返回語義變化:更新 API.md 並執行直接測試。
- 配置變化:同步預設值、描述、型別、全域性/任務/賬號優先順序測試。
- OCR 文本變化:更新統一語言 JSON,執行
TestCheckLang。 - GUI gettext 變化:執行
TestGuiI18n和TestPoLocaleConsistency。 - Feature/YOLO 變化:驗證資源、模型路由、ROI 座標及 Debug overlay。
- 互動流程變化:除單元測試外,用
main_debug.py在支援解析度實測。
權威來源:
- 註冊和應用引數:
src/config.py - 核心組合:
src/core/BaseEfTask.py - 執行時介面:
src/core/base_mixin/*.py - 業務行為:
src/tasks/**/*.py - 全域性戰鬥配置:
src/core/BattleConfig.py - OCR locale/schema:
src/data/lang/__init__.py - 測試範圍:
tests/*.py - 釋出:
.github/workflows/*.yml