mirror of
https://github.com/layue13/MoonBridge.git
synced 2026-10-25 18:46:18 +00:00
refactor: 仓库根目录按用途分组
- proxy/:core、plugin-api、luckperms 及其上游子模块 vendor/luckperms - messaging/、backend/ 保持在根目录(messaging 是代理与后端共用的 API) - build-logic/(原 proxy-build-logic) - testing/:smoke/ 与 benchmarks/,不进入发行物 Gradle 项目名不变(settings.gradle.kts 映射目录),任务路径与 Maven 坐标照旧。 脚本的仓库根定位、文档与记录中的链接同步更新。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7664c1cf60
commit
789648c82f
369 files changed
+188
-160
No files matched your search
+2
-2
@@ -1,3 +1,3 @@
|
||||
[submodule "vendor/luckperms"]
|
||||
path = vendor/luckperms
|
||||
[submodule "proxy/vendor/luckperms"]
|
||||
path = proxy/vendor/luckperms
|
||||
url = https://github.com/LuckPerms/LuckPerms.git
|
||||
@@ -8,7 +8,7 @@ MoonBridge is a session proxy for Minecraft 1.7.10 Forge (protocol 5): login/aut
|
||||
|
||||
JDK 25 is required (Gradle toolchain; the daemon JVM is pinned to 25). Use `./gradlew` (`.\gradlew.bat` on Windows).
|
||||
|
||||
The LuckPerms platform plugin compiles LuckPerms from the `vendor/luckperms` submodule, which is slow and download-heavy, so it is opt-in: `-Pluckperms` includes `luckperms-moonbridge`, its tests, `permissionAcceptance` and the plugin in the distribution (run `git submodule update --init --recursive` first). CI always passes it; run it locally when touching permissions, plugin loading or the distribution layout.
|
||||
The LuckPerms platform plugin compiles LuckPerms from the `proxy/vendor/luckperms` submodule, which is slow and download-heavy, so it is opt-in: `-Pluckperms` includes `luckperms-moonbridge`, its tests, `permissionAcceptance` and the plugin in the distribution (run `git submodule update --init --recursive` first). CI always passes it; run it locally when touching permissions, plugin loading or the distribution layout.
|
||||
|
||||
```sh
|
||||
./gradlew check # tests, installed-dist smoke tests, benchmark compile
|
||||
@@ -17,7 +17,7 @@ The LuckPerms platform plugin compiles LuckPerms from the `vendor/luckperms` sub
|
||||
./gradlew :proxy-core:test # proxy-core tests only
|
||||
./gradlew :proxy-core:test --tests '*RawRelayTest' # one class
|
||||
./gradlew :proxy-core:test --tests '*RawRelayTest.m' # one method
|
||||
./gradlew :proxy-core:installDist # runnable distribution in proxy-core/build/install/moonbridge
|
||||
./gradlew :proxy-core:installDist # runnable distribution in proxy/core/build/install/moonbridge
|
||||
```
|
||||
|
||||
The slow tests are the session integration tests (`ProxySessionListenerTest`, `SessionTransferTest`, `InitialRoutingTest`, `SourceReleaseTransferTest`); iterate with `--tests` and run `check` once before pushing.
|
||||
@@ -26,14 +26,24 @@ The slow tests are the session integration tests (`ProxySessionListenerTest`, `S
|
||||
|
||||
## Modules
|
||||
|
||||
Directories group the modules by side; Gradle project names stay flat, so task paths and Maven artifact IDs are the same as the names below. `settings.gradle.kts` maps each name to its directory.
|
||||
|
||||
```
|
||||
proxy/core proxy-core proxy/plugin-api proxy-plugin-api
|
||||
proxy/luckperms luckperms-moonbridge proxy/vendor/luckperms (submodule)
|
||||
messaging messaging backend backend
|
||||
client-mod/ separate build build-logic/ convention plugins (included build)
|
||||
testing/smoke/ smoke scripts and dated records; testing/benchmarks/ likewise. Never packaged.
|
||||
```
|
||||
|
||||
- `proxy-core` — the proxy runtime (`dev.moonbridge.app` = startup/config, `dev.moonbridge.core.*` = everything else). The only module that uses Netty.
|
||||
- `proxy-plugin-api` — the stable plugin boundary. Plugins are discovered with `META-INF/services/dev.moonbridge.api.Plugin` and loaded in separate class loaders by `PluginHost`.
|
||||
- `messaging` — message envelope, channel API and wire codec shared by the proxy and backends.
|
||||
- `backend` — the Bukkit/Uranium host plugin `MoonBridgeBackend` (its jar bundles `messaging`), its service API (`dev.moonbridge.bukkit`) and the control channel client (`dev.moonbridge.backendchannel`). Business plugins compile against this jar `compileOnly`.
|
||||
- `messaging` and `backend` use `moonbridge.java8-library-conventions` (`--release 8`, for Java 8 backends such as Uranium) and must not pull in newer APIs.
|
||||
- `luckperms-moonbridge` — native LuckPerms platform plugin, built from `vendor/luckperms` via the included build `luckperms-moonbridge/upstream-build`; only included with `-Pluckperms`.
|
||||
- `luckperms-moonbridge` — native LuckPerms platform plugin, built from `proxy/vendor/luckperms` via the included build `proxy/luckperms/upstream-build`; only included with `-Pluckperms`.
|
||||
- `client-mod/` — the 1.7.10 Forge WebSocket client mod. A separate Gradle build (GTNH template, RetroFuturaGradle, Mixins) with its own wrapper: `cd client-mod && ./gradlew build`. Its `net` package is free of Minecraft classes and uses Minecraft's bundled Netty 4.0.10.
|
||||
- `proxy-build-logic` — Kotlin convention plugins: `java-library`, `java8-library`, `application`, and `publishing-conventions` (shared package repository; set `moonbridgePublication { artifactId ... }` for a standard publication).
|
||||
- `build-logic` — Kotlin convention plugins: `java-library`, `java8-library`, `application`, and `publishing-conventions` (shared package repository; set `moonbridgePublication { artifactId ... }` for a standard publication).
|
||||
|
||||
## Architecture that spans files
|
||||
|
||||
@@ -58,4 +68,4 @@ The slow tests are the session integration tests (`ProxySessionListenerTest`, `S
|
||||
|
||||
## Performance work
|
||||
|
||||
Benchmarks live in `benchmarks/` (`ProxySessionBenchmark`, PowerShell runners; on Linux compile it against `proxy-core/build/install/moonbridge/lib` and run `java --enable-native-access=ALL-UNNAMED -cp ... dev.moonbridge.core.session.ProxySessionBenchmark --burst 32 --window 4 --transport epoll`). The existing records show the house method: set the decision rule first, rotate variant order across JVM runs, report median and range, keep raw output next to a dated `benchmarks/results/*.md` that states what it does not cover, and prefer profile samples (JFR) over overlapping throughput ranges. Single-host loopback numbers are never capacity claims.
|
||||
Benchmarks live in `testing/benchmarks/` (`ProxySessionBenchmark`, PowerShell runners; on Linux compile it against `proxy/core/build/install/moonbridge/lib` and run `java --enable-native-access=ALL-UNNAMED -cp ... dev.moonbridge.core.session.ProxySessionBenchmark --burst 32 --window 4 --transport epoll`). The existing records show the house method: set the decision rule first, rotate variant order across JVM runs, report median and range, keep raw output next to a dated `testing/benchmarks/results/*.md` that states what it does not cover, and prefer profile samples (JFR) over overlapping throughput ranges. Single-host loopback numbers are never capacity claims.
|
||||
@@ -19,14 +19,14 @@
|
||||
|
||||
```sh
|
||||
./gradlew check :proxy-core:installDist # Windows: .\gradlew.bat check :proxy-core:installDist
|
||||
cd proxy-core/build/install/moonbridge
|
||||
cd proxy/core/build/install/moonbridge
|
||||
bin/moonbridge --validate-config config/moonbridge.yml # Windows: bin\moonbridge.bat
|
||||
bin/moonbridge --config config/moonbridge.yml
|
||||
```
|
||||
|
||||
需要全部部署物(服务器包、后端插件、客户端 mod)时运行 `./gradlew release`,说明见[发行物与安装位置](docs/release-layout.md)。LuckPerms 平台插件从 `vendor/luckperms` 子模块编译,默认不构建;需要时先 `git submodule update --init --recursive`,再加 `-Pluckperms`。
|
||||
需要全部部署物(服务器包、后端插件、客户端 mod)时运行 `./gradlew release`,说明见[发行物与安装位置](docs/release-layout.md)。LuckPerms 平台插件从 `proxy/vendor/luckperms` 子模块编译,默认不构建;需要时先 `git submodule update --init --recursive`,再加 `-Pluckperms`。
|
||||
|
||||
默认配置为 `OFFLINE`,仅监听 `127.0.0.1:25577`。公开部署使用 `ONLINE_BUNGEE` 并限制玩家直连后端;认证、监听、入口候选和后端地址见[运行配置](docs/operations.md)。发行包根目录附带 `docs/` 与按日期归档的 `smoke/results/`、`benchmarks/results/`。
|
||||
默认配置为 `OFFLINE`,仅监听 `127.0.0.1:25577`。公开部署使用 `ONLINE_BUNGEE` 并限制玩家直连后端;认证、监听、入口候选和后端地址见[运行配置](docs/operations.md)。
|
||||
|
||||
## 后端插件开发
|
||||
|
||||
@@ -36,6 +36,6 @@ bin/moonbridge --config config/moonbridge.yml
|
||||
|
||||
## 验证状态
|
||||
|
||||
当前可引用的验收记录及其覆盖范围见[文档索引](docs/README.md#当前可引用的验证记录)和[验证方法](docs/testing.md)。各记录只证明其注明的提交和环境,不代表生产容量。已知 Uranium 候选服登录停滞见[记录](smoke/results/2026-09-26-uranium-login-stalls.md)及 [Uranium #585](https://git.nest.potatolab.uk:8443/TDLM/Uranium/issues/585)。
|
||||
当前可引用的验收记录及其覆盖范围见[文档索引](docs/README.md#当前可引用的验证记录)和[验证方法](docs/testing.md)。各记录只证明其注明的提交和环境,不代表生产容量。已知 Uranium 候选服登录停滞见[记录](testing/smoke/results/2026-09-26-uranium-login-stalls.md)及 [Uranium #585](https://git.nest.potatolab.uk:8443/TDLM/Uranium/issues/585)。
|
||||
|
||||
生产权限存储统一使用 MariaDB 13.0.2;见 [MariaDB 权限数据库](docs/mariadb.md)。
|
||||
File renamed without changes.
@@ -5,4 +5,4 @@ dependencyResolutionManagement {
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "proxy-build-logic"
|
||||
rootProject.name = "build-logic"
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+4
-4
@@ -6,7 +6,7 @@
|
||||
|
||||
- 要运行 Proxy:先看[运行配置](operations.md),再按部署需求修改认证方式、入口候选和后端地址。
|
||||
- 要开发插件:先看[插件开发](plugins.md);后端 Bukkit 插件另看[后端 Channel 接入](backend-channel-design.md#后端插件接入)。
|
||||
- 要理解初次登录为什么拒绝或如何重试:看[初次登录路由](initial-routing.md)及其[专项验收记录](../smoke/results/2026-09-27-initial-routing.md)。
|
||||
- 要理解初次登录为什么拒绝或如何重试:看[初次登录路由](initial-routing.md)及其[专项验收记录](../testing/smoke/results/2026-09-27-initial-routing.md)。
|
||||
- 要核对证据覆盖面:看[验证方法](testing.md),并按各记录注明的日期、提交、环境和探针类型判断。
|
||||
|
||||
| 文档 | 内容 |
|
||||
@@ -28,8 +28,8 @@
|
||||
|
||||
## 当前可引用的验证记录
|
||||
|
||||
- [初次路由专项验收](../smoke/results/2026-09-27-initial-routing.md):自动化路由覆盖与真实 Java 8 Uranium 后端协议探针;不是完整 Prism 模组包视觉验收。
|
||||
- [MoonBridge 后端 API 验收](../smoke/results/2026-09-27-moonbridge-api.md):隔离 Uranium 服务端中的 Bukkit 宿主和 API 功能验收;无玩家。
|
||||
- [2026-09-26 Prism 历史记录](../benchmarks/results/2026-09-26-prism-pack.md):真实客户端及配对测量,仅适用于该记录描述的代码版本和环境。
|
||||
- [初次路由专项验收](../testing/smoke/results/2026-09-27-initial-routing.md):自动化路由覆盖与真实 Java 8 Uranium 后端协议探针;不是完整 Prism 模组包视觉验收。
|
||||
- [MoonBridge 后端 API 验收](../testing/smoke/results/2026-09-27-moonbridge-api.md):隔离 Uranium 服务端中的 Bukkit 宿主和 API 功能验收;无玩家。
|
||||
- [2026-09-26 Prism 历史记录](../testing/benchmarks/results/2026-09-26-prism-pack.md):真实客户端及配对测量,仅适用于该记录描述的代码版本和环境。
|
||||
|
||||
设计约束:核心管理连接和协议;插件负责玩法与访问策略。`ServerView` 是后端目录快照,发现方式是目录的提供者,不引入核心负载观测。准入与会话通知使用同一事件类型、监听器和注册表;不同事件在派发策略上处理结果。常规 PLAY 转发没有通用事件派发。
|
||||
+20
-7
@@ -4,12 +4,25 @@
|
||||
|
||||
## 模块
|
||||
|
||||
仓库按用途分目录,Gradle 项目名保持不变(任务路径与 Maven 坐标照旧):
|
||||
|
||||
| 目录 | Gradle 项目 | 内容 |
|
||||
| --- | --- | --- |
|
||||
| `proxy/core` | `proxy-core` | 代理运行时 |
|
||||
| `proxy/plugin-api` | `proxy-plugin-api` | 代理插件 API |
|
||||
| `proxy/luckperms`、`proxy/vendor/luckperms` | `luckperms-moonbridge` | LuckPerms 平台插件及其上游子模块(`-Pluckperms`) |
|
||||
| `messaging` | `messaging` | 代理与后端共用的消息 API 与线协议 |
|
||||
| `backend` | `backend` | Bukkit/Uranium 后端宿主 |
|
||||
| `client-mod` | 独立构建 | 1.7.10 WebSocket 客户端 mod |
|
||||
| `build-logic` | 包含构建 | Gradle 约定插件 |
|
||||
| `testing/smoke`、`testing/benchmarks` | — | 烟测脚本、基准与按日期归档的记录;不进入发行物 |
|
||||
|
||||
- `proxy-plugin-api` 定义插件外部接口:生命周期、玩家/服务器只读视图、后端注册、类型化事件、初始选服、命令和转服。核心实现位于 `proxy-core`;可选发现器位于 `plugins/`。
|
||||
- `ProxyMain` 读取严格 YAML 配置,先注册静态后端,再加载配置启用的插件,连接插件选服回调,最后启动 Netty 监听器。插件以 `META-INF/services/dev.moonbridge.api.Plugin` 声明,通过独立类加载器加载。
|
||||
- 后端一侧只有两个 Java 8 模块:`messaging`(消息 API 与线协议,代理与后端共用)和 `backend`(Bukkit/Uranium 共享宿主 `MoonBridgeBackend`、其服务 API 与控制通道客户端,打成一个 JAR)。`luckperms-moonbridge` 是可选的原生权限插件(`-Pluckperms` 构建);`client-mod/` 是独立构建的 1.7.10 客户端 WebSocket mod。
|
||||
- 核心支持 Minecraft 1.7.10(协议 5)登录和转发。`OFFLINE` 信任客户端提交的名字;`ONLINE_BUNGEE` 在代理执行加密与会话验证,并将身份转发给受信任的旧版 Bungee 后端。
|
||||
|
||||
入口可从 [`ProxyMain`](../proxy-core/src/main/java/dev/moonbridge/app/ProxyMain.java)、[`ProxySessionListener`](../proxy-core/src/main/java/dev/moonbridge/core/session/ProxySessionListener.java) 和 [`PluginHost`](../proxy-core/src/main/java/dev/moonbridge/core/plugin/PluginHost.java) 追踪。
|
||||
入口可从 [`ProxyMain`](../proxy/core/src/main/java/dev/moonbridge/app/ProxyMain.java)、[`ProxySessionListener`](../proxy/core/src/main/java/dev/moonbridge/core/session/ProxySessionListener.java) 和 [`PluginHost`](../proxy/core/src/main/java/dev/moonbridge/core/plugin/PluginHost.java) 追踪。
|
||||
|
||||
## 会话与连接生命周期
|
||||
|
||||
@@ -31,7 +44,7 @@ flowchart LR
|
||||
F --> G[PLAY / Forge 握手与转发]
|
||||
```
|
||||
|
||||
普通转发沿用协议 5 帧边界,不重新编码普通帧;同一次 socket 读取解码出的帧逐个写入对端,在读取完成时合并为一次 flush,读取之外转发的帧由每批一次的事件循环任务补发 flush。前后端通道绑定同一 Netty EventLoop,会话控制状态在该循环串行变更。Keep Alive ID 由代理转换并跟踪未完成请求;必要的玩家实体 ID 数据包在转服后改写。通道不可写时通过暂停对端读取施加背压。实现见 [`Session`](../proxy-core/src/main/java/dev/moonbridge/core/session/Session.java)、[`RawRelay`](../proxy-core/src/main/java/dev/moonbridge/core/session/play/RawRelay.java) 与 [`KeepAliveBridge`](../proxy-core/src/main/java/dev/moonbridge/core/session/play/KeepAliveBridge.java)。
|
||||
普通转发沿用协议 5 帧边界,不重新编码普通帧;同一次 socket 读取解码出的帧逐个写入对端,在读取完成时合并为一次 flush,读取之外转发的帧由每批一次的事件循环任务补发 flush。前后端通道绑定同一 Netty EventLoop,会话控制状态在该循环串行变更。Keep Alive ID 由代理转换并跟踪未完成请求;必要的玩家实体 ID 数据包在转服后改写。通道不可写时通过暂停对端读取施加背压。实现见 [`Session`](../proxy/core/src/main/java/dev/moonbridge/core/session/Session.java)、[`RawRelay`](../proxy/core/src/main/java/dev/moonbridge/core/session/play/RawRelay.java) 与 [`KeepAliveBridge`](../proxy/core/src/main/java/dev/moonbridge/core/session/play/KeepAliveBridge.java)。
|
||||
|
||||
## 后端目录与发现所有权
|
||||
|
||||
@@ -43,7 +56,7 @@ flowchart LR
|
||||
|
||||
## 转服、并发与错误边界
|
||||
|
||||
转服先在旧后端保持服务的同时连接并登录候选后端。普通后端在 Join Game 后可进入切换;Forge 候选后端要等待客户端 Forge 握手链路切换及 Join Game,再进行世界切换。交接期间客户端与旧后端帧分别进入有上限的缓冲区;切换前失败时尽可能恢复旧链路并回放暂存帧,成功时改用候选链路并清理旧链路。候选连接失败不会立即破坏旧链路;Forge 客户端切换包写出后若目标拒绝或超时,旧链路无法安全恢复,代理会关闭会话。`NETWORK_READY` 只表示协议握手和代理发出的世界切换已完成,不表示目标服插件或玩法世界已准备好。接口定义见 [`Players`](../proxy-plugin-api/src/main/java/dev/moonbridge/api/Players.java)、状态见 [`TransferStatus`](../proxy-plugin-api/src/main/java/dev/moonbridge/api/TransferStatus.java)。
|
||||
转服先在旧后端保持服务的同时连接并登录候选后端。普通后端在 Join Game 后可进入切换;Forge 候选后端要等待客户端 Forge 握手链路切换及 Join Game,再进行世界切换。交接期间客户端与旧后端帧分别进入有上限的缓冲区;切换前失败时尽可能恢复旧链路并回放暂存帧,成功时改用候选链路并清理旧链路。候选连接失败不会立即破坏旧链路;Forge 客户端切换包写出后若目标拒绝或超时,旧链路无法安全恢复,代理会关闭会话。`NETWORK_READY` 只表示协议握手和代理发出的世界切换已完成,不表示目标服插件或玩法世界已准备好。接口定义见 [`Players`](../proxy/plugin-api/src/main/java/dev/moonbridge/api/Players.java)、状态见 [`TransferStatus`](../proxy/plugin-api/src/main/java/dev/moonbridge/api/TransferStatus.java)。
|
||||
|
||||
主要并发和失败界限:
|
||||
|
||||
@@ -80,7 +93,7 @@ flowchart LR
|
||||
|
||||
## 相关源码
|
||||
|
||||
- 插件 API:[`PluginContext`](../proxy-plugin-api/src/main/java/dev/moonbridge/api/PluginContext.java)、[`Servers`](../proxy-plugin-api/src/main/java/dev/moonbridge/api/Servers.java)、[`Players`](../proxy-plugin-api/src/main/java/dev/moonbridge/api/Players.java)
|
||||
- 会话和转服:[`Session`](../proxy-core/src/main/java/dev/moonbridge/core/session/Session.java)、[`TransferCandidate`](../proxy-core/src/main/java/dev/moonbridge/core/session/transfer/TransferCandidate.java)、[`TransferFrameBuffer`](../proxy-core/src/main/java/dev/moonbridge/core/session/transfer/TransferFrameBuffer.java)
|
||||
- 目录:[`BackendCatalog`](../proxy-core/src/main/java/dev/moonbridge/core/backend/BackendCatalog.java)、[`InMemoryBackendCatalog`](../proxy-core/src/main/java/dev/moonbridge/core/backend/InMemoryBackendCatalog.java)
|
||||
- 后端控制通道:[`BackendControlService`](../proxy-core/src/main/java/dev/moonbridge/core/control/BackendControlService.java)
|
||||
- 插件 API:[`PluginContext`](../proxy/plugin-api/src/main/java/dev/moonbridge/api/PluginContext.java)、[`Servers`](../proxy/plugin-api/src/main/java/dev/moonbridge/api/Servers.java)、[`Players`](../proxy/plugin-api/src/main/java/dev/moonbridge/api/Players.java)
|
||||
- 会话和转服:[`Session`](../proxy/core/src/main/java/dev/moonbridge/core/session/Session.java)、[`TransferCandidate`](../proxy/core/src/main/java/dev/moonbridge/core/session/transfer/TransferCandidate.java)、[`TransferFrameBuffer`](../proxy/core/src/main/java/dev/moonbridge/core/session/transfer/TransferFrameBuffer.java)
|
||||
- 目录:[`BackendCatalog`](../proxy/core/src/main/java/dev/moonbridge/core/backend/BackendCatalog.java)、[`InMemoryBackendCatalog`](../proxy/core/src/main/java/dev/moonbridge/core/backend/InMemoryBackendCatalog.java)
|
||||
- 后端控制通道:[`BackendControlService`](../proxy/core/src/main/java/dev/moonbridge/core/control/BackendControlService.java)
|
||||
@@ -25,7 +25,7 @@ flowchart LR
|
||||
|
||||
## 后端插件接入
|
||||
|
||||
在 Bukkit/Uranium 后端安装一次 `backend` 模块生成的 `moonbridge-backend` JAR(发行包 `backend/` 目录),插件名为 `MoonBridgeBackend`。配置唯一的实例 ID、后端名称、代理控制地址、游戏地址与凭据。宿主异步建立连接,不在启动主线程等待网络。
|
||||
在 Bukkit/Uranium 后端安装一次 `backend` 模块生成的 `moonbridge-backend` JAR(`gradlew release` 输出的 `backend/` 目录),插件名为 `MoonBridgeBackend`。配置唯一的实例 ID、后端名称、代理控制地址、游戏地址与凭据。宿主异步建立连接,不在启动主线程等待网络。
|
||||
|
||||
消费者 `plugin.yml` 声明:
|
||||
|
||||
@@ -100,7 +100,7 @@ Proxy 为每个插件管理独立的 scope,在停用时自动撤销。项目
|
||||
|
||||
## 配置与部署
|
||||
|
||||
代理在 `backendChannel.listen` 启动独立监听器。配置示例见 [moonbridge-channel.example.yml](../proxy-core/src/main/resources/config/moonbridge-channel.example.yml)。每个实例的 `secret` 至少 32 个 UTF-8 字节,`allowedHosts` 限制其广告游戏地址;`allowedNamespaces` 控制发送,`allowedReceiveNamespaces` 控制接收,未配置接收列表时继承发送列表,显式空列表表示禁止该方向的所有消息。跨后端路由同时检查源发送权限与目的接收权限。Channel registration v3 将代理启动 epoch 和 backend registration epoch 同时交给后端。代理用该 backend client secret 为发往该 backendName 的 legacy forwarding handshake 生成短时 HMAC 会话证明;证明绑定两端当前 epoch、backendName、UUID、connectionId、一次性 nonce 和到期时间。后端 `MoonBridgeBackend` 校验它并把会话绑定到实际 Bukkit Player 登录对象。两端身份或 secret 不匹配、registration 未完成或 epoch 已变化时,`BukkitSessionService.find(player)` 返回空值。证明不代表任何 AetherShard 操作。
|
||||
代理在 `backendChannel.listen` 启动独立监听器。配置示例见 [moonbridge-channel.example.yml](../proxy/core/src/main/resources/config/moonbridge-channel.example.yml)。每个实例的 `secret` 至少 32 个 UTF-8 字节,`allowedHosts` 限制其广告游戏地址;`allowedNamespaces` 控制发送,`allowedReceiveNamespaces` 控制接收,未配置接收列表时继承发送列表,显式空列表表示禁止该方向的所有消息。跨后端路由同时检查源发送权限与目的接收权限。Channel registration v3 将代理启动 epoch 和 backend registration epoch 同时交给后端。代理用该 backend client secret 为发往该 backendName 的 legacy forwarding handshake 生成短时 HMAC 会话证明;证明绑定两端当前 epoch、backendName、UUID、connectionId、一次性 nonce 和到期时间。后端 `MoonBridgeBackend` 校验它并把会话绑定到实际 Bukkit Player 登录对象。两端身份或 secret 不匹配、registration 未完成或 epoch 已变化时,`BukkitSessionService.find(player)` 返回空值。证明不代表任何 AetherShard 操作。
|
||||
|
||||
在 `OFFLINE` 代理模式中,只有显式配置了该 backend 的 session-binding secret 时,代理才会在初始连接或转服时转发由代理派生的 offline UUID 和会话证明;这证明代理连接身份,不表示 Mojang 已认证。没有配置 secret 的 offline backend 仍接收原始握手。静态 backend 或尚未获得正数 registration epoch 的目标不会收到会话证明。
|
||||
|
||||
@@ -114,7 +114,7 @@ HMAC 挑战认证本身不加密链路;跨机器使用私有加密链路或可
|
||||
|
||||
自动化验证针对 Java 8 API/宿主字节码、宿主 JAR 打包边界、真实 TCP 的零玩家双向及跨后端请求、发布、多插件关闭、并发回复关联、超时与异常帧。构建和独立 TCP 测试不能代替真实 Bukkit/Uranium 装载、玩家整合包验收或生产容量测试。
|
||||
|
||||
本次构建、244 项回归和实际 Java 8 进程的结果见 [2026-09-27 验证记录](../smoke/results/2026-09-27-channel-messaging.md)。
|
||||
本次构建、244 项回归和实际 Java 8 进程的结果见 [2026-09-27 验证记录](../testing/smoke/results/2026-09-27-channel-messaging.md)。
|
||||
|
||||
安装发行包的 `backend/` 提供共享宿主 JAR;它同时包含非 Bukkit 宿主所需的控制通道客户端、消息 API 和协议。运行 `:proxy-core:installDist` 后,可用实际 JDK 8 运行独立进程验收:
|
||||
|
||||
|
||||
@@ -84,4 +84,4 @@ initialRouting:
|
||||
|
||||
这些是验收要求而不是本文件对运行时通过状态的声明。自动化测试、隔离协议烟测、真实后端登录与完整客户端/Forge 登录属于不同证据层级;各自结果必须单独记录。
|
||||
|
||||
本次专项测试与真实 Uranium 协议登录结果见[验收记录](../smoke/results/2026-09-27-initial-routing.md)。
|
||||
本次专项测试与真实 Uranium 协议登录结果见[验收记录](../testing/smoke/results/2026-09-27-initial-routing.md)。
|
||||
+7
-7
@@ -22,19 +22,19 @@ PDS、AetherShard 与 LuckPerms 可以使用同一台 MariaDB 服务,各自保
|
||||
git submodule update --init --recursive
|
||||
bash ./gradlew clean check :proxy-core:distZip --no-daemon --max-workers=2
|
||||
mkdir -p build/permission-network-classes
|
||||
javac -cp 'proxy-core/build/install/moonbridge/lib/*' -d build/permission-network-classes smoke/PermissionNetworkAcceptance.java
|
||||
node smoke/permission-services.cjs start
|
||||
javac -cp 'proxy/core/build/install/moonbridge/lib/*' -d build/permission-network-classes testing/smoke/PermissionNetworkAcceptance.java
|
||||
node testing/smoke/permission-services.cjs start
|
||||
```
|
||||
|
||||
运行下面两轮后,务必执行 stop(失败也需清理):
|
||||
|
||||
```sh
|
||||
node smoke/permission-network.cjs sql outage
|
||||
node smoke/permission-network.cjs redis outage
|
||||
node smoke/permission-services.cjs query
|
||||
node smoke/permission-services.cjs stop
|
||||
node testing/smoke/permission-network.cjs sql outage
|
||||
node testing/smoke/permission-network.cjs redis outage
|
||||
node testing/smoke/permission-services.cjs query
|
||||
node testing/smoke/permission-services.cjs stop
|
||||
```
|
||||
|
||||
fixture 只创建带本轮所有权标签的本机容器,固定使用 `mariadb:13.0.2` 并检查实际服务器版本。SQL 模式使用 MariaDB 原生自动 SQL messenger;Redis 模式仍使用 MariaDB 保存权限。测试执行双实例授权/撤销/组继承、上下文、临时权限、插件重启持久化,以及 MariaDB/Redis 停机恢复。普通构建不会自动执行这些外部服务测试。
|
||||
|
||||
stop 删除本轮容器和数据卷、移除凭据文件,并对保留的测试配置密码脱敏。[当前验收记录](../smoke/results/2026-10-02-mariadb.md) 与早期 MySQL/H2/游戏客户端证据分别记录,避免将旧运行结果当成本次 MariaDB 联测。
|
||||
stop 删除本轮容器和数据卷、移除凭据文件,并对保留的测试配置密码脱敏。[当前验收记录](../testing/smoke/results/2026-10-02-mariadb.md) 与早期 MySQL/H2/游戏客户端证据分别记录,避免将旧运行结果当成本次 MariaDB 联测。
|
||||
+9
-9
@@ -4,7 +4,7 @@
|
||||
|
||||
## 配置和启动
|
||||
|
||||
默认配置模板为 [`moonbridge.yml`](../proxy-core/src/main/resources/config/moonbridge.yml)。发行包将示例配置放在 `config/`;自有插件 JAR 可放在 `plugins.directory` 指向的目录。相对 `plugins.directory` 从所选配置文件所在目录解析;`plugins.enabled` 以插件实现类全名为键,空映射不启用外部插件。插件可用设置由各插件在启动时校验。
|
||||
默认配置模板为 [`moonbridge.yml`](../proxy/core/src/main/resources/config/moonbridge.yml)。发行包将示例配置放在 `config/`;自有插件 JAR 可放在 `plugins.directory` 指向的目录。相对 `plugins.directory` 从所选配置文件所在目录解析;`plugins.enabled` 以插件实现类全名为键,空映射不启用外部插件。插件可用设置由各插件在启动时校验。
|
||||
|
||||
本地安装发行包并启动:
|
||||
|
||||
@@ -44,16 +44,16 @@ status:
|
||||
- 可选的 `websocket` 段在 TCP `listen` 之外再开一个 WebSocket 玩家监听,供经 CDN 接入的客户端使用;两种入口同时可用,见 [WebSocket 接入](websocket.md)。OFFLINE 模式对 `websocket.listen` 同样要求字面量回环 IP,除非设置 `allowOfflinePublicAccess: true`。
|
||||
- `maxConnections` 默认 4096,范围为 1–1,000,000;计数包括登录中的客户端,以及尚未完成 WebSocket 升级的连接。达到上限时新连接直接关闭。按部署资源和连接规模配置,不将其解释为后端容量。
|
||||
- `transport` 选择玩家连接、后端连接和 DNS 使用的网络传输层,默认 `AUTO`:Linux 上用 epoll,macOS 上用 kqueue,其他平台(如 Windows)或原生库无法加载时(如 ARM/x86 以外的架构、musl 发行版)回退到 NIO,启动日志会输出实际选用的传输层。发行包附带 Linux x86_64/aarch64 的 epoll 与 macOS x86_64/aarch64 的 kqueue 原生库,启动脚本已加 `--enable-native-access=ALL-UNNAMED`。显式写 `NIO`、`EPOLL` 或 `KQUEUE` 会强制使用对应实现;指定的原生传输层不可用时启动失败,不会静默回退。后端控制通道使用独立的阻塞套接字,不受此项影响。
|
||||
- 发行包默认关闭 Netty 的内存泄漏检测(`-Dio.netty.leakDetection.level=disabled`):它在每个手写转发/编码路径上都有逐帧开销,合成基准中 burst 场景每帧 CPU 中位数约低 26%(范围有重叠,见[记录](../benchmarks/results/2026-10-05-event-loop-queue-and-netty.md))。代替它的是测试期的 `LeakGate`:`proxy-core` 的每个测试类都以 PARANOID 级别运行,发现未释放的缓冲区即让该类失败,且有自测证明它能抓到故意的泄漏。引用计数的手写位置已集中到 `ByteBufs`、`FrameTransformHandler` 与 Netty 自带的编解码基类里;已评估的手写 release 位置都有测试守护,范围与方法见[验证说明](testing.md)。需要在某个部署上重新启用时,设置 `JAVA_OPTS=-Dio.netty.leakDetection.level=simple`(启动脚本里后出现的 `-D` 覆盖默认值)。
|
||||
- 发行包默认关闭 Netty 的内存泄漏检测(`-Dio.netty.leakDetection.level=disabled`):它在每个手写转发/编码路径上都有逐帧开销,合成基准中 burst 场景每帧 CPU 中位数约低 26%(范围有重叠,见[记录](../testing/benchmarks/results/2026-10-05-event-loop-queue-and-netty.md))。代替它的是测试期的 `LeakGate`:`proxy-core` 的每个测试类都以 PARANOID 级别运行,发现未释放的缓冲区即让该类失败,且有自测证明它能抓到故意的泄漏。引用计数的手写位置已集中到 `ByteBufs`、`FrameTransformHandler` 与 Netty 自带的编解码基类里;已评估的手写 release 位置都有测试守护,范围与方法见[验证说明](testing.md)。需要在某个部署上重新启用时,设置 `JAVA_OPTS=-Dio.netty.leakDetection.level=simple`(启动脚本里后出现的 `-D` 覆盖默认值)。
|
||||
- `plugins.eventTimeoutSeconds` 为统一事件链期限,默认 5 秒,可设为 1–30 秒。玩家准入事件按订阅注册顺序共享一个期限;无订阅者时跳过派发。准入队列容量为 128,最多 1024 个未决请求。队列饱和、超时、异常或空结果都会拒绝当前访问:连接准入阶段关闭 TCP 连接,玩家准入阶段返回通用错误文本;插件可通过显式拒绝结果提供登录断开原因。生命周期通知有独立的单线程 FIFO 队列,容量 128,最多一个事件正在派发;单事件链受同一事件期限约束。过载时尽力丢弃并聚合记录,不影响连接处理。
|
||||
- 未认证帧上限为 4 KiB;后端 Login Success 后切换到协议 5 PLAY 帧上限。握手/身份验证与后端连接/登录各自有 15 秒期限;`initialRouting.timeoutSeconds` 默认 15 秒,可设为 1–120 秒,覆盖插件异步选服和所有候选服务器的 DNS/TCP 建连。`initialRouting.servers` 是无插件策略时显式配置的有序候选服务器名,最多 16 个;默认空列表会拒绝首次登录,不会从动态注册目录猜一个服务器。有初始选服插件时,该插件的选择完全接管路由,失败不会回退到配置列表。只有发送任何 Minecraft 握手/登录字节前的 DNS/TCP 失败可继续尝试候选;开始后端登录后失败会结束本次登录,不重放协议流量。成功登录后,客户端须在两分钟内完成首次 PLAY/Forge 握手。
|
||||
- 登录拒绝、插件主动断开以及后端关闭/读失败的已提交前端写入最多排空等待 5 秒。转服切换阶段有 15 秒期限;Forge 客户端切换后目标握手最多等待 30 秒。各期限届满可能使当前登录失败或关闭当前会话。
|
||||
|
||||
## 可选后端发现
|
||||
|
||||
后端控制通道示例见 [`moonbridge-channel.example.yml`](../proxy-core/src/main/resources/config/moonbridge-channel.example.yml),使用独立监听端口接收实例注册、心跳和双向消息;使用方法与限制见[后端控制通道](backend-channel-design.md)。
|
||||
后端控制通道示例见 [`moonbridge-channel.example.yml`](../proxy/core/src/main/resources/config/moonbridge-channel.example.yml),使用独立监听端口接收实例注册、心跳和双向消息;使用方法与限制见[后端控制通道](backend-channel-design.md)。
|
||||
|
||||
Docker 容器间的监听、服务名和地址配置见[配置与部署](backend-channel-design.md#配置与部署);`sh smoke/container-channel.sh` 可运行跨容器烟测。
|
||||
Docker 容器间的监听、服务名和地址配置见[配置与部署](backend-channel-design.md#配置与部署);`sh testing/smoke/container-channel.sh` 可运行跨容器烟测。
|
||||
|
||||
控制通道默认关闭。启用后,后端实例通过独立 TCP 连接认证和注册;代理不提供 DNS 发现或 HTTP 注册。代理核心没有内置云实例发现或健康探测。
|
||||
|
||||
@@ -71,9 +71,9 @@ Docker 容器间的监听、服务名和地址配置见[配置与部署](backend
|
||||
|
||||
现有测试可用于定位行为范围:
|
||||
|
||||
- 登录、认证和协议:`proxy-core/src/test/java/dev/moonbridge/core/auth/` 与 `proxy-core/src/test/java/dev/moonbridge/core/protocol/`
|
||||
- 会话、断开、转服与缓冲:`proxy-core/src/test/java/dev/moonbridge/core/session/`,重点包括 `SessionTransferTest`、`SessionTransferDispatchTest`、`transfer/TransferFrameBufferTest`
|
||||
- 插件生命周期、访问检查和 API:`proxy-core/src/test/java/dev/moonbridge/core/plugin/PluginHostTest.java`、`proxy-core/src/test/java/dev/moonbridge/core/session/ProxySessionListenerTest.java`、`proxy-core/src/test/java/dev/moonbridge/app/ProxyConfigurationTest.java` 与 `proxy-plugin-api/src/test/`
|
||||
- 控制通道:`proxy-core/src/test/java/dev/moonbridge/core/control/` 与 `backend/src/test/`
|
||||
- 登录、认证和协议:`proxy/core/src/test/java/dev/moonbridge/core/auth/` 与 `proxy/core/src/test/java/dev/moonbridge/core/protocol/`
|
||||
- 会话、断开、转服与缓冲:`proxy/core/src/test/java/dev/moonbridge/core/session/`,重点包括 `SessionTransferTest`、`SessionTransferDispatchTest`、`transfer/TransferFrameBufferTest`
|
||||
- 插件生命周期、访问检查和 API:`proxy/core/src/test/java/dev/moonbridge/core/plugin/PluginHostTest.java`、`proxy/core/src/test/java/dev/moonbridge/core/session/ProxySessionListenerTest.java`、`proxy/core/src/test/java/dev/moonbridge/app/ProxyConfigurationTest.java` 与 `proxy/plugin-api/src/test/`
|
||||
- 控制通道:`proxy/core/src/test/java/dev/moonbridge/core/control/` 与 `backend/src/test/`
|
||||
|
||||
仓库另有本地 Uranium 协议探针和 Prism Forge 客户端记录,见 [`smoke/results`](../smoke/results/2026-09-25-local-uranium.md)、[转服记录](../smoke/results/2026-09-25-local-uranium-transfer.md) 和 [真实客户端记录](../smoke/results/2026-09-25-prism-forge-client.md)。这些记录支持其明确写出的单机环境、软件版本和探针路径。已知也出现过真实 Forge 客户端转服候选后端登录停滞,见[调查记录](../smoke/results/2026-09-26-uranium-login-stalls.md);已有成功样例不构成稳定性或生产验收。
|
||||
仓库另有本地 Uranium 协议探针和 Prism Forge 客户端记录,见 [`testing/smoke/results`](../testing/smoke/results/2026-09-25-local-uranium.md)、[转服记录](../testing/smoke/results/2026-09-25-local-uranium-transfer.md) 和 [真实客户端记录](../testing/smoke/results/2026-09-25-prism-forge-client.md)。这些记录支持其明确写出的单机环境、软件版本和探针路径。已知也出现过真实 Forge 客户端转服候选后端登录停滞,见[调查记录](../testing/smoke/results/2026-09-26-uranium-login-stalls.md);已有成功样例不构成稳定性或生产验收。
|
||||
+2
-2
@@ -55,7 +55,7 @@ context.commands().register("island", "example.command.island", invocation -> {
|
||||
|
||||
## LuckPerms 平台插件
|
||||
|
||||
`luckperms-moonbridge` 使用固定版本的官方 LuckPerms 公共核心,并实现 MoonBridge 平台适配。上游源码在 Git 子模块 `vendor/luckperms`。编译它较慢且依赖很多,因此默认构建不包含该插件,需要显式开启:
|
||||
`luckperms-moonbridge` 使用固定版本的官方 LuckPerms 公共核心,并实现 MoonBridge 平台适配。上游源码在 Git 子模块 `proxy/vendor/luckperms`。编译它较慢且依赖很多,因此默认构建不包含该插件,需要显式开启:
|
||||
|
||||
```sh
|
||||
git submodule update --init --recursive
|
||||
@@ -120,7 +120,7 @@ redis:
|
||||
|
||||
Redis 负责通知其他实例重载权限,权限数据仍保存在 MariaDB。Redis 中断期间不会保证其他实例即时看到修改;恢复连接后的新通知可触发刷新,也可以在需要时使用 `lp sync` 主动同步。数据库中断时,已加载玩家可继续使用现有缓存,新玩家加载失败会被拒绝登录;缓存不是数据库最新状态的保证。
|
||||
|
||||
此前 MySQL 8.4 与 Redis 7.4 的结果保留为 [历史验收记录](../smoke/results/2026-09-28-permissions.md)。当前 MariaDB 13.0.2 的验收入口和记录见 [MariaDB 验证](mariadb.md)。
|
||||
此前 MySQL 8.4 与 Redis 7.4 的结果保留为 [历史验收记录](../testing/smoke/results/2026-09-28-permissions.md)。当前 MariaDB 13.0.2 的验收入口和记录见 [MariaDB 验证](mariadb.md)。
|
||||
|
||||
backend 可安装与其 Minecraft / Java 版本兼容的原生 Bukkit LuckPerms,使用相同的身份模式、共享数据库与 LuckPerms 支持的同步方式;MoonBridge 平台插件 JAR 只供代理使用。共享数据库不意味着所有场景的检查结果相同:代理知道后端名称,但不知道玩家在 Bukkit 世界中的位置或其他后端私有上下文。玩家首次登录的权限加载不依赖某个 backend 在线。
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 玩家操作与部署完善设计
|
||||
|
||||
状态:本文保留首批玩家操作的设计基线。当前消息模型见[富文本与命令补全](messages-and-completion.md)。2026-09-26 Prism 记录是历史提交下的真实在线认证和客户端结果,不代表当前初次路由分支的完整模组包验收;当前路由证据见[专项验收](../smoke/results/2026-09-27-initial-routing.md)。
|
||||
状态:本文保留首批玩家操作的设计基线。当前消息模型见[富文本与命令补全](messages-and-completion.md)。2026-09-26 Prism 记录是历史提交下的真实在线认证和客户端结果,不代表当前初次路由分支的完整模组包验收;当前路由证据见[专项验收](../testing/smoke/results/2026-09-27-initial-routing.md)。
|
||||
|
||||
## 目标与边界
|
||||
|
||||
|
||||
+1
-1
@@ -145,6 +145,6 @@ context.events().subscribe(PlayerDisconnectedEvent.class, event ->
|
||||
|
||||
统一事件模型让准入决策和会话通知共享同一类型、监听器、订阅表与派发实现,同时保留各类事件所需的运行策略。准入阶段执行有序且失败关闭的结果聚合;生命周期通知异步 FIFO 尽力交付并与会话处理隔离。没有 PLAY 包事件。目前没有事件 API 的专门基准,不能据此宣称性能收益或无开销。
|
||||
|
||||
源码入口:[`PluginContext`](../proxy-plugin-api/src/main/java/dev/moonbridge/api/PluginContext.java)、[`Events`](../proxy-plugin-api/src/main/java/dev/moonbridge/api/event/Events.java)、[`AccessDecision`](../proxy-plugin-api/src/main/java/dev/moonbridge/api/AccessDecision.java)。
|
||||
源码入口:[`PluginContext`](../proxy/plugin-api/src/main/java/dev/moonbridge/api/PluginContext.java)、[`Events`](../proxy/plugin-api/src/main/java/dev/moonbridge/api/event/Events.java)、[`AccessDecision`](../proxy/plugin-api/src/main/java/dev/moonbridge/api/AccessDecision.java)。
|
||||
|
||||
富文本构造、MiniMessage 和异步命令补全示例见[消息与命令补全](messages-and-completion.md)。
|
||||
+1
-1
@@ -54,7 +54,7 @@ dependencies {
|
||||
|
||||
## Proxy 发行包
|
||||
|
||||
`:proxy-core:distZip` 生成 `proxy-core/build/distributions/moonbridge-<version>.zip`。CI 把这个 ZIP 作为 `moonbridge-development` 下载工件的一部分上传,保留 30 天;它不是 Maven 模块,也不自动成为 Git Release。解压后从发行包目录运行:
|
||||
`:proxy-core:distZip` 生成 `proxy/core/build/distributions/moonbridge-<version>.zip`。CI 把这个 ZIP 作为 `moonbridge-development` 下载工件的一部分上传,保留 30 天;它不是 Maven 模块,也不自动成为 Git Release。解压后从发行包目录运行:
|
||||
|
||||
```powershell
|
||||
.\bin\moonbridge.bat --validate-config .\config\moonbridge.yml
|
||||
|
||||
+22
-22
@@ -7,26 +7,26 @@
|
||||
.\gradlew.bat :proxy-core:installedDistSmokeTest
|
||||
.\gradlew.bat -Pluckperms :proxy-core:permissionAcceptance
|
||||
.\smoke\container-network.ps1
|
||||
sh smoke/container-channel.sh
|
||||
sh testing/smoke/container-channel.sh
|
||||
```
|
||||
|
||||
定向测试覆盖控制通道认证与代次、目录租约、插件生命周期与超时、协议边界、relay 背压,以及合成 TCP 登录和切换。初次路由最新专项验收包括自动化覆盖和实际 Java 8 Uranium 后端协议探针,见[2026-09-27 路由验收](../smoke/results/2026-09-27-initial-routing.md);它不是完整模组包视觉验收。2026-09-26 Prism 记录保留为其提交和环境下的历史真实客户端/配对测量,见[历史 Prism 记录](../benchmarks/results/2026-09-26-prism-pack.md)。下面其他历史结果也只支持其记录注明的范围。
|
||||
定向测试覆盖控制通道认证与代次、目录租约、插件生命周期与超时、协议边界、relay 背压,以及合成 TCP 登录和切换。初次路由最新专项验收包括自动化覆盖和实际 Java 8 Uranium 后端协议探针,见[2026-09-27 路由验收](../testing/smoke/results/2026-09-27-initial-routing.md);它不是完整模组包视觉验收。2026-09-26 Prism 记录保留为其提交和环境下的历史真实客户端/配对测量,见[历史 Prism 记录](../testing/benchmarks/results/2026-09-26-prism-pack.md)。下面其他历史结果也只支持其记录注明的范围。
|
||||
|
||||
`smoke/container-network.ps1` 使用 Docker bridge 中的独立代理、后端和客户端容器,依次检查静态配置和控制通道注册、登录及 PLAY 转发;控制通道模式还验证注销后已连接会话继续转发。PowerShell 7 和 Docker Desktop 是运行前提。`smoke/container-channel.sh` 在 Unix shell 下验证控制通道的同一跨容器路径。2026-09-25 的[容器网络烟测记录](../smoke/results/2026-09-25-container-network.md)是旧实现的历史结果,不代表当前通道已在那次运行中验证。容器烟测不能代替跨物理主机或目标 Forge 整合包实测。
|
||||
`testing/smoke/container-network.ps1` 使用 Docker bridge 中的独立代理、后端和客户端容器,依次检查静态配置和控制通道注册、登录及 PLAY 转发;控制通道模式还验证注销后已连接会话继续转发。PowerShell 7 和 Docker Desktop 是运行前提。`testing/smoke/container-channel.sh` 在 Unix shell 下验证控制通道的同一跨容器路径。2026-09-25 的[容器网络烟测记录](../testing/smoke/results/2026-09-25-container-network.md)是旧实现的历史结果,不代表当前通道已在那次运行中验证。容器烟测不能代替跨物理主机或目标 Forge 整合包实测。
|
||||
|
||||
`.github/workflows/verify.yml` 在每个 Pull Request 上运行 `gradlew -Pluckperms check`,并单独构建、测试 `client-mod/`。`.github/workflows/ci.yml` 在 `main` 推送或手动触发时先执行 `gradlew -Pluckperms check release`,再上传 `build/release/` 并发布 Maven 模块。发布步骤要求 `MAVEN_USER` 与 `MAVEN_PASSWORD` secrets;本地 `check` 不能证明远端 Maven 发布成功。版本规则、Maven 坐标和发行物 见[发布与依赖版本](publishing.md)。
|
||||
|
||||
带 `-Pluckperms` 时 `check` 包含 `permissionAcceptance`(本地默认 `check` 不编译 LuckPerms,因此不含这一项;CI 始终开启):使用发行包中的实际 LuckPerms JAR、隔离插件类加载器和临时 H2 数据库,验证原生命令、授权/拒绝/未设置、组继承、临时节点到期、后端上下文、连接代次隔离及关闭后重新打开数据库。输出位于 `proxy-core/build/permission-acceptance/run-*/`,成功标记为 `PERMISSION_ACCEPTANCE_PASS`。它使用 API 玩家探针,不连接真实 Minecraft 客户端,也不证明外部 SQL/Redis 联调成功;真实会话的权限准备和释放由 TCP 生命周期测试另行覆盖。
|
||||
带 `-Pluckperms` 时 `check` 包含 `permissionAcceptance`(本地默认 `check` 不编译 LuckPerms,因此不含这一项;CI 始终开启):使用发行包中的实际 LuckPerms JAR、隔离插件类加载器和临时 H2 数据库,验证原生命令、授权/拒绝/未设置、组继承、临时节点到期、后端上下文、连接代次隔离及关闭后重新打开数据库。输出位于 `proxy/core/build/permission-acceptance/run-*/`,成功标记为 `PERMISSION_ACCEPTANCE_PASS`。它使用 API 玩家探针,不连接真实 Minecraft 客户端,也不证明外部 SQL/Redis 联调成功;真实会话的权限准备和释放由 TCP 生命周期测试另行覆盖。
|
||||
|
||||
如果本地已有 Uranium 1.7.10 可运行包及其编译好的 `MinecraftProtocolProbe`,可运行 `smoke/local-uranium.ps1 -BundlePath <包目录> -ProbeClassesPath <探针类目录>`。脚本复制服务端到忽略目录,启动 Java 8 后端与当前安装包,再让探针经代理完成状态查询、FML 登录、Join Game 和持续 Keep Alive,结束时停止两个进程。本地一次结果与具体前提见 [最小 Uranium 联机记录](../smoke/results/2026-09-25-local-uranium.md)。初次路由的当前 `ProxyMain` 协议探针结果另见[路由验收](../smoke/results/2026-09-27-initial-routing.md)。真实客户端记录见下段和其单独的历史验收档案;它们不应与当前路由分支的完整模组包验收混为一谈。
|
||||
如果本地已有 Uranium 1.7.10 可运行包及其编译好的 `MinecraftProtocolProbe`,可运行 `testing/smoke/local-uranium.ps1 -BundlePath <包目录> -ProbeClassesPath <探针类目录>`。脚本复制服务端到忽略目录,启动 Java 8 后端与当前安装包,再让探针经代理完成状态查询、FML 登录、Join Game 和持续 Keep Alive,结束时停止两个进程。本地一次结果与具体前提见 [最小 Uranium 联机记录](../testing/smoke/results/2026-09-25-local-uranium.md)。初次路由的当前 `ProxyMain` 协议探针结果另见[路由验收](../testing/smoke/results/2026-09-27-initial-routing.md)。真实客户端记录见下段和其单独的历史验收档案;它们不应与当前路由分支的完整模组包验收混为一谈。
|
||||
|
||||
`smoke/local-uranium-transfer.ps1 -BundlePath <包目录>` 复制并启动两台 Uranium,然后编译仓库中的协议探针,通过实际 `ProxySessionListener` 请求从旧服切换到新服。加上 `-InstalledPlugin` 则启动已安装的 `ProxyMain`:旧服由静态配置注册,临时插件用 `Servers.register` 注册目标服,在初始落点回调读取 `ServerView`,再通过 `Players.transfer` 发起转服。默认模式使用协议探针核对 FML 重置、重新握手、世界切换包和目标连接的 Keep Alive,见 [两台 Uranium 转服记录](../smoke/results/2026-09-25-local-uranium-transfer.md)。`-InstalledPlugin -ReturnToOld` 让协议探针验证旧服→新服→旧服的两次切换。`-InstalledPlugin -PrismClient` 改用本机 Prism 中的 `1.7.10` Forge 实例,要求客户端在目标服保持连接 10 秒;可同时使用 `-ReturnToOld` 验证真实客户端往返。两个真实客户端脚本都可用 `-PrismInstance <实例名>` 选择其他实例。若实例的文件夹名与启动名不同,另传 `-PrismInstanceFolder <文件夹名>`,以便准确定位并清理这次启动的客户端;`-PrismPath` 指向其他 Prism 安装位置。`smoke/local-uranium.ps1 -PrismClient` 可单独验证首次登录。这些实测仍不能替代目标整合包验收。
|
||||
`testing/smoke/local-uranium-transfer.ps1 -BundlePath <包目录>` 复制并启动两台 Uranium,然后编译仓库中的协议探针,通过实际 `ProxySessionListener` 请求从旧服切换到新服。加上 `-InstalledPlugin` 则启动已安装的 `ProxyMain`:旧服由静态配置注册,临时插件用 `Servers.register` 注册目标服,在初始落点回调读取 `ServerView`,再通过 `Players.transfer` 发起转服。默认模式使用协议探针核对 FML 重置、重新握手、世界切换包和目标连接的 Keep Alive,见 [两台 Uranium 转服记录](../testing/smoke/results/2026-09-25-local-uranium-transfer.md)。`-InstalledPlugin -ReturnToOld` 让协议探针验证旧服→新服→旧服的两次切换。`-InstalledPlugin -PrismClient` 改用本机 Prism 中的 `1.7.10` Forge 实例,要求客户端在目标服保持连接 10 秒;可同时使用 `-ReturnToOld` 验证真实客户端往返。两个真实客户端脚本都可用 `-PrismInstance <实例名>` 选择其他实例。若实例的文件夹名与启动名不同,另传 `-PrismInstanceFolder <文件夹名>`,以便准确定位并清理这次启动的客户端;`-PrismPath` 指向其他 Prism 安装位置。`testing/smoke/local-uranium.ps1 -PrismClient` 可单独验证首次登录。这些实测仍不能替代目标整合包验收。
|
||||
|
||||
安装包转服烟测可加 `-DebugSession`,在本次复制的 Uranium 配置中开启登录阶段日志,并将代理会话的连接、登录写入和失败路径 DEBUG 日志写入所打印运行目录的 `proxy.stdout.log`。加 `-TraceBackend` 会在代理与两台 Uranium 之间放置本地 TCP 中继,并将每个方向的前 512 字节记录到运行目录的 `tap-old.log` 和 `tap-new.log`;这一诊断选项会改变连接时序。初次登录 EOF 的复现实验见 [运行记录](../smoke/results/2026-09-26-initial-login-repeat.md);增强日志和中继后捕获的 Uranium 登录停滞及源码假设见 [登录停滞记录](../smoke/results/2026-09-26-uranium-login-stalls.md)。
|
||||
安装包转服烟测可加 `-DebugSession`,在本次复制的 Uranium 配置中开启登录阶段日志,并将代理会话的连接、登录写入和失败路径 DEBUG 日志写入所打印运行目录的 `proxy.stdout.log`。加 `-TraceBackend` 会在代理与两台 Uranium 之间放置本地 TCP 中继,并将每个方向的前 512 字节记录到运行目录的 `tap-old.log` 和 `tap-new.log`;这一诊断选项会改变连接时序。初次登录 EOF 的复现实验见 [运行记录](../testing/smoke/results/2026-09-26-initial-login-repeat.md);增强日志和中继后捕获的 Uranium 登录停滞及源码假设见 [登录停滞记录](../testing/smoke/results/2026-09-26-uranium-login-stalls.md)。
|
||||
|
||||
## 历史验证记录
|
||||
|
||||
带日期的逐轮验证结果放在 [`records/`](records/),与 `smoke/results/`、`benchmarks/results/` 一样只证明各自注明的提交和环境:
|
||||
带日期的逐轮验证结果放在 [`records/`](records/),与 `testing/smoke/results/`、`testing/benchmarks/results/` 一样只证明各自注明的提交和环境:
|
||||
|
||||
- [2026-09-26 验证记录](records/2026-09-26-validation-log.md):玩家操作与服务器列表、统一事件模型、历史类型化事件与访问检查。
|
||||
- [2026-09-27 富文本与命令补全验证](records/2026-09-27-rich-text-completion.md)。
|
||||
@@ -39,7 +39,7 @@ sh smoke/container-channel.sh
|
||||
|
||||
## 合成 relay 基准
|
||||
|
||||
`benchmarks/run-relay.ps1` 比较同一 JVM、同一个本机回声后端上的直连、原始字节 relay、按帧 relay,以及安装了实际 `KeepAliveBridge` 的按帧 relay。每个连接先预热,再重复发送固定长度的合成 Minecraft 帧并读取同样长度的回声;连接数、每连接消息数、预热数、帧负载字节数、重复轮数和同时在途的消息数均可配置。`-Window 1` 是逐包等待回声;更大的窗口使用独立写线程持续发送,读线程按顺序核对回声,并用信号量限制在途消息数。基准在轮次间交替执行三种 relay,并在首尾测直连基线。输出往返吞吐、按单向传输字节计算的 MiB/s、往返延迟 p50/p95/p99、JVM GC 次数/耗时和堆已用量变化。
|
||||
`testing/benchmarks/run-relay.ps1` 比较同一 JVM、同一个本机回声后端上的直连、原始字节 relay、按帧 relay,以及安装了实际 `KeepAliveBridge` 的按帧 relay。每个连接先预热,再重复发送固定长度的合成 Minecraft 帧并读取同样长度的回声;连接数、每连接消息数、预热数、帧负载字节数、重复轮数和同时在途的消息数均可配置。`-Window 1` 是逐包等待回声;更大的窗口使用独立写线程持续发送,读线程按顺序核对回声,并用信号量限制在途消息数。基准在轮次间交替执行三种 relay,并在首尾测直连基线。输出往返吞吐、按单向传输字节计算的 MiB/s、往返延迟 p50/p95/p99、JVM GC 次数/耗时和堆已用量变化。
|
||||
|
||||
```powershell
|
||||
.\benchmarks\run-relay.ps1 -Connections 8 -Messages 2000 -Warmup 200 -Payload 4096
|
||||
@@ -48,8 +48,8 @@ sh smoke/container-channel.sh
|
||||
|
||||
该基准只覆盖本机 TCP 回声和三种 relay 数据路径。不同窗口使用不同的客户端发送方式,应在相同窗口内比较。负载是合成帧,不含登录、Forge 握手、模组流量、转服时的实体 ID 改写或真实客户端/后端行为;结果不代表 1.7.10 整合包等价性能,也不设 CI 性能门槛。堆变化是阶段前后的粗略观测,不是分配速率;请在目标机器、JDK 和连接规模上多轮运行并记录环境,避免把单次结果当成容量承诺。
|
||||
|
||||
本地一次测量的环境、参数与原始输出见 `benchmarks/results/2026-09-25-local-relay.md`。
|
||||
加入实际 `KeepAliveBridge` 后的配对测量见 `benchmarks/results/2026-09-25-keepalive-bridge.md`;两份结果使用的 relay 事件循环安排不同,不能直接视为前后性能对比。
|
||||
本地一次测量的环境、参数与原始输出见 `testing/benchmarks/results/2026-09-25-local-relay.md`。
|
||||
加入实际 `KeepAliveBridge` 后的配对测量见 `testing/benchmarks/results/2026-09-25-keepalive-bridge.md`;两份结果使用的 relay 事件循环安排不同,不能直接视为前后性能对比。
|
||||
|
||||
## 真实 TCP 慢接收端背压回归
|
||||
|
||||
@@ -63,34 +63,34 @@ sh smoke/container-channel.sh
|
||||
|
||||
## 合成会话基准
|
||||
|
||||
`benchmarks/run-proxy-session.ps1` 在同一 JVM 中比较直接连接模拟后端,以及经过实际 `ProxySessionListener` 登录、落点选择和会话转发后连接同一后端。客户端先完成离线登录,读取 Join Game 和 Position and Look,再预热;计时仅包含固定 PLAY 帧的往返。`-Window` 设置每个客户端允许的在途请求数,默认 `1`(stop-and-wait);大于 `1` 时客户端最多连续发送 Window 个帧,再按 TCP 顺序读取回声并逐条校验,每收到一条便补发一条。预热和计时阶段、直连和代理都使用相同的发送算法。测得的单条延迟从该请求写出前计时到其回声读完;延迟样本和在途时间戳都使用有界数组,受 `Connections`、`Messages` 和 Window 上限约束。出现错误回声或阶段超时时基准以失败退出。
|
||||
`testing/benchmarks/run-proxy-session.ps1` 在同一 JVM 中比较直接连接模拟后端,以及经过实际 `ProxySessionListener` 登录、落点选择和会话转发后连接同一后端。客户端先完成离线登录,读取 Join Game 和 Position and Look,再预热;计时仅包含固定 PLAY 帧的往返。`-Window` 设置每个客户端允许的在途请求数,默认 `1`(stop-and-wait);大于 `1` 时客户端最多连续发送 Window 个帧,再按 TCP 顺序读取回声并逐条校验,每收到一条便补发一条。预热和计时阶段、直连和代理都使用相同的发送算法。测得的单条延迟从该请求写出前计时到其回声读完;延迟样本和在途时间戳都使用有界数组,受 `Connections`、`Messages` 和 Window 上限约束。出现错误回声或阶段超时时基准以失败退出。
|
||||
|
||||
```powershell
|
||||
.\benchmarks\run-proxy-session.ps1 -Connections 4 -Messages 1000 -Warmup 100 -Payload 1024 -Repeats 2 -Window 1
|
||||
.\benchmarks\run-proxy-session.ps1 -Connections 4 -Messages 1000 -Warmup 100 -Payload 1024 -Repeats 2 -Window 1 -Mode post-transfer
|
||||
```
|
||||
|
||||
2026-09-25 的多轮、同条件本机测量及原始输出见 [生命周期修复后的会话基准记录](../benchmarks/results/2026-09-25-session-after-lifecycle.md)。更早的测量见 [原会话基准记录](../benchmarks/results/2026-09-25-current-session-benchmark.md)。这些记录对应各自注明的源码版本,不是当前事件 API 的性能结果,也不代表后端负载观测。
|
||||
2026-09-25 的多轮、同条件本机测量及原始输出见 [生命周期修复后的会话基准记录](../testing/benchmarks/results/2026-09-25-session-after-lifecycle.md)。更早的测量见 [原会话基准记录](../testing/benchmarks/results/2026-09-25-current-session-benchmark.md)。这些记录对应各自注明的源码版本,不是当前事件 API 的性能结果,也不代表后端负载观测。
|
||||
|
||||
`-Mode post-transfer` 让代理客户端先从 `bench` 转到 `replacement`,直连客户端直接进入同一个 `replacement` 模拟后端;转服与预热均在计时外。两后端使用不同玩家实体 ID,因此代理在转服后仍运行实体 ID 映射路径。[转服前后会话基准记录](../benchmarks/results/2026-09-25-post-transfer-session.md) 包含窗口 1 和 16 的同条件多轮测量及原始输出。结果没有显示值得据此修改普通转发路径的稳定差异。
|
||||
`-Mode post-transfer` 让代理客户端先从 `bench` 转到 `replacement`,直连客户端直接进入同一个 `replacement` 模拟后端;转服与预热均在计时外。两后端使用不同玩家实体 ID,因此代理在转服后仍运行实体 ID 映射路径。[转服前后会话基准记录](../testing/benchmarks/results/2026-09-25-post-transfer-session.md) 包含窗口 1 和 16 的同条件多轮测量及原始输出。结果没有显示值得据此修改普通转发路径的稳定差异。
|
||||
|
||||
加入 Forge 握手阶段旧世界数据包过滤后,在该历史版本上重跑的 [转服后基准](../benchmarks/results/2026-09-25-forge-transfer-gate-followup.md) 与先前结果的范围重叠;合成流量没有显示稳定的大幅退化,目标整合包仍需单独测量。
|
||||
加入 Forge 握手阶段旧世界数据包过滤后,在该历史版本上重跑的 [转服后基准](../testing/benchmarks/results/2026-09-25-forge-transfer-gate-followup.md) 与先前结果的范围重叠;合成流量没有显示稳定的大幅退化,目标整合包仍需单独测量。
|
||||
|
||||
同一提交在独立 Linux 容器中的 [转服后会话基准](../benchmarks/results/2026-09-25-linux-container-post-transfer.md) 也完成了窗口 1 和 16 的各五轮对照与逐包校验。该结果仅验证另一运行环境中的合成路径;目标整合包和跨主机网络仍需实测。
|
||||
同一提交在独立 Linux 容器中的 [转服后会话基准](../testing/benchmarks/results/2026-09-25-linux-container-post-transfer.md) 也完成了窗口 1 和 16 的各五轮对照与逐包校验。该结果仅验证另一运行环境中的合成路径;目标整合包和跨主机网络仍需实测。
|
||||
|
||||
2026-09-25 会话路径的 [JFR 采样记录](../benchmarks/results/2026-09-25-session-jfr-screening.md) 只提供了分配线索,代理 I/O 线程的 CPU 执行样本不足以定位热点;因此没有据此改动普通转发路径。
|
||||
2026-09-25 会话路径的 [JFR 采样记录](../testing/benchmarks/results/2026-09-25-session-jfr-screening.md) 只提供了分配线索,代理 I/O 线程的 CPU 执行样本不足以定位热点;因此没有据此改动普通转发路径。
|
||||
|
||||
[玩家命令拦截初筛](../benchmarks/results/2026-09-26-command-interceptor.md) 比较同一合成 PLAY 回声流量下启用与关闭命令拦截器的结果;三轮吞吐和延迟范围重叠。该实验没有发送命令,也不能替代目标整合包的容量验收。
|
||||
[玩家命令拦截初筛](../testing/benchmarks/results/2026-09-26-command-interceptor.md) 比较同一合成 PLAY 回声流量下启用与关闭命令拦截器的结果;三轮吞吐和延迟范围重叠。该实验没有发送命令,也不能替代目标整合包的容量验收。
|
||||
|
||||
将 `-Window` 改为 `16` 可测每连接最多 16 个在途往返的情形。
|
||||
|
||||
`-Burst N`(直接运行 Java 时为 `--burst N`)让每次往返由客户端一次写出 N 个帧、模拟后端一次 flush 回声,接近一个服务器 tick 内的多个小 PLAY 包;此时 Window 按批计数。输出另含代理 I/O 线程每帧 CPU 时间,以及在 Linux 上读取 `/proc/net/snmp` 得到的全机 TCP 发送段数/帧(含 ACK,其他平台显示 `n/a`)。[2026-10-05 批量 flush 记录](../benchmarks/results/2026-10-05-relay-batched-flush.md)用它比较逐帧 flush 与按读取批次 flush。`-Transport auto|nio|epoll|kqueue`(`--transport`)选择代理使用的网络传输层,默认 `auto`;[2026-10-05 传输层记录](../benchmarks/results/2026-10-05-network-transport.md)比较了 epoll 与 NIO。
|
||||
`-Burst N`(直接运行 Java 时为 `--burst N`)让每次往返由客户端一次写出 N 个帧、模拟后端一次 flush 回声,接近一个服务器 tick 内的多个小 PLAY 包;此时 Window 按批计数。输出另含代理 I/O 线程每帧 CPU 时间,以及在 Linux 上读取 `/proc/net/snmp` 得到的全机 TCP 发送段数/帧(含 ACK,其他平台显示 `n/a`)。[2026-10-05 批量 flush 记录](../testing/benchmarks/results/2026-10-05-relay-batched-flush.md)用它比较逐帧 flush 与按读取批次 flush。`-Transport auto|nio|epoll|kqueue`(`--transport`)选择代理使用的网络传输层,默认 `auto`;[2026-10-05 传输层记录](../testing/benchmarks/results/2026-10-05-network-transport.md)比较了 epoll 与 NIO。
|
||||
|
||||
原 stop-and-wait 小样本见 `benchmarks/results/2026-09-25-proxy-session-benchmark-smoke.md`;Window 参数的小样本和 Window=1/16 重复测量见 `benchmarks/results/2026-09-25-proxy-session-window.md`。这些是环回网络上的合成帧对照,不能代表 Forge 整合包、真实后端或跨主机部署的性能。
|
||||
原 stop-and-wait 小样本见 `testing/benchmarks/results/2026-09-25-proxy-session-benchmark-smoke.md`;Window 参数的小样本和 Window=1/16 重复测量见 `testing/benchmarks/results/2026-09-25-proxy-session-window.md`。这些是环回网络上的合成帧对照,不能代表 Forge 整合包、真实后端或跨主机部署的性能。
|
||||
|
||||
## 后端宿主真实服务端验收
|
||||
|
||||
`smoke/backend-uranium.ps1` 将已经接受 EULA 的 Uranium 发行包中的服务端 JAR、运行库和 EULA 复制到全新隔离目录,启动两个 Java 8 后端及实际 Java 25 Proxy。它安装 `MoonBridgeBackend`、两个独立的 Bukkit 业务插件和一个外部 Proxy 验收插件,通过正式插件 API 检查注册与消息服务;不会复制或修改原有世界、模组、插件及凭据。Bukkit 业务插件以发行包 `backend/` 中的 JAR 和服务器 Bukkit API 编译(compileOnly,运行时依赖 `MoonBridgeBackend`),并在实际插件加载器下验证服务类身份一致。
|
||||
`testing/smoke/backend-uranium.ps1` 将已经接受 EULA 的 Uranium 发行包中的服务端 JAR、运行库和 EULA 复制到全新隔离目录,启动两个 Java 8 后端及实际 Java 25 Proxy。它安装 `MoonBridgeBackend`、两个独立的 Bukkit 业务插件和一个外部 Proxy 验收插件,通过正式插件 API 检查注册与消息服务;不会复制或修改原有世界、模组、插件及凭据。Bukkit 业务插件以发行包 `backend/` 中的 JAR 和服务器 Bukkit API 编译(compileOnly,运行时依赖 `MoonBridgeBackend`),并在实际插件加载器下验证服务类身份一致。
|
||||
|
||||
```powershell
|
||||
.\gradlew.bat check :proxy-core:installDist
|
||||
@@ -100,4 +100,4 @@ sh smoke/container-channel.sh
|
||||
|
||||
脚本默认使用本机 Zulu Java 8 和 Java 25,可通过 `-Java8Home`、`-Java25Home` 指定其他路径。完整成功输出 `BACKEND_URANIUM_PASS`;任一阶段失败会返回非零退出码并保留日志。后台进程有启动、请求、停机期限,退出时只清理本次创建的进程。
|
||||
|
||||
验收覆盖 Proxy→后端、后端→Proxy、后端→后端请求,UUID/replyTo、多个独立订阅者接收同一广播、Bukkit 主线程与零在线玩家、业务插件停用隔离、Proxy 重启后的自动重新注册、正常停服快速注销、异常退出后的租约清理和后端重启。具体构件哈希和运行结果见[2026-09-27 后端宿主记录](../smoke/results/2026-09-27-backend-host.md)。
|
||||
验收覆盖 Proxy→后端、后端→Proxy、后端→后端请求,UUID/replyTo、多个独立订阅者接收同一广播、Bukkit 主线程与零在线玩家、业务插件停用隔离、Proxy 重启后的自动重新注册、正常停服快速注销、异常退出后的租约清理和后端重启。具体构件哈希和运行结果见[2026-09-27 后端宿主记录](../testing/smoke/results/2026-09-27-backend-host.md)。
|
||||
@@ -86,12 +86,12 @@ val installedDistVersionSmokeTest = tasks.register<Exec>("installedDistVersionSm
|
||||
}
|
||||
}
|
||||
|
||||
// The benchmarks in benchmarks/ declare proxy-core packages to reach package-private classes and are
|
||||
// The benchmarks in testing/benchmarks/ declare proxy-core packages to reach package-private classes and are
|
||||
// normally compiled by their PowerShell runners. Compiling them here keeps them building with main.
|
||||
val compileBenchmarks = tasks.register<JavaCompile>("compileBenchmarks") {
|
||||
group = "verification"
|
||||
description = "Compiles the benchmarks in benchmarks/ against proxy-core."
|
||||
source(rootProject.fileTree("benchmarks") { include("*.java") })
|
||||
description = "Compiles the benchmarks in testing/benchmarks/ against proxy-core."
|
||||
source(rootProject.fileTree("testing/benchmarks") { include("*.java") })
|
||||
classpath = sourceSets.main.get().runtimeClasspath
|
||||
destinationDirectory.set(layout.buildDirectory.dir("classes/benchmarks"))
|
||||
options.release.set(25)
|
||||
@@ -101,7 +101,7 @@ val compileBenchmarks = tasks.register<JavaCompile>("compileBenchmarks") {
|
||||
val luckPerms = rootProject.findProject(":luckperms-moonbridge")
|
||||
if (luckPerms != null) {
|
||||
val compilePermissionAcceptance = tasks.register<JavaCompile>("compilePermissionAcceptance") {
|
||||
source(rootProject.file("smoke/PermissionAcceptance.java"))
|
||||
source(rootProject.file("testing/smoke/PermissionAcceptance.java"))
|
||||
classpath = sourceSets.main.get().runtimeClasspath
|
||||
destinationDirectory.set(layout.buildDirectory.dir("classes/permissionAcceptance"))
|
||||
options.release.set(25)
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 369 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user