# Project Interface 协议

> 注意: 本文档是关于 `ProjectInterface` 的编写和使用
>
> 文中将使用 PI 代指 `ProjectInterface`，Client 代指可以处理 PI 的工具

## 简介

所谓 `ProjectInterface`，即 MaaFramework 的一个标准化的项目结构声明，该声明目前包含 `interface.json` 一个文件。通过定义 PI，你可以使用 MaaFramework 的各种衍生工具。因此，即使你打算纯粹依靠通用编程语言集成，也建议定义包含基础信息的 PI。

* MaaPiCli

  通用 CLI

* [MFAWPF](https://github.com/SweetSmellFox/MFAWPF)

  通用 UI

* [Maa Pipeline Support](https://marketplace.visualstudio.com/items?itemName=nekosu.maa-support)

  VSCode 插件

* [项目模板](https://github.com/MaaXYZ/MaaPracticeBoilerplate)

  基于 PI 组织的模板

## `interface.json`

> 该文件可以通过 [schema](https://github.com/MaaXYZ/MaaFramework/blob/main/tools/interface.schema.json) 文件获得提示和校验功能
>
> 使用 VSCode 打开 项目模板 文件夹，可自动关联 schema 和文件

### 整体结构

* version `string`

  项目版本，Client 可以展示给用户。

* message `string`

  欢迎语，Client 可以展示给用户。

* controller `object[]`

  控制器配置，为一个对象数组，含有预设的控制器信息。

  * name `string`

    唯一名称，Client 会展示给用户进行选择。

  * type `'Adb' | 'Win32'`

    控制器类型，取值为 `Adb` 和 `Win32`。

  * adb `object`

    `Adb` 控制器的具体配置。

    * input `number`

      可选。`Adb` 控制器的控制方式，不提供则使用默认。具体定义参见 [Input和Screencap](#adb-input)。

    * screencap `number`

      可选。`Adb` 控制器的截图方式，不提供则使用默认。具体定义参见 [Input和Screencap](#adb-screencap)。

    * config `object`

      可选。`Adb` 控制器的额外配置，不提供则使用空对象。具体定义参见 [Adb Config](#adb-config)。
  
  * win32 `object`

    `Win32` 控制器的具体配置。

    * class_regex `string`

      可选。`Win32` 控制器搜索窗口类名使用的正则表达式。

    * window_regex `string`

      可选。`Win32` 控制器搜索窗口标题使用的正则表达式。

    * input `number`

      可选。`Win32` 控制器的控制方式，不提供则使用默认。具体定义参见 [Input和Screencap](#win32-input)。

    * screencap `number`

      可选。`Win32` 控制器的截图方式，不提供则使用默认。具体定义参见 [Input和Screencap](#win32-screencap)。

* resource `object[]`

  资源配置，为一个对象数组，含有资源加载的信息。

  * name `string`

    唯一名称，Client 会展示给用户进行选择。

  * path `string[]`

    加载的路径数组。如果提供多个路径，会依次加载，后加载的资源会[覆盖](#资源覆盖)前加载的资源。

    使用 `{PROJECT_DIR}` 来指代 `interface.json` 文件所在的目录，例如:

    ```json
    "resource": [
        {
            "name": "Official",
            "path": [
                "{PROJECT_DIR}/resource"
            ]
        }
    ]
    ```

    注意: 资源不仅仅是 `pipeline`，也包含 `image` 和 `model`，因此不要直接指定 `pipeline` 目录。

* agent `object`

  代理配置，为一个对象，含有子进程（AgentServer）的信息。

  * child_exec `string`

    子进程路径，为系统路径中可执行文件。如在环境变量（系统变量、用户变量）中存在 Python 路径，可直接写 `"python"`。

  * child_args `string[]`

    可选。子进程参数数组。

    使用 `{PROJECT_DIR}` 来指代 `interface.json` 文件所在的目录，例如:

    ```json
    "agent": {
        "child_exec": "python",
        "child_args": [
            "{PROJECT_DIR}/agent/main.py"
        ]
    }
    ```

    注意：这里 `{PROJECT_DIR}` 指安装后 `interface.json` 文件所在的目录，不同项目请根据实际情况确定。

  * identifier `string`

    可选。连接标识符，被用来创建一个通信套接字。填写则会被使用，否则自动创建。

* task `object[]`

  任务配置，为一个对象数组，含有可执行任务的信息。

  * name `string`

    唯一名称，Client 会展示给用户进行选择。

  * entry `string`

    任务入口，为 `pipeline` 中 `Task` 的名称。

  * pipeline_override `pipeline`

    可选。任务参数，执行任务时会[覆盖](#资源覆盖)已加载的资源。该项结构与 `pipeline` 中的 `json` 文件完全一致，需要包含 任务名 部分，例如:

    ```json
    "pipeline_override": {
        "Quit": {
            "enabled": true
        }
    }
    ```

  * option `string[]`

    可选。任务配置项，为一个数组，含有若干后续 `option` 对象中的键的值，Client 会根据要求用户进行选择。

    Client 可以使用 `option` 中的顺序来展示配置项。

* option `record<string, object>`

  配置项定义，为一个对象映射，含有配置项的信息。

  * _key_

    唯一名称，任务会使用该名称进行引用。

  * cases `object[]`

    可选项，为一个对象数组，含有各个可选项的信息。

    Client 可以使用 `cases` 中的顺序来展示可选项。

    * name `string`

      唯一名称，Client 会展示给用户进行选择。

    * pipeline_override `pipeline`

      同 `task` 中的 `pipeline_override`，在选项激活时生效。

  * default_case `string`

    可选。默认选项，Client 可以使用该值作为选项的初始值。

### Input和Screencap

#### Input

定义 MaaFramework 会使用何种方式来控制。

##### Adb Input

> 参考 [MaaDef.h](https://github.com/MaaXYZ/MaaFramework/blob/main/include/MaaFramework/MaaDef.h#L227-L240)

将下面选择的方式 **按位或** 合并为一个值提供。MaaFramework 将会按照固定优先级顺序尝试所有提供的方式，选择首个可用方式。

默认尝试除 EmulatorExtras 外所有方式。

> 优先级: EmulatorExtras > Maatouch > MinitouchAndAdbKey > AdbShell

* AdbShell `1`

  使用 adb 进程进行控制。

* MinitouchAndAdbKey `2`

  使用 adb 进程进行按键控制，使用 minitouch 工具进行触摸控制。

* Maatouch `4`

  使用 maatouch 工具控制。

* EmulatorExtras `8`

  使用模拟器专用工具进行控制。目前支持的模拟器:

  * MuMu 12

  * 雷电 9

##### Win32 Input

> 参考 [MaaDef.h](https://github.com/MaaXYZ/MaaFramework/blob/main/include/MaaFramework/MaaDef.h#L252-L259)

选择下面的值提供。

无默认值。Client 可以选择一个作为默认值。

Win32 下不同程序处理输入的方法不同，不存在一个通用方式。

* Seize `1`

  抢占式控制。该模式下用户的光标将直接被 MaaFramework 移动，目标窗口将会保持激活。

* SendMessage `2`

  使用 SendMessage 控制。该模式下目标窗口可以失焦。

#### Screencap

定义 MaaFramework 会使用何种方式来截图。

##### Adb Screencap

> 参考 [MaaDef.h](https://github.com/MaaXYZ/MaaFramework/blob/main/include/MaaFramework/MaaDef.h#L208-L225)

将下面选择的方式 **按位或** 合并为一个值提供。MaaFramework 将会尝试所有提供的方式，选择最快的可用方式。

默认尝试除 `RawByNetcat`，`MinicapDirect`，`MinicapStream` 外所有方式。

`MinicapDirect` 和 `MinicapStream` 由于会编码为 jpg，为有损编码，将显著降低模板匹配的效果，不建议使用。

* EncodeToFileAndPull `1`

  通过内置 screencap 进程截图，编码为 png 输出到文件，通过 adb 进程拉取文件，读取文件。

* Encode `2`

  通过内置 screencap 进程截图，编码为 png，通过 adb 进程管道传输。

* RawWithGzip `4`

  通过内置 screencap 进程截图，通过 gzip 压缩，通过 adb 进程管道传输。

* RawByNetcat `8`

  通过内置 screencap 进程截图，通过 nc 进程网络传输。

* MinicapDirect `16`

  通过 minicap 工具截图和编码为 jpg，通过 adb 进程管道传输。

* MinicapStream `32`

  通过 minicap 工具流式截图和编码为 jpg，通过 adb 进程管道传输。

* EmulatorExtras `64`

  使用模拟器专用工具进行截图。

##### Win32 Screencap

> 参考 [MaaDef.h](https://github.com/MaaXYZ/MaaFramework/blob/main/include/MaaFramework/MaaDef.h#L242-L250)

选择下面的值提供。

无默认值。Client 可以选择一个作为默认值。

Win32 下不同程序处理绘制的方法不同，不存在一个通用方式。

* GDI `1`

* FramePool `2`

* DXGI_DesktopDup `4`

### Adb Config

可以通过 config 对象覆盖控制器的部分默认逻辑。通常只有在使用 `EmulatorExtras` 且进行多开时会需要特定配置。

### 资源覆盖

后加载的资源中如果发现了和已加载资源同名的任务，会对任务进行合并。通常情况下，可以认为新的任务的顶级键会替换旧任务的。例如:

旧任务

```json
{
    "task1": {
        "enabled": false,
        "recognition": "DirectHit",
        "next": [ "T1", "T2" ]
    }
}
```

新任务

```json
{
    "task1": {
        "enabled": true,
        "action": "Click",
        "next": [ "T2", "T3" ]
    }
}
```

合并后的任务

```jsonc
{
    "task1": {
        "enabled": true,
        "recognition": "DirectHit",
        "action": "Click",
        "next": [ "T2", "T3" ]       // 直接替换，内部不会合并
    }
}
```
