内容
# Gua
英文 | [日本語](README.ja.md)
[](https://github.com/link1345/gua/blob/main/LICENSE)
[](https://discord.gg/Zy65k8AxH2)
**Gua** 是一款用于游戏的运行时 UI 自动化协议。
它从正在运行的游戏中公开语义 UI 树,以便测试运行器和 AI 代理可以在不依赖脆弱的图像识别或基于坐标的输入的情况下检查、查询、点击和验证游戏中的 UI。
## NuGet 包
- **Gua.Core:** [](https://www.nuget.org/packages/Gua.Core) <br>
用于从 .NET 使用 Gua C ABI 运行时,包括 Windows x64 本地运行时。
- **Gua.Testing:** [](https://www.nuget.org/packages/Gua.Testing) <br>
为常规 .NET 测试添加 Gua 定位器、等待、断言和适配器测试循环。
- **Gua.Testing.Godot:** [](https://www.nuget.org/packages/Gua.Testing.Godot) <br>
启动 Godot 进程,并提供帮助程序通过 Gua 桥接器控制和验证正在运行的场景。
## MCP 和 Inspector
- **gui-mcp:** [](https://www.npmjs.com/package/gui-mcp) <br>
一个薄的 MCP 服务器,通过 Inspector 使用的相同 WebSocket 桥接器将 Gua 运行时操作暴露给 AI 代理。
- **Gua Inspector:** [](https://github.com/link1345/gua/actions/workflows/gua-release.yml)<br>
一个浏览器和 Windows 桌面 UI,用于检查语义 UI 树、节点状态、截图和日志,以及用于发送运行时命令。
```ts
await game.getByRole("button", { name: "Start Game" }).click()
await expect(game.getById("loading")).toBeVisible()
```
当前实现通过 C ABI 在 C++ 和 C# 中公开此形状,添加了 Inspector 和 MCP 消费者,并包括 Godot 4.7 适配器和示例:
```cpp
gua::testing::get_by_role(ctx, "button", "Start Game").click();
gua::testing::wait_for_text(ctx, "Loading...").to_be_visible();
```
```csharp
GuaAssertions.GetByRole(ui, "button", "Start Game").Click();
GuaAssertions.WaitForText(ui, "Loading...").ToBeVisible();
```
`Click()` 有意将点击请求加入队列;它不会直接改变游戏。游戏适配器(例如 ImGui 或 Godot 适配器)必须在后续帧中消耗请求并发出观察到的点击事件。 不运行真实引擎适配器的测试可以使用 `GuaTestHost` 进行相同的循环:
```csharp
using var ui = new GuaContext();
var host = new GuaTestHost(ui);
var loading = false;
host.Frame("title", frame =>
{
frame.Button("start", "Start Game", new GuaBounds(100, 100, 240, 64));
});
GuaAssertions.GetByRole(ui, "button", "Start Game").Click();
host.Frame("title", frame =>
{
frame.Button("start", "Start Game", new GuaBounds(100, 100, 240, 64));
});
host.DrainClickEvents(id => loading = id == "start");
host.Frame("loading", frame =>
{
if (loading)
{
frame.Text("loading", "Loading...", new GuaBounds(100, 180, 240, 24));
}
});
GuaAssertions.WaitForText(ui, "Loading...").ToBeVisible();
```
真正的 .NET 测试应该使用现有的测试运行器,例如 NUnit。`Gua.Testing` 不尝试成为 Vitest 风格的运行器;它在常规 NUnit 测试中提供 Gua 特定的定位器、等待、断言和适配器测试循环。一个 C# 文件可以包含多个 `[Test]` 方法:
```csharp
using Gua.Core;
using Gua.Testing;
using NUnit.Framework;
[TestFixture]
public sealed class TitleScreenTests
{
[Test]
public void StartClickShowsLoadingText()
{
using var _ = GuaAssertionScope.UseNUnit(Assert.Fail);
using var ui = new GuaContext();
var host = new GuaTestHost(ui);
host.Frame("title", frame =>
{
frame.Button("start", "Start Game", new GuaBounds(100, 100, 240, 64));
});
GuaAssertions.GetByRole(ui, "button", "Start Game").Click();
}
}
```
存储库中包含一个可运行的 NUnit 示例,位于 `examples/dotnet-nunit` 中。
Godot 场景测试可以使用 `Gua.Testing.Godot` 包启动 Godot 进程并断言 Gua 桥接器的实时连接:
```csharp
using var host = GodotSceneTestHost.Load("game/scenes/title_screen.tscn");
GuaAssertions.GetByRole(host.Context, "button", "開始").ToBeVisible();
host.Click("CenterPanel/Content/ButtonBox/StartButton", nextScene: "game/scenes/village_list.tscn");
GuaAssertions.GetByRole(host.Context, "button", "Create").ToBeVisible();
```
对于 v0.2.0 及更高版本,存储库本地的 `GuaLiveAssertions` 帮助程序可以直接迁移到 `WaitForId` / `WaitForText` / `WaitForVisible` / `WaitForEnabled`,定位器 `WaitForCount*` 和相关节点操作,例如 `ClickAsync`。等待返回的期望保留成功的完成帧快照;如果需要后续帧,请使用 `Refresh()` 或 `WaitUntil*`。存储库 `GodotHostFactory` 包装器应仅保留游戏特定的进程和夹具策略,而 `GodotSceneTestHost` 拥有可执行文件/项目发现、自动环回端口、渲染/无头启动、桥接器诊断和重置策略。所有 API 都在现有的 C ABI 和 WebSocket 协议上添加。
故障诊断可以通过与框架无关的 `GuaDiagnosticsSession` 进行协调。断言和已完成的操作使用相同的工件布局,返回类型化的绝对路径/媒体类型/次要捕获错误,并且可以通过回调附加。Godot 会话可以包括实时进程元数据、stdout/stderr、运行时版本和按需截图;成功的测试除非明确请求捕获,否则不会创建工件。
想在 GitHub Actions 中尝试此操作而无需手动配置每个设置步骤?[`link1345/gua-tester`](https://github.com/link1345/gua-tester) 为 Godot GDScript 项目提供可重用的操作。它在运行器上下载 Godot,将发布的 Gua Godot 插件链接到您的项目,设置 `GODOT_EXECUTABLE`,并运行使用 `Gua.Testing.Godot` 的 .NET 测试。
对于典型的消费者存储库,工作流程可以小到:
```yaml
- uses: link1345/gua-tester@v1
with:
project-path: game
test-project: tests/GuaTester.Tests.csproj
godot-version: "4.7"
godot-status: stable
```
如果您有一个启动 Gua 桥接器的 Godot 项目,请在 CI 中试用它,并查看语义 UI 树是否在问题落地之前捕获回归。
```cpp
context.log(gua::LogLevel::info, "title screen opened");
context.set_screenshot("data:image/png;base64,...", 1280, 720);
std::cout << context.ui_tree_json() << '\n';
std::cout << context.logs_json() << '\n';
std::cout << context.screenshot_json() << '\n';
```
```csharp
while (ui.TryPollEvent(out var e))
{
if (e.Type == GuaEventType.Click && e.NodeId == "start")
{
ShowLoading();
}
}
```
* Gua 不是游戏引擎。
* Gua 不是编辑器 MCP。
* Gua 不是图像识别 QA 机器人。
Gua 是游戏运行时和自动化工具之间的一座小桥。
## 范围
第一个实现专注于一个小而稳定的核心:
- 协议规范和 JSON 模式
- C ABI 运行时核心
- 薄的 C++ 包装器
- ImGui 适配器
- C++ 和 C# 测试帮助程序
- .NET P/Invoke 绑定到 C ABI
- 用于树、节点详细信息、截图、日志和运行时命令的检查器
- 用于 AI 代理访问运行时桥的 MCP 服务器
- 使用共享的本地运行时桥的 Godot 4.7 C# 示例
- 使用相同运行时桥的 Godot 4.7 GDScript 示例,通过 GDExtension
像 Unity、Unreal Engine、Godot 和 MonoGame 这样的引擎特定集成预计将作为适配器构建在协议之上,而不是项目的中心。
## 本机工具链
运行时兼容性可以通过附加的 C ABI `gua_copy_version_json`、WebSocket `get_version` 命令或 .NET `GetVersion()` 进行检查。响应遵循 `protocol/schema/version.schema.json` 并列出稳定的功能 ID。非 Godot 运行时将 `godotPluginVersion` 报告为 `null`;发布工作流程将发布版本和提交构建 ID 注入。
Windows 本机开发使用 MSVC 作为主要工具链:
```powershell
cmake --preset windows-msvc-debug
cmake --build --preset windows-msvc-debug
```
可移植边界仍然是 C ABI。macOS 和 iOS 应使用 Apple Clang,而 Android 应在添加这些目标时使用 Android NDK Clang。
## .NET 测试
.NET 包发布在 NuGet 上,也可以本地打包:
```powershell
dotnet pack bindings/dotnet/src/Gua.Core/Gua.Core.csproj --configuration Release
dotnet pack bindings/dotnet/src/Gua.Testing/Gua.Testing.csproj --configuration Release
```
包被写入 `artifacts/packages`。`Gua.Testing` 声明对匹配的 `Gua.Core` 包的 NuGet 依赖,因此测试项目只需要测试包:
```xml
<PackageReference Include="Gua.Testing" Version="0.5.0-preview.3" />
```
`Gua.Core` 也作为 NuGet 包交付,`Gua.Testing` 依赖于匹配的版本。Windows x64 本地运行时包含在 `Gua.Core` 下的 `runtimes/win-x64/native/gua.dll` 中,因此正常的包还原/生成会将其复制到使用它的应用程序或测试输出中。`GUA_NATIVE_DIR` 仍然作为本地构建的本地运行时覆盖。
运行独立的测试示例:
```powershell
cmake --preset windows-msvc-debug
cmake --build --preset windows-msvc-debug --target gua
$env:GUA_NATIVE_DIR = "$PWD\build\windows-msvc-debug\native\gua-core\Debug"
dotnet run --project examples/dotnet-testing/GuaDotNetTestingSample.csproj
```
运行 NUnit 测试示例:
```powershell
cmake --preset windows-msvc-release
cmake --build --preset windows-msvc-release --target gua
dotnet pack bindings/dotnet/src/Gua.Core/Gua.Core.csproj --configuration Release
dotnet pack bindings/dotnet/src/Gua.Testing/Gua.Testing.csproj --configuration Release
dotnet test examples/dotnet-nunit/GuaDotNetNUnitSample.csproj
```
## 检查器
检查器是一个 React 应用程序,它使用 Gua 协议快照。可以连接模拟数据、WebSocket 桥、HTTP 桥、MCP、保存的文件或本机运行时桥。
运行浏览器版本:
```powershell
bun run --filter @gua/inspector dev
```
在另一个终端中运行示例 WebSocket 桥:
```powershell
bun run bridge:ws
```
或者构建并运行提供真实 `gua::Context` 的本机 C++ 桥:
```powershell
cmake --preset windows-msvc-debug
cmake --build --preset windows-msvc-debug --target gua-native-bridge-example
.\build\windows-msvc-debug\examples\native-bridge\Debug\gua-native-bridge-example.exe
```
ImGui 示例还在 UI 运行时托管相同的 WebSocket 桥:
```powershell
cmake --preset windows-msvc-debug
cmake --build --preset windows-msvc-debug --target gua-cpp-imgui-example
.\build\windows-msvc-debug\examples\cpp-imgui\Debug\gua-cpp-imgui-example.exe
```
然后连接到:
```text
ws://127.0.0.1:8765
```
ImGui 桥在 UI 运行时推送快照通知,因此检查器在不轮询的情况下更新。检查器中的 `Poll` 切换保持为仅实现请求/响应的桥的备用。
桥使用 Gua 运行时适配器使用的相同 JSON 命令形状:
```json
{ "id": 1, "type": "get_ui_tree" }
{ "id": 2, "type": "click_node", "nodeId": "start" }
```
构建静态检查器:
```powershell
bun run --filter @gua/inspector build
```
在开发过程中运行 Tauri 桌面外壳:
```powershell
bun run --filter @gua/inspector tauri:dev
```
Tauri 需要除 JavaScript 依赖项之外的 Rust 工具链。
## MCP
MCP 服务器是通过检查器使用的相同桥接器上的一个薄协议消费者。首先启动运行时桥:
```powershell
bun run bridge:ws
```
然后在标准输入/输出上运行 MCP 服务器:
```powershell
bun run mcp
```
MCP 服务器作为 `gui-mcp` 发布到 npm。MCP 客户端可以使用以下命令启动它:
```powershell
bunx gui-mcp@latest mcp
```
默认情况下,它连接到 `ws://127.0.0.1:8765`。为另一个运行时适配器覆盖它:
```powershell
$env:GUA_BRIDGE_URL = "ws://127.0.0.1:8765"
bunx gui-mcp@latest mcp
```
MCP 工具表面:
```text
get_ui_tree
click_node
press_key
wait_for_node
get_screenshot
get_logs
run_test
```
## 发布自动化
GitHub Actions 从 `main` 发布运行时工件,当相关的协议使用者发生更改时。检查器、Godot 插件和 ImGui 插件一起构建,并附加到一个版本化的 `gua-v*` GitHub 发布。MCP 和 .NET 包继续使用它们独立的 npm 和 NuGet 发布工作流程。
MCP 工作流程使用 npm 信任发布通过 GitHub Actions OIDC。`gui-mcp` 包必须在此存储库、`.github/workflows/mcp-publish.yml` 工作流程和 `release` 环境中配置 npm。
## Godot 4.7 C# 示例
v0.5 C# 运行时示例位于 `examples/dotnet-godot` 中。它是一个最小的 Godot 4.7 项目,使用 `Godot.NET.Sdk/4.7.0`、`net10.0`、项目引用到 `Gua.Core` 和 `Gua.Testing`,以及 `addons/gua` 中的运行时插件。
使用以下命令构建:
```powershell
dotnet build examples/dotnet-godot/GuaGodotSample.csproj -v:minimal
```
示例使用来自插件的 `Gua.Godot.GuaGodotRuntime`,将其附加到根 Godot `Control`,并在 `ws://127.0.0.1:8765` 上启动检查器桥。适配器收集标准控件到语义树中,并通过正常的 Godot 按钮信号调度外部点击请求。
`examples/dotnet-monogame` 仍然作为未来占位符存在。
## Godot 4.7 GDScript 插件
面向 GDScript 的适配器位于 `native/gua-godot` 中,并为 `native/gua-runtime` 构建了一个薄的 GDExtension 包装器。它将 `GuaContext` 公开给 GDScript,而无需重新实现运行时核心或检查器桥:
```gdscript
var ui := GuaContext.new()
ui.begin_frame("title")
ui.register_node("start", "button", "Start Game", Rect2(512, 312, 256, 56), true, true)
ui.end_frame()
ui.start_inspector_bridge(8765)
ui.enqueue_click("start")
while true:
var event := ui.poll_event()
if event.is_empty():
break
```
构建 Windows 调试 GDExtension:
```powershell
cmake --preset windows-msvc-debug
cmake --build --preset windows-msvc-debug --target gua-godot
```
构建将调试 DLL 写入 `examples/godot-gdscript/addons/gua/bin`。使用 Godot 4.7 打开 `examples/godot-gdscript` 并运行项目。正在运行的游戏进程在 `ws://127.0.0.1:8765` 上启动了一个检查器桥接器,Gua 检查器可以连接到它,而游戏是打开的。插件包含 `plugin.cfg` 仅用于标准的 Godot 插件打包;Gua 的运行时 API 由 `gua.gdextension` 提供,而不是编辑器 MCP。
对于游戏脚本,通过显式预加载而不是依赖于 `class_name` 注册顺序,在实例化 GDScript 适配器:
```gdscript
const GuaAutoAdapterScript := preload("res://addons/gua/gua_auto_adapter.gd")
var ui := GuaAutoAdapterScript.new()
```
适配器在第一次使用时通过 `ClassDB` 解析本机 `GuaContext` 类,并在调度检查器点击请求之前验证存在诸如 `consume_click_request` 之类的必需方法。如果检查失败,请重新构建 `gua-godot`;问题出在陈旧的已编译 DLL 上,而不是游戏脚本。
使用以下命令运行 GDScript 烟雾测试:
```powershell
C:\Users\testk\.local\bin\Godot_v4.7-stable_win64_console.exe --headless --path examples/godot-gdscript --script res://scripts/gua_smoke.gd
```
## 存储库布局
```text
protocol/ 协议规范和 JSON 模式
native/gua-core/ C ABI 运行时核心和 C++ 参考实现
native/gua-runtime/ Godot C# 和 GDScript 的共享本机运行时桥
native/gua-imgui/ ImGui 适配器层
native/gua-testing/ C ABI 上的 C++ 测试帮助程序
native/gua-godot/ GDScript 的 Godot GDExtension 适配器
bindings/dotnet/ .NET P/Invoke 绑定和 C# 测试帮助程序
bindings/dotnet/src/Gua.Testing.Godot/
Godot 进程测试帮助程序,基于 Gua.Testing
packages/mcp/ 已发布的 MCP 服务器包
packages/inspector/ 浏览器和 Tauri 桌面检查器 UI
examples/ 最小演示和示例,包括 Godot C# 示例
docs/ 本机工具链指导
```
## 许可
MIT
连接信息
猜你喜欢
暂无推荐服务器