Skip to content

UltiTools-API 6.4.0 更新说明 ​

6.4.0 让针对当前 Paper 编译的模块可以在较旧的受支持 Paper 版本上运行。模块加载时,框架会调整模块对服务器 API 的调用,并在启动时报告它无法调整的引用。6.4.0 还新增了绑定配置的异步定时任务和可选的崩溃安全 YAML 写入,并包含 6.3.2 之后的修复。

面向模块作者的完整清单见 COMPATIBILITY.md,发布页见 GitHub 上的 v6.4.0。

五个模块在 Minecraft 1.21 以下需要 6.4.0

UltiLogin、UltiMail、UltiKits、UltiRemoteBag 和 UltiTrade 针对 Paper 1.21 编译,在较旧服务器上配合 UltiTools 6.3.x 会失败。在 Paper 1.19.2 build 163 至 1.20.x 上,它们需要 UltiTools 6.4.0 或更高版本,以及下表列出的模块版本。在 Paper 1.21 及以上,UltiTools 6.3.x 仍然可用。

重点:当前 Paper 的模块在旧服务器上运行 ​

  • 加载时调整。 模块类加载时,框架会调整编译时的服务器与运行时服务器之间调用形式不同的地方。第一类是同一个服务器 API 类型在某个版本是类、在另一个版本是接口,例如 InventoryView,它曾在旧服务器上引发 IncompatibleClassChangeError。每个调用的所有者、成员名和描述符保持不变,磁盘上的模块 JAR 不会被修改。
  • 不会做的事。 框架不会补上旧服务器缺失的 API,不会重命名事件,也不会隔离同一个类里的处理器。没有让运维关闭这项调整的开关。
  • 启动汇总。 每个模块会输出一行 INFO,说明被调整的类和调用点数量,数量为零时也会输出。
  • 链接审计。 主类加载之后、组件扫描之前,框架会为模块自身扫描包中、服务器无法解析且没有被调整覆盖的每个引用输出一条 WARNING,其中包含模块、类和方法。随模块打包的第三方库中的引用,每个顶级库包只输出一行 INFO 汇总。当某个 Bean 因缺少服务器类而被跳过时,日志会写出模块、Bean、缺失的类以及所有受影响的事件处理器(包括继承来的)。
  • 离线审计命令。 同样的审计可以在部署前对模块 JAR 运行,可重复使用 --own 指定模块自身的包根。只有模块自身包中的发现才会使命令返回非零退出码。

哪些模块需要什么 ​

模块在 Minecraft 1.21 以下是否需要 UltiTools-API 6.4.0说明
UltiLogin是:UltiLogin 2.1.0(已发布)在 Minecraft 1.21 及以上需要 UltiTools-API 6.3.1 或更高版本。在缺少某个登录保护所用事件的 Paper 版本上,坐骑保护改用旧的坐骑事件;拾取物品、打开告示牌和装备栏交换保护各自跳过,并在控制台警告一次;其余保护照常注册。变更:UltiLogin#85、#86。
UltiMail是:UltiMail 2.1.0(已发布)在 Minecraft 1.21 及以上,UltiTools-API 6.3.0 或更高版本仍可运行。变更:UltiMail#67。
UltiKits是:UltiKits 2.1.0(已发布)在 Minecraft 1.21 及以上,UltiTools-API 6.3.0 或更高版本仍可运行。变更:UltiKits#58。
UltiRemoteBag是:UltiRemoteBag 2.1.0(已发布)在 Minecraft 1.21 及以上没有变化(UltiTools-API 6.3.0 或更高版本)。变更:UltiRemoteBag#80。
UltiTrade是:UltiTrade 2.1.0(已发布)在 Minecraft 1.21 及以上,UltiTools-API 6.3.0 或更高版本仍可运行。在 Minecraft 1.19.2–1.19.3 上,已打开的交易窗口标题不会刷新。变更:UltiTrade#92、#93。

