Skip to content

[Question]: outpre 模式与 Ambassador协议层冲突,Forge 客户端无法登入;切换 backend 模式可用 #22

@sipo610

Description

@sipo610

你的目标

希望 outpre 增加一条 LOGIN-state 桥接路径,专门用于 Forge 玩家或所有需要 LOGIN-state 协商的客户端。即:

  • 不发 ServerLoginSuccessPacket,客户端保持 LOGIN state
  • 在 LOGIN state 下转发 ModList 与 Channels 协商插件包(LoginPluginRequest 与 LoginPluginResponse)到 outpre-auth 后端
  • 协商完成后,outpre-auth 那边发出的 LoginSuccess 经 Ambassador 的 OutboundSuccessHolder 放行
  • 玩家进入 PLAY,outpre 后续逻辑(认证、onVerified、connectVerifiedPlayerToTarget)继续

当前环境

  • Velocity 3.4.0-566(也试过 3.5.0-SNAPSHOT-594)
  • HyperZoneLogin 26.4.6-RC-29a32a89
  • Ambassador 1.5.3-beta(含本地 instanceof 修复)
  • Forge 1.20.1(47.4.0)
  • 客户端 mod 数约 200个

插件版本与下载渠道

HyperZoneLogin-26.4.6-RC-29a32a89-all

服务器插件列表

velocity:
Ambassador-Velocity-1.5.3-beta-all
HyperZoneLogin 26.4.6-RC-29a32a89
CMIV-1.0.2.3

Mohist:
YukiNoaAPI-3.0.1
vault-1.6
ProtocolLib
item-nbt-api-plugin-2.15.7
CMILib1.5.9.3
LagFixer
Banit-1.2.1
PlayerTitle-5.0.0-beta.3
LuckPerms-Bukkit-5.5.42
CMI-9.8.6.6
SuperLobbyDeluxe-4.7.7-shaded
GeneralFix-1.1.7

具体问题

背景

在 Velocity 上同时运行 HyperZoneLogin 26.4.6-RC-29a32a89 与 Ambassador 1.5.3-beta 时,Forge 1.20.1 客户端无法完成登入。outpre 模式启用,outpre-auth 后端是 Forge 1.20.1 服务器。

现象

服务端日志(outpre 模式下):

[INFO] <player> entered outpre pre-registration flow
[INFO] OutPreBackendBridge has connected
[INFO] <player> has disconnected
[INFO] OutPreBackendBridge has disconnected
[INFO] 条目 mojang: 玩家 <player> 认证成功

服务端视角认证流程是成功的,没有 ERROR。

客户端日志在等约 50 秒后断开:

[Netty Client IO] [NetworkRegistry]: Channels [touhou_little_maid:network, ..., twilightforest:channel] rejected vanilla connections

客户端认为收到的是 vanilla 服务器响应,所以拒绝连接。

根因分析

经过对 outpre 源码、Ambassador 源码、Forge 协议三方对照,这是协议层面的设计冲突。

Forge 协议要求的握手顺序(Ambassador 实现)

Client 发握手包(含 FML marker) 给 Server
Client 收到 ModList 请求          在 LOGIN state
Client 回 ModList                 在 LOGIN state
Client 收到 Channels 协商          在 LOGIN state
Client 收到 ServerLoginSuccess     ModList 协商通过后才发
Client 进入 PLAY state

Ambassador 在客户端 pipeline 装了 OutboundSuccessHolder(velocity/client/OutboundSuccessHolder.java),作用是截留 ServerLoginSuccessPacket,直到 Forge ModList 协商完毕才放行。

outpre 的设计顺序(OutPreAuthSessionHandler)

OutPreAuthSessionHandler.kt 第 144 至 148 行:

val success = ServerLoginSuccessPacket()
mcConnection.write(success)
loginState = State.SUCCESS_SENT

outpre 的核心是先把客户端推到 PLAY 或 CONFIG state,然后桥接 PLAY/CONFIG state 包到 outpre-auth。

物理冲突

  • Ambassador 期望客户端停留在 LOGIN state 完成 ModList 协商,LoginSuccess 被 OutboundSuccessHolder 拦下;
  • outpre 期望立刻发 LoginSuccess 把客户端推到 PLAY 或 CONFIG state,才能启动 Bridge SessionHandler;
  • 同装时 outpre 写出的 LoginSuccess 被 Ambassador 拦截,客户端永远停在 LOGIN state 等 ModList,50 秒后超时断开。

OutPreClientBridgeSessionHandler 完全建立在 PLAY 或 CONFIG state 之上(StateRegistry.PLAY 与 StateRegistry.CONFIG 分支),没有 LOGIN state 桥接路径。

已尝试的修复(均不成立)

  1. 改 Ambassador 让 OutPreBackendBridge 走 instanceof 放行:编译通过、ClassCast 不再抛,但 backend 不再发 FML marker、不接管 ModList 协商,客户端协议拒绝。
  2. 加 ServerConnection 接口 instanceof 走 marker:marker 发出去了,但 Ambassador 的 ForgeLoginWrapperHandler 和 VelocityForgeBackendConnectionPhase 强依赖 VelocityServerConnection.getPhase() 和 setConnectionPhase,OutPreBackendBridge 没实现这些方法。
  3. 让 Forge 玩家跳过 outpre:会破坏 outpre 对 Forge 玩家的认证。

你已经看过哪些文档

全部看过

其他补充

已验证可用的临时方案

切换到 backend 模式(作者在 config-comments 里写的退路:推荐 outpre 模式,若有问题请使用 backend 模式)。

具体步骤(零代码改动):

  1. core.conf 把 v-server.mode 从 outpre 改为 backend
  2. core.conf 设置 v-server.backend.fallback-auth-server 为一个 Velocity 注册的 Forge 认证服服务器名(比如 verify)
  3. velocity.toml 的 [servers] 段加一行注册这个服务器,比如 verify = "127.0.0.1:25581"
  4. velocity.toml 的 try 列表不要包含这个 verify 服务器

为什么有效:backend 模式走 Velocity 标准 PlayerChooseInitialServerEvent + createConnectionRequest 流程,不在 LOGIN state 做任何 hack。Ambassador 完整接管 Forge ModList 协商,客户端正常进入 verify 服后再走 yggdrasil 认证。验证通过后 BackendAuthHoldListener.connectVerifiedPlayerToTarget 跨服到 post-auth-default-server。

实测日志线索:

Using backend auth hold server 'verify'
[server connection] HZL... -> verify has connected
条目 mojang: 玩家 <player> 认证成功
玩家 <player> 通过 Yggdrasil 验证,Entry: mojang

代价:玩家会先进 verify 服,再被自动跳走,不像 outpre 那样隐形过渡。但功能完整、Forge 协议兼容、Ambassador 跨服转发正常。

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions