正版离线共存

正版离线共存

一款可以在登录阶段安全验证离线模式服务器上的高级账户,且不会将玩家的访问令牌发送到服务器的模组。

TrueUUID

English | 简体中文

TrueUUID 是一个用于离线模式服务器的 Minecraft 身份验证模组。它在登录过程中安全地验证正版账号,同时将每位玩家的访问令牌保留在各自的客户端上。

它还支持配置的 Yggdrasil/authlib-injector 皮肤站账号。当前已测试和计划中的目标状态维护在 目标矩阵 中。

客户端和服务器都必须安装此模组。服务器必须以以下配置运行:

online-mode=false

特性

  • 保护隐私的身份验证:玩家的访问令牌仅在客户端本地使用。
  • 在离线模式服务器上支持正版/Yggdrasil UUID。
  • 验证成功后更正用户名的大小写。
  • 登录时注入签名的皮肤纹理。
  • 加入后刷新玩家信息,有助于皮肤正确更新。
  • 为正版、皮肤站和离线回退状态提供清晰的加入反馈。
  • 通过 Minecraft 语言文件实现本地化 UI 文本,每个客户端以其选择的语言查看消息。
  • 支持离线玩家数据到已验证玩家数据的迁移,包含确认和备份。
  • 防止已验证玩家以同名在离线模式下重新加入。

为何开发此模组

离线模式服务器通常无法信任玩家 UUID。TrueUUID 在保持服务器处于离线模式的同时,提高了身份完整性。

已验证的玩家可以保留其官方的 Mojang 或 Yggdrasil UUID 及皮肤数据,而服务器永远不会看到他们的访问令牌。

这对于整合包、局域网风格的服务器、私人离线模式社区,以及那些希望在不直接启用 Mojang 在线模式的情况下获得更好身份一致性的服务器非常有用。

工作原理

  1. 服务器以离线模式运行。
  2. 登录期间,服务器发送一个带有随机数(nonce)的自定义登录查询。
  3. 安装了模组的客户端接收查询,并使用玩家的配置文件、令牌和随机数在本地调用 joinServer。令牌从不离开客户端。
  4. 客户端回复身份验证结果和所选的身份验证源。
  5. 服务器通过 Mojang 会话服务器或支持的 Yggdrasil hasJoined 端点验证随机数。
  6. 如果验证成功:
    • 待处理的登录配置文件将被替换为已验证的 UUID。
    • 更正用户名的大小写。
    • 注入签名的皮肤纹理属性。
    • 记录身份验证源。
    • 加入后刷新玩家信息。
  7. 如果验证失败或超时:
    • 行为由配置文件控制。
    • 可以阻止已知的已验证玩家名回退到离线模式。
    • 如果配置允许,未知玩家名可能仍被允许使用离线回退。

离线数据迁移

TrueUUID 为那些过去以离线方式游玩、之后改用同名的正版或皮肤站账号的玩家提供了一种更安全的迁移流程。

当已验证的登录检测到匹配的离线 UUID 数据时,玩家将看到一个确认屏幕。只有在确认后才会进行迁移。

迁移前,TrueUUID 会备份旧的离线数据和任何现有的目标已验证 UUID 数据。

支持的迁移目标包括:

  • 原版 playerdata
  • 原版 playerdata_old
  • 进度(Advancements)
  • 统计(Stats)
  • Cosmetic Armor .cosarmor 数据
  • Open Parties and Claims
  • FTB Chunks
  • FTB Essentials
  • FTB Teams
  • FTB Quests
  • FTB Ranks
  • CustomNPCs 玩家数据

要求

当前经过运行时验证的目标:

  • Minecraft: 1.20.1
  • 加载器:Forge
  • Java: 17

不要从源代码目录或构建成功推断支持情况。请参阅 目标矩阵 以了解每个适配器的确切状态。

客户端和服务器都必须安装 TrueUUID。

安装

服务器:

  1. 在 server.properties 中设置 online-mode=false。
  2. 将匹配的 TrueUUID jar 文件放入服务器的 mods 文件夹。

客户端:

  1. 将匹配的 TrueUUID jar 文件放入客户端的 mods 文件夹。

如果客户端未安装此模组,服务器将不会收到预期的登录查询响应。根据配置,玩家可能会被踢出或允许回退到离线模式。

配置

首次运行后,将在以下位置生成配置文件:

config/trueuuid-common.toml

重要选项:

auth.timeoutMs = 30000

登录阶段的等待时间(毫秒)。

auth.allowOfflineOnTimeout = false

false: 超时时踢出玩家。

true: 超时时允许离线回退。

auth.allowOfflineOnFailure = true

true: 允许在验证普通失败时进行离线回退。

false: 验证失败时断开连接。

auth.knownPremiumDenyOffline = true

如果某个玩家名已被验证为正版或 Yggdrasil,则拒绝该名称后续的离线回退。

auth.allowOfflineForUnknownOnly = true

仅允许从未被验证过的玩家名进行离线回退。

auth.recentIpGrace.enabled = true auth.recentIpGrace.ttlSeconds = 10

允许已验证玩家断开连接后,从同一 IP 短时间重新连接。当客户端明确拒绝身份验证或作为离线登录时,此宽限期不适用。

auth.showJoinFeedback = true