以上五个模块版本新增了启动检查:在 Minecraft 1.21 以下且 UltiTools 低于 6.4.0 时,模块会拒绝启动,并用中英文提示更新 UltiTools。Minecraft 1.21 及以上配合 UltiTools 6.3.x 不受影响。6.4.0-SNAPSHOT 按 6.4.0 处理。版本字符串无法解析时,模块会警告并继续。这五个模块版本均已先于 UltiTools-API 6.4.0 发布,可从各自的 GitHub 发布页(见上表链接)和 UltiCloud 模块目录获取。模块发布与本次发布相互独立;各模块的其他变更见其发布说明。

升级前准备 ​

  • 支持的服务器: Paper 1.19.2 build 163 及以上,直至 Paper 1.21.x。Spigot 不是受支持的目标。
  • UltiLogin:升级 UltiTools-API 6.4.0 之前,先把 UltiLogin 升级到 2.1.0。 UltiLogin 2.1.0 可在 UltiTools-API 6.3.1 及以上运行。UltiLogin 2.0.0 的 /panel 引用了 6.4.0 已删除的 SimpleHttpClient 和 UltiCloudRequests,在 6.4.0 上 /panel 会失败(/login 不受影响),2.0.0 没有过渡方案。
  • Minecraft 1.21 以下的服务器: 把 UltiTools-API 升级到 6.4.0,再升级上表中的模块版本。
  • 离线所有者的交易取消(UltiTrade 2.1.0): 取消交易时若找不到在线的所有者,其押金会被保存,并在其下次加入时发还。保存失败且没有可用的所有者位置时,物品交给最初的发起方,绝不会掉落在世界出生点。每次转交都会记录所有者、接收者和物品。
  • 自定义异步定时任务或 YAML 写入: 采用下面两项新功能之前请先阅读说明。

