跳转到内容

添加扩展

SRA 的扩展系统是一套“泛型声明 + 装饰器注册 + 动态发现”的可插拔架构:

  1. 配置泛型:每个扩展通过继承 BaseExtension[YourConfig] 声明自己的配置类型,YourConfig 是一个 Pydantic BaseModel。泛型参数让框架在编译期就知道扩展需要哪些配置,并能自动生成 JSON Schema 供前端渲染配置表单。

  2. 装饰器注册@extension 装饰器在模块导入时自动将扩展类及其配置模型注册到全局 ExtensionRegistry。扩展标识(ID)、展示名称和描述都可在此声明。

  3. 动态发现:SRA 启动时调用 load_extensions(),扫描 extensions/ 目录下所有 .py 文件并逐一导入,触发各模块顶层的 @extension 装饰器完成注册。这与 tasks/ 目录的动态导入机制完全一致。

  4. 运行与配置ExtensionRunner 负责实例化扩展并注入 IOperator,扩展可通过 self.operator 执行截图、点击、OCR 等实际操作。ExtensionConfigManager 负责从 extensions.json 加载和保存各扩展的配置。

简单来说:extensions/ 目录下创建一个 Python 文件,定义配置模型并继承 BaseExtension[Config],用 @extension 装饰器注册,SRA 启动时就会自动发现并注册你的扩展。

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++)
  1. 打开 SRA 的安装目录或源码目录,找到 extensions 文件夹。 这里存放了所有的扩展脚本。

  2. 创建一个新的 Python 文件,例如 MyExtension.py

  3. 定义配置模型。配置模型是一个继承自 pydantic.BaseModel 的类,使用 Field 声明每个配置项的默认值、描述和约束:

    from pydantic import BaseModel, Field
    class 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 类型渲染带上下限的数字输入框。
  4. 定义扩展类并用 @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 能提供完整的自动补全。
  5. 使用 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 True

    self.operator 的常用方法:

    • screenshot() — 截取当前屏幕
    • locate(template) — 定位模板图片在屏幕中的位置
    • click_box(box) — 点击指定区域
    • ocr(...) — 对指定区域进行 OCR 文字识别
  6. (可选)重写生命周期回调:

    @extension(name="生命周期示例", description="演示生命周期回调")
    class LifecycleDemo(BaseExtension[MyConfig]):
    """演示生命周期回调。"""
    def on_start(self) -> None:
    print("扩展开始执行前调用,可用于初始化资源")
    def run(self) -> bool:
    print("执行主要逻辑")
    return True
    def on_completed(self) -> None:
    print("执行成功后调用,可用于清理资源")
    def on_failed(self) -> None:
    print("执行失败后调用,可用于错误恢复")
  7. 运行 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"}, ...}}
  8. 恭喜! 你已经学会了如何在 SRA 中添加扩展。回顾一下关键点:

    • 文件放在 extensions/ 目录下
    • 定义 Pydantic BaseModel 作为配置模型,用 Field 声明默认值和约束
    • 继承 BaseExtension[YourConfig] 并实现 run() 方法
    • @extension 装饰器注册,可附带 namedescription
    • 通过 self.operator 执行游戏内操作(截图、OCR、点击等)
    • 通过 self.config 访问配置,IDE 完整支持类型补全
    • SRA 启动时自动发现并注册,无需手动修改任何注册代码
    • 前端会根据配置 Schema 自动生成配置表单,无需编写 UI 代码