添加扩展
在 SRA 中添加扩展
Section titled “在 SRA 中添加扩展”SRA 的扩展系统是一套“泛型声明 + 装饰器注册 + 动态发现”的可插拔架构:
-
配置泛型:每个扩展通过继承
BaseExtension[YourConfig]声明自己的配置类型,YourConfig是一个 PydanticBaseModel。泛型参数让框架在编译期就知道扩展需要哪些配置,并能自动生成 JSON Schema 供前端渲染配置表单。 -
装饰器注册:
@extension装饰器在模块导入时自动将扩展类及其配置模型注册到全局ExtensionRegistry。扩展标识(ID)、展示名称和描述都可在此声明。 -
动态发现:SRA 启动时调用
load_extensions(),扫描extensions/目录下所有.py文件并逐一导入,触发各模块顶层的@extension装饰器完成注册。这与tasks/目录的动态导入机制完全一致。 -
运行与配置:
ExtensionRunner负责实例化扩展并注入IOperator,扩展可通过self.operator执行截图、点击、OCR 等实际操作。ExtensionConfigManager负责从extensions.json加载和保存各扩展的配置。
简单来说:在 extensions/ 目录下创建一个 Python 文件,定义配置模型并继承 BaseExtension[Config],用 @extension 装饰器注册,SRA 启动时就会自动发现并注册你的扩展。
扩展 vs 任务 vs 命令
Section titled “扩展 vs 任务 vs 命令”SRA 有三种可插拔模块,它们共享“动态发现”机制但定位不同:
| 扩展(Extension) | 任务(Task) | 命令(CommandSet) | |
|---|---|---|---|
| 目录 | extensions/ |
tasks/ |
tasks/ |
| 基类 | BaseExtension[Config] |
BaseTask |
cmd2.CommandSet[SRACli] |
| 注册方式 | @extension 装饰器,泛型声明配置类 |
@task 装饰器 |
cmd2 自动发现 |
| 用途 | 可独立运行的功能模块(截图、OCR 等) | 自动化任务流水线中的一个步骤 | CLI 命令 |
| 配置 | Pydantic BaseModel,自动生成 Schema,前端可渲染配置表单 | 通过 self.settings 读取全局设置,无独立配置模型 |
无内置配置系统 |
| 运行方式 | extension run <id> / extension run-all |
task single <index> / task single <ClassName> |
CLI 命令直接调用 |
| 执行顺序 | 无固定顺序,按 ID 独立调用 | 按文件名排序决定索引,task run 依次执行 |
无固定顺序 |
| IOperator | 自动注入,可执行游戏内操作 | 自动注入,可执行游戏内操作 | 不可用 |
| 生命周期回调 | on_start / on_completed / on_failed |
由 TaskManager 管理,任务失败会停止后续任务 |
无 |
简单来说:
- 如果你想做一个可独立运行、有配置界面的功能模块,用扩展。
- 如果你想参与自动化的任务流水线(如每日任务链),用任务。
- 如果你想添加一个CLI 命令供手动调用,用命令。
- 已安装 SRA 或已获取 SRA 源码
- 了解 Python 编程基础
- 了解 Pydantic
BaseModel的基本用法 - 文本编辑器(如 VSCode、Notepad++)
-
打开 SRA 的安装目录或源码目录,找到
extensions文件夹。 这里存放了所有的扩展脚本。 -
创建一个新的 Python 文件,例如
MyExtension.py。 -
定义配置模型。配置模型是一个继承自
pydantic.BaseModel的类,使用Field声明每个配置项的默认值、描述和约束:from pydantic import BaseModel, Fieldclass MyConfig(BaseModel):"""我的扩展配置。"""target: str = Field(default="星穹列车", description="目标名称")count: int = Field(default=1, ge=1, le=100, description="执行次数")verbose: bool = Field(default=False, description="是否输出详细日志")解释:
Field(default=...)— 设置默认值,未配置时使用此值。Field(description=...)— 描述文本,会显示在前端配置弹窗中。Field(ge=1, le=100)— 约束条件,ge= 最小值,le= 最大值。前端会自动为int类型渲染带上下限的数字输入框。
-
定义扩展类并用
@extension装饰器注册:from SRACore.extension import BaseExtension, extension@extension(name="我的扩展", description="这是一个自定义扩展")class MyExtension(BaseExtension[MyConfig]):"""一个自定义扩展示例。"""def run(self) -> bool:for i in range(self.config.count):print(f"[MyExtension] ({i + 1}/{self.config.count}) 目标: {self.config.target}")return True解释:
class MyExtension(BaseExtension[MyConfig])— 通过泛型参数MyConfig声明配置类型。框架会自动从中提取配置模型并注册。@extension(name="...", description="...")— 注册装饰器。name是展示名称,description是功能描述。不传时name默认使用类名,description默认使用 docstring 首行。def run(self) -> bool:— 抽象方法,必须实现。返回True表示成功,False表示失败。self.config— 类型为MyConfig,可直接访问配置字段,IDE 能提供完整的自动补全。
-
使用 IOperator 执行实际操作。扩展通过
self.operator可以执行游戏内的各种操作:@extension(name="截图示例", description="演示 IOperator 的基本用法")class ScreenshotDemo(BaseExtension[MyConfig]):"""演示 operator 的使用。"""def run(self) -> bool:# 截图screenshot = self.operator.screenshot()# 定位模板图片box = self.operator.locate("resources/template.png")if box:self.operator.click_box(box)# OCR 文字识别text = self.operator.ocr(screenshot, x=100, y=200, w=300, h=50)print(f"识别到文字: {text}")# 发送通知self.send_notification("截图完成", f"识别结果: {text}")return Trueself.operator的常用方法:screenshot()— 截取当前屏幕locate(template)— 定位模板图片在屏幕中的位置click_box(box)— 点击指定区域ocr(...)— 对指定区域进行 OCR 文字识别
-
(可选)重写生命周期回调:
@extension(name="生命周期示例", description="演示生命周期回调")class LifecycleDemo(BaseExtension[MyConfig]):"""演示生命周期回调。"""def on_start(self) -> None:print("扩展开始执行前调用,可用于初始化资源")def run(self) -> bool:print("执行主要逻辑")return Truedef on_completed(self) -> None:print("执行成功后调用,可用于清理资源")def on_failed(self) -> None:print("执行失败后调用,可用于错误恢复") -
运行 SRA 测试你的扩展。
确保你的文件已保存到
extensions/目录下。运行 SRA-cli:sra> extension list已注册 2 个扩展:Hello 问候 HelloExtension (config: HelloConfig) 简单的问候示例...MyExtension 我的扩展 MyExtension (config: MyConfig) 这是一个自定义扩展sra> extension run MyExtension[MyExtension] (1/1) 目标: 星穹列车扩展 'MyExtension' 执行成功sra> extension run MyExtension --count 3 --target 黑塔空间站[MyExtension] (1/3) 目标: 黑塔空间站[MyExtension] (2/3) 目标: 黑塔空间站[MyExtension] (3/3) 目标: 黑塔空间站扩展 'MyExtension' 执行成功你还可以查看扩展的配置 Schema:
sra> extension info MyExtension --json{"properties": {"target": {"default": "星穹列车", "description": "目标名称", "type": "string"}, ...}} -
恭喜! 你已经学会了如何在 SRA 中添加扩展。回顾一下关键点:
- 文件放在
extensions/目录下 - 定义 Pydantic
BaseModel作为配置模型,用Field声明默认值和约束 - 继承
BaseExtension[YourConfig]并实现run()方法 - 用
@extension装饰器注册,可附带name和description - 通过
self.operator执行游戏内操作(截图、OCR、点击等) - 通过
self.config访问配置,IDE 完整支持类型补全 - SRA 启动时自动发现并注册,无需手动修改任何注册代码
- 前端会根据配置 Schema 自动生成配置表单,无需编写 UI 代码
- 文件放在