新增 ​

  • 绑定配置的异步 @Scheduled 任务。 现在可以对时间绑定到配置项的任务使用 async = true。触发器仍在主线程运行,只有方法体在触发后一个 tick 交给异步线程执行。/ul reload 会保持触发器的相位。执行较慢的任务体可能重叠,与字面量异步任务一致;异步代码不得使用非线程安全的 Bukkit API。现有注解签名以及同步和字面量异步任务的行为不变。(#535、#797)
  • CrashSafeYamlFiles。 可选 API,用于模块显式创建或编辑运维人员的 YAML 文件。读取方要么看到旧文件,要么看到完整的新文件,不会看到写了一半的文件。它要求本地 POSIX 文件系统上的普通文件,保留权限位、所有者和属主组,并拒绝读取之后已被改动的文件。不会自动迁移任何模块,常规配置加载不变。平台限制见 COMPATIBILITY.md。(#545、#798)
  • 敏感的远程控制台命令在本地记录中被隐藏。 当面板的远程控制台执行模块登记为敏感的命令(例如 UltiLogin 的 logadmin)时,其参数在 [Remote command] 回显行、被拦截行、拒绝记录和操作日志目标中显示为 ***;失败行只显示命令名。命令仍会带着参数被执行,其回复不变;未登记的命令按原样记录。与 6.3.1 和 6.3.2 相比,这是有意改变本地日志内容。见 COMPATIBILITY.md 的“Sensitive commands in the remote console's local records”。(#868)

修复 ​

  • 含有转义换行符的映射键的配置警告保持在一行日志内。被拒绝的具名配置迁移警告现在会说明为什么插入会改变服务器读取该键的方式。(#851)
  • onLoad 失败时会释放启动日志捕获。(#858)
  • 更新检查失败时会报告失败,模块之间简单名称冲突只报告一次,未声明键的警告设有数量上限。(#855)
  • 中文语言文件中的暂存读取原因键使用中文源文本。(#854)
  • 移除了未使用的 SQLite 连接池设置。(#850)
  • 发布工具在每次 gh 调用中都指明仓库,并按要求完成草稿。(#864)

变更 ​

  • 二进制兼容性检查改为与 6.3.2 比较。(#860)
  • 新增 CI 任务,针对固定的 Paper API 1.19.2 和 1.20.6 依赖图审计框架的链接情况。(#846)
  • UAT-CHECKLIST.md 的条目按该构建的 API 级别编写。(#856)

已知限制 ​

  • 诊断不等于恢复。 若某个 Bean 因缺少服务器类被跳过,它的事件处理器就会丢失。请把可选处理器放到所有 scanBasePackages 前缀之外,先确认类存在,再显式注册。做法见旧版服务器指南。
  • 继承或实现了“种类已变化”的 API,或使用了受影响的特殊调用的类,会被拒绝,而不会只调整一部分。
  • 逐引用的 WARNING 只适用于模块自身的组件扫描包。重定位到扫描包内的打包库,仍然是每个引用一条 WARNING。在 6.3.2 的扫描修复之前,扫描根还会匹配文本前缀相同的相邻包,因此可选处理器所在的包名不要以任何扫描根开头。
  • INFO 数量是启动时的快照,不预测之后才加载的类。
  • 崩溃安全 YAML 只覆盖单个文件,不提供多文件崩溃事务。硬崩溃后残留的暂存文件需要人工查看。非 POSIX 文件系统和带有 Java 可见 ACL 的文件会被拒绝。
  • 绑定配置的异步任务中已经在运行的方法体,可能在模块卸载之后才结束。
  • 块标量(|-)后紧跟空行时,不会追加新引入的默认键(#883)。运维人员编辑过的 YAML 文件中,若块标量(|-)后紧跟空行,框架不会追加新引入的默认键:文件保持不变,默认值在内存中生效,并有一条 WARN 指出该键,请手动添加。行为与 6.3.2 相同,并非 6.4.0 的回归。
  • 6.3.x 中其余的已知限制(远程文件、云端客户端、面板重新绑定)见 COMPATIBILITY.md。

弃用 ​

6.4.0 弃用 8 个此前从未弃用的方法,标注 @Deprecated(since = "6.4.0", forRemoval = true),计划在 6.5.0 删除(按“一个 MINOR 版本”删除规则,这是最早允许删除的版本)。它们的行为不变。(#880)

  • DataStore#checkOwnership(File, Class)
  • DataStore#checkOwnership(UltiToolsPlugin, Class)
  • JsonStore#getOperator(UltiToolsPlugin, Class) 和 JsonStore#getOperator(File, Class)
  • MysqlDataStore#getOperator(UltiToolsPlugin, Class) 和 MysqlDataStore#getOperator(File, Class)
  • SQLiteDataStore#getOperator(UltiToolsPlugin, Class) 和 SQLiteDataStore#getOperator(File, Class)

替代用法:DataStore#getOperator(DataScope, Class),模块调用 UltiToolsPlugin#getDataOperator(Class)。

破坏性变更 ​

6.4.0 删除了 6.3.0 和 6.3.1 预告将在 6.4.0 移除的 72 项公开 API。它们在已发布版本中都带有 @Deprecated(forRemoval = true) 和 @removeIn 6.4.0,仍在使用的模块在编译时会按名称收到警告。针对 6.3.x 编译、并调用了已删除成员的模块,在 6.4.0 上会出现 NoSuchMethodError 或 NoClassDefFoundError。请针对 6.4.0 重新编译,并按 COMPATIBILITY.md 中“Removal list for 6.4.0”一节的迁移说明修改。(#880)

v1 WebSocket 与面板路径(48 项)。 协议 2.1.0 之前的 UltiCloud 路径已被移除。框架自带的 UltiCloud 会话(协议 2.1.0)已经承载全部面板请求,服主不会看到变化。

  • 数据与客户端类型:ApiResponse、TokenEntity、ServerEntityVO、UltiPanelWebSocketClient、ReconnectStrategy、ExponentialBackoffStrategy 及其 Builder(7 项)。
  • 内部管理器 CommandExecutionManager(3 项,含 CommandResult)、FileOperationManager(2 项)、ServerPropertiesManager(2 项)、LogStreamManager(9 项)、PlayerEventManager(8 项)、ServerMonitorManager(9 项)的 v1 入口、处理器和监听方法,以及构造器 UltiPanelLogTransmitter(UltiPanelWebSocketClient, String)(1 项)。CommandExecutionManager#execute(String, String, Executor, CommandResultSink) 替代 executeCommand(JsonObject),其余没有替代。
  • 登录与令牌辅助方法(7 项):CloudAuthManager#login(Runnable, Consumer, Runnable, Consumer, Consumer)(改用 login(DeviceLoginListener))、CloudAuthManager.CloudStatus#getUserName() 和 #getExpirationDate()(改用 getServerName() 或 getServerId())、HttpRequestUtils#registerServer、#updateServer、#getServerByUUID,以及 PluginInitiationUtils#startTokenRefreshScheduler()。

旧配置解析器(6 项)。 @ConfigEntry(parser = ...)、Parser、ObjectConfigSerializer、ConfigParser、DefaultConfigParser、StringHashMapParser。删除 parser = ...,并在扫描包内注册带 @ConfigConverterFor(T.class) 的 ConfigConverter<T>。DefaultConfigParser 和 StringHashMapParser 的声明直接删除即可,内置转换已覆盖这些类型。见 COMPATIBILITY.md 的“Migrating legacy parsers to converters”一节。

HTTP 客户端(7 项)。 SimpleHttpClient(含 Response),改用 HttpURLConnection 或自选的 HTTP 客户端;UltiCloudRequests(含 get、post、Outcome、Result),改用 CloudPlayerLinks(通过 UltiTools#getCloudPlayerLinks() 获取)。

其他(11 项)。

  • DataStore#getOperator(UltiToolsPlugin, Class) 和 #getOperator(File, Class)(2 项):改用 UltiToolsPlugin#getDataOperator(Class)。自定义存储重写 getOperatorUnchecked(DataScope, Class)。
  • TransactionManager#getConnection()、#setIsolationLevel(int)、#setReadOnly(boolean)(3 项):改为面向 JdbcTransactionManager 编程。
  • 四个简短的 SimpleTempListener 构造器(4 项):改用 TempListener.common(Class) 或四参数构造器。
  • PluginDependencyResolver.PluginNode#getAllDependencies(Set)(1 项):改用 getAllDependencies(Set, Map)。
  • AnnotationUtils#findAnnotation(Class, Class)(1 项):改用 MergedAnnotationResolver.find(Class, Class)。

行为说明:

  • 未设置 DataScope 时,UltiToolsPlugin#getDataOperator 和 UltiToolsAPI.getDataOperator 不再回退到已删除的重载,而是以 ENTITY_NOT_OWNED 拒绝。正常的模块加载总会设置该范围。
  • TransactionInterceptor 和 TransactionAwareDataSource 按 JdbcTransactionManager 或 JsonTransactionManager 分派。其他事务管理器会得到与已删除默认方法相同的 UnsupportedOperationException。
  • UltiPanelLogTransmitter 的批量、重放和间隔设置方法现在是空操作,或只保存数值。

二进制兼容性检查:japicmp 基线仍为已发布的 6.3.2。每个被删除的符号都有各自的 <exclude> 条目(没有整包排除),弃用登记表(compatibility/DEPRECATIONS.md)把这 72 项都标为 6.4.0 REMOVED,因此没有任何条目仍被预告为 6.4.0 删除。内部类 LegacyParserAdapter 另有一条排除,共 73 条具名排除。在 6.4.0 定版构建上,japicmp 0.26.5 将 6.4.0 与 6.3.2 比较,判定为 semver MINOR,除这些具名排除外没有二进制不兼容变更。6.4.0 新增的弃用不属于 japicmp 变更。

贡献者

基于 MIT 许可发布