English TL;DR: The author of STS2 LAN Connect (a multiplayer lobby mod) integrates with RitsuLib's public typed sidecar API (module sts2_lan_connect / protocol_v1, StableSync, Required). Since RitsuLib 0.5.14 (reproduced on 0.5.18), typed sidecar delivery stalls over our room-level ENet relay: the client's EndpointCatalog (opcode 23) and handshake get no response from the host, no typed traffic ever flows, and the vanilla join timer eventually kills the connection with LobbyJoinTimeout. The exact same integration passed an end-to-end relay test on 0.5.13. We'd like to know whether third-party ENet relay paths are expected to work, whether a legacy-delivery opt-out exists, and — as a feature request — whether reserved channel allocations, the control-opcode range, and native-trailer ownership could be documented as a public coexistence contract for networking mods.
背景
我是 STS2 LAN Connect(联机大厅)的作者(创意工坊 3749766330,源码 STS2-Game-Lobby)。我们的 mod 让玩家通过自建大厅服务 + 房间级 UDP 中继(ENet 透明转发)联机。当房间内所有玩家都启用 RitsuLib 时,我们的协议容器会通过 RitsuLib 的公开 typed sidecar API(RitsuLibSidecarTypedMessageRegistry)投递:module id sts2_lan_connect,message key protocol_v1,StableSync,Required=true。我们只使用公开 API,不依赖私有内部实现。
首先感谢提供公开 typed registry——这正是我们选择它作为载体的原因。
现象(RitsuLib 0.5.18,游戏 v0.111.0 / 41cef1ea)
双端均启用 RitsuLib,客户端经由我们的 UDP 中继加入房主房间。精简时间线(客户端日志):
[INFO] [ENetClient] Sending handshake with net ID 7780...(原版握手,正常完成)
[INFO] [Sidecar] Session bound epoch=1, netType=Client, netId=7780...
[INFO] [Sidecar] Peer reachability changed peer=1, Unknown->Supported, reason=route:manual_hint
[WARN] [Sidecar] Handshake send failed peer=1 ... retrying with backoff ← 与 0.5.13 成功场景相同,良性
[INFO] [HandshakeManager] Got handshake from sender 1. Version: v0.111.0 ...(原版握手完成)
[DEBUG] [Sidecar] Inbound parsed opcode=16, sender=1, payloadLen=8, channel=48 ← 收到房主 sidecar 握手
[DEBUG] [Sidecar] Outbound client->host opcode=23, wireLen=189, ch=48 ← EndpointCatalog
[DEBUG] [Sidecar] Outbound client->host opcode=16, wireLen=43, ch=48 ← 我方握手
(此后房主侧再无任何 sidecar 响应;typed 流量从未出现)
[DEBUG] [ENetClient] Received disconnection packet with reason: LobbyJoinTimeout ← ~30s 后房主断开
要点:ENet 连接与原版握手全程正常(双端模型哈希一致),ch=48 的 host→client 方向可达(房主握手已到达),但客户端发出 EndpointCatalog + 握手后房主完全静默——没有 HandshakeAck、没有任何 typed 消息,最终房主的原始加入计时器以 LobbyJoinTimeout 断开。
对照:0.5.13 上同一路径是通的
2026-08-18 我们用同样的集成代码、同样的中继架构做过一次完整 E2E(macOS 房主 + Android 客户端,双端 RitsuLib v0.5.13):sidecar 握手交换后立即出现双向 typed 流量(大数 opcode),加入成功,relay_success。0.5.13 与 0.5.18 的日志差异仅在:0.5.18 客户端额外发出 opcode=23(EndpointCatalog)且协商就此停滞。
结合 0.5.14 的变更说明(routed sidecar endpoints、typed 消息优先走 confirmed routed endpoints、host relay 路径改用传输层认证身份),我们猜测 typed 投递现在依赖路由端点协商完成,而该协商在我们的中继场景中未完成。
想请教的问题
- 第三方 ENet 中继(对我们而言是透明的原始 UDP 转发)是否属于 0.5.14+ routed endpoints 的支持场景?host 对客户端
EndpointCatalog 完全无响应,更像协商在某一步被静默拒绝——如果是已知边界,能否在文档中标出?
- 是否存在(或计划提供)公开的降级开关,让 typed 消息在 routed endpoint 未确认时回退 legacy 投递?0.5.14 说明中提到 "legacy delivery is automatically retained for peers or payloads that can't use the new path",但在我们的场景里看起来没有触发回退。
建议(feature request):把共存所需的最小事实文档化为公开契约
作为依赖方,我们每次 RitsuLib 更新都要重新逆向确认以下事实,任何一项漂移都会以最不透明的方式(对玩家表现为 30 秒超时)失败。恳请考虑将它们文档化,甚至做版本化探测:
- 保留 ENet 通道分配(当前 48 = reliable / 49 = unreliable);
- 控制 opcode 保留段(ControlRangeStart 及已分配 offset);
- native trailer / 消息尾部的所有权约定(单 owner Write/Read);
- typed registry 的最小稳定语义(注册、投递语义、reachability hint 的行为契约)。
如果这些成为公开承诺,网络类 mod 就不必逐版本跟跑;我们也愿意把我们这边的联调场景(含开源的房间中继服务)贡献为参考测试用例。
可提供的材料
- 0.5.18 失败与 0.5.13 成功的完整双端日志(可再提供房主侧);
- 可复现的自建服务 + 中继部署步骤(全部开源);
- 我们对 typed API 的完整调用方式(module
sts2_lan_connect,约 190B 的 join request 载荷)。
我们的目标是与 RitsuLib 长期稳定共存,而不是要求冻结演进;如果上述猜测有误,也欢迎指正。
背景
我是 STS2 LAN Connect(联机大厅)的作者(创意工坊 3749766330,源码 STS2-Game-Lobby)。我们的 mod 让玩家通过自建大厅服务 + 房间级 UDP 中继(ENet 透明转发)联机。当房间内所有玩家都启用 RitsuLib 时,我们的协议容器会通过 RitsuLib 的公开 typed sidecar API(
RitsuLibSidecarTypedMessageRegistry)投递:module idsts2_lan_connect,message keyprotocol_v1,StableSync,Required=true。我们只使用公开 API,不依赖私有内部实现。首先感谢提供公开 typed registry——这正是我们选择它作为载体的原因。
现象(RitsuLib 0.5.18,游戏 v0.111.0 / 41cef1ea)
双端均启用 RitsuLib,客户端经由我们的 UDP 中继加入房主房间。精简时间线(客户端日志):
要点:ENet 连接与原版握手全程正常(双端模型哈希一致),ch=48 的 host→client 方向可达(房主握手已到达),但客户端发出
EndpointCatalog+ 握手后房主完全静默——没有 HandshakeAck、没有任何 typed 消息,最终房主的原始加入计时器以LobbyJoinTimeout断开。对照:0.5.13 上同一路径是通的
2026-08-18 我们用同样的集成代码、同样的中继架构做过一次完整 E2E(macOS 房主 + Android 客户端,双端 RitsuLib v0.5.13):sidecar 握手交换后立即出现双向 typed 流量(大数 opcode),加入成功,relay_success。0.5.13 与 0.5.18 的日志差异仅在:0.5.18 客户端额外发出 opcode=23(
EndpointCatalog)且协商就此停滞。结合 0.5.14 的变更说明(routed sidecar endpoints、typed 消息优先走 confirmed routed endpoints、host relay 路径改用传输层认证身份),我们猜测 typed 投递现在依赖路由端点协商完成,而该协商在我们的中继场景中未完成。
想请教的问题
EndpointCatalog完全无响应,更像协商在某一步被静默拒绝——如果是已知边界,能否在文档中标出?建议(feature request):把共存所需的最小事实文档化为公开契约
作为依赖方,我们每次 RitsuLib 更新都要重新逆向确认以下事实,任何一项漂移都会以最不透明的方式(对玩家表现为 30 秒超时)失败。恳请考虑将它们文档化,甚至做版本化探测:
如果这些成为公开承诺,网络类 mod 就不必逐版本跟跑;我们也愿意把我们这边的联调场景(含开源的房间中继服务)贡献为参考测试用例。
可提供的材料
sts2_lan_connect,约 190B 的 join request 载荷)。我们的目标是与 RitsuLib 长期稳定共存,而不是要求冻结演进;如果上述猜测有误,也欢迎指正。