显示关于正版、皮肤站、离线回退和单人游戏状态的加入反馈聊天消息。设置为 false 以将其静音,而不改变身份验证或皮肤刷新行为。

auth.showJoinTitle = false

额外在加入时显示全屏标题/副标题。默认关闭,因为下面持久的账户状态覆盖层已经报告了相同的状态,而不会中断屏幕。设置为 true 以恢复旧的标题行为。

auth.showAccountOverlay = true

在 TrueUUID 握手后显示一个小的客户端徽章:绿色 Premium 或红色 Offline,以纯角落文本形式绘制,无背景。它是客户端局部的,仅在已启用 TrueUUID 的服务器响应后出现。

默认的反馈和断开连接消息以 Minecraft 翻译键形式发送,并由玩家客户端的语言文件(en_us / zh_cn)渲染。如果您之前生成过自定义双语字符串的配置文件,请将这些消息值改回 trueuuid.* 键,或重新生成配置文件以使用客户端本地化。

/trueuuid cleanupuuid <name>

管理员命令,权限等级 4。它备份并删除某个玩家名的重复离线 UUID 数据,而不影响已验证的 UUID 数据。

/trueuuid migrateuuid <name>

管理员命令,权限等级 4。它批准继承同名的离线 UUID 数据,将其迁移到已验证的 Mojang/Yggdrasil UUID,并进行备份。

auth.yggdrasil.apiRootWhitelist = []

Yggdrasil/authlib-injector hasJoined 主机的白名单。空列表拒绝所有客户端报告的端点,并保持 Mojang 作为安全默认值。添加确切的主机,如 "littleskin.cn",或显式通配符,如 "*.example.com"。自定义端点必须通过 HTTPS/443、路径、DNS/IP、响应大小、超时和无重定向检查。

账户状态徽章的位置是可配置的:

auth.overlayCorner = "bottom_right" auth.overlayOffsetX = 0 auth.overlayOffsetY = 0 auth.overlayScale = 1.25

overlayCorner 接受 top_left、top_right、bottom_left 或 bottom_right。默认是 bottom_right,因为原版将状态效果和进度提示放在右上角,聊天框在左下角,而其他模组通常占据左上角。偏移量将徽章移动指定的像素数(正值 = 向右/向下),以防止与另一个模组的 HUD 冲突。overlayScale 调整锁图标和标签的大小;整数(1.0、2.0)可保持 Minecraft 位图字体完美清晰,中间值会稍显柔和。

这些选项在所有支持的目标上行为相同。

附加 API

TrueUUID 公开了一个小型服务器端 API(cn.alini.trueuuid.api),以便其他模组可以根据在线玩家是已验证为正版还是通过离线回退来进行分支处理——例如,将离线玩家传送至不同的出生点。

AccountStatus 是以下之一:PREMIUM_VERIFIED、ONLINE_MODE、OFFLINE_FALLBACK 或 UNKNOWN(附带 isPremium() / isOffline() 辅助方法)。

在玩家在线时随时查询其状态:

import cn.alini.trueuuid.api.TrueuuidApi;
import cn.alini.trueuuid.api.AccountStatus;

AccountStatus status = TrueuuidApi.getStatus(serverPlayer);
if (status.isOffline()) {
    // 例如,限制权限,或传送至仅限离线的世界
}

或者在玩家加入且状态已知的那一刻,在服务器线程上注册一个回调(在模组设置过程中注册一次):

TrueuuidApi.registerLoginCallback((player, status) -> {
    if (status.isOffline()) {
        // 离线账户首次加入的出生点处理
    }
});

此外还可使用:TrueuuidApi.isKnownPremiumName(name) 和 TrueuuidApi.getPremiumUuid(name) 来访问持久的已验证名称注册表。

兼容性说明

  • 代理端:Mojang 的 hasJoined IP 参数是可选的。当真实客户端 IP 被代理隐藏时,验证仍然可以工作。
  • 皮肤:TrueUUID 在登录期间注入签名的皮肤属性,并在加入后刷新玩家信息。如果客户端仍然显示过时的皮肤,重新加入或清除皮肤缓存可能会有所帮助。
  • 离线回退:离线回退是可配置的。在推荐的设置中,先前已验证的名称不能被离线客户端重复使用。
  • 注册表:TrueUUID 将已知的已验证名称存储在 trueuuid-registry.json 中。如果此文件被清除,服务器将忘记以前的正版/Yggdrasil 绑定。

构建

Windows:

.\gradlew.bat build

macOS/Linux:

./gradlew build

每个平台的构建都会将其特定目标的构件写入各自 platform/<加载器>-<minecraft-版本>/build/libs/ 目录。Forge 1.20.1 是经过运行时验证的目标;有关确切目标状态和发布模型,请参阅 目标矩阵。

隐私

玩家的访问令牌永远不会发送到服务器。

客户端在本地使用令牌来调用 joinServer。服务器仅接收身份验证结果,并通过 Mojang 会话服务器或受支持的 Yggdrasil 端点验证随机数。

许可证

GNU LGPL 3.0

鸣谢

  • Mojang authlib 和会话 API
  • Sponge Mixin
  • ForgeGradle
  • NeoForge / ModDevGradle

由 @YuWan-030、@wish131400 和 @F1xGOD 维护